diff --git a/.azure/pipelines/ci-official.yml b/.azure/pipelines/ci-official.yml new file mode 100644 index 0000000000..e23c1fa545 --- /dev/null +++ b/.azure/pipelines/ci-official.yml @@ -0,0 +1,225 @@ +trigger: + branches: + include: + - master + - release/* + exclude: + - release/2.0 + +phases: +- phase: Windows + queue: + name: DotNetCore-Windows + timeoutInMinutes: 120 + matrix: + Release: + BuildConfiguration: Release + variables: + CI: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + + # This variable is required by MicroBuildSigningPlugin to determine permissions for codesigning. + TeamName: AspNetCore + + # SignType = { test, real } + # This is prefixed underscore because variables automatically become environment variables (and therefore MSBuild properties), + # and this one was causing issues in MSBuild projects which use the $(SignType) MSbuild prop. + _SignType: real + + steps: + - task: NodeTool@0 + displayName: Install Node 10.x + inputs: + versionSpec: 10.x + - task: MicroBuildSigningPlugin@1 + displayName: Install MicroBuild plugin + condition: and(succeeded(), in(variables['_SignType'], 'test', 'real')) + inputs: + signType: $(_SignType) + zipSources: false + # TODO: configure build.cmd to build both x64 and x86 in one invocation + - script: build.cmd -ci /p:SkipTests=true /p:Configuration=$(BuildConfiguration) /p:BuildNumber=$(Build.BuildNumber) /t:Build /t:BuildSharedFx /p:SharedFxRID=win-x64 /t:BuildFallbackArchive + displayName: Build NuGet packages and win-x64 runtime + - script: build.cmd -ci /p:SkipTests=true /p:Configuration=$(BuildConfiguration) /p:BuildNumber=$(Build.BuildNumber) /t:BuildSharedFx /p:SharedFxRID=win-x86 + displayName: Build win-x86 runtime + - powershell: > + src/Installers/Windows/clone_and_build_ancm.ps1 + -GitCredential '$(dn-bot-devdiv-build-rw-code-rw)' + -Config $(BuildConfiguration) + -BuildNumber $(Build.BuildNumber) + -SignType $(_SignType) + displayName: Build ANCM installers + # TODO: configure harvesting to run as a part of build.cmd + - powershell: > + src/Installers/Windows/build.ps1 + -x64 artifacts/runtime/aspnetcore-runtime-internal-3.0.0-alpha1-$(Build.BuildNumber)-win-x64.zip + -x86 artifacts/runtime/aspnetcore-runtime-internal-3.0.0-alpha1-$(Build.BuildNumber)-win-x86.zip + -Config $(BuildConfiguration) + -BuildNumber $(Build.BuildNumber) + -SignType $(_SignType) + displayName: Build Windows installers + - task: PublishTestResults@2 + displayName: Publish test results + condition: always() + inputs: + testRunner: vstest + testResultsFiles: 'artifacts/logs/**/*.trx' + - task: PublishBuildArtifacts@1 + displayName: Upload artifacts + condition: eq(variables['system.pullrequest.isfork'], false) + inputs: + pathtoPublish: ./artifacts/ + artifactName: artifacts-Windows-Release + artifactType: Container + # Detect OSS Components in use in the product. Only needs to run on one OS in the matrix. + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: 'Component Detection' + inputs: + # This funky GUID represents the product "ASP.NET and EF Core" + governanceProduct: 'c641993b-8380-e811-80c3-0004ffb4789e' + snapshotForceEnabled: true + - task: MicroBuildCleanup@1 + displayName: Cleanup MicroBuild tasks + condition: always() + +- phase: macOS + dependsOn: Windows + queue: + name: Hosted macOS Preview + matrix: + Release: + BuildConfiguration: Release + variables: + CI: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download artifacts + inputs: + artifactName: artifacts-Windows-Release + downloadPath: $(Build.SourcesDirectory)/.deps + itemPattern: '**/*.nupkg' + # Workaround https://github.com/Microsoft/vsts-tasks/issues/6739 + - task: CopyFiles@2 + displayName: Copy package assets to correct folder + inputs: + sourceFolder: $(Build.SourcesDirectory)/.deps/artifacts-Windows-Release + targetFolder: $(Build.SourcesDirectory)/.deps + - script: > + ./build.sh + --ci + /t:Prepare + /t:Restore + /t:GeneratePropsFiles + /t:BuildSharedFx + /p:SharedFxRID=osx-x64 + /p:BuildNumber=$(Build.BuildNumber) + displayName: Build osx-x64 runtime + - task: PublishTestResults@2 + displayName: Publish test results + condition: always() + inputs: + testRunner: vstest + testResultsFiles: 'artifacts/logs/**/*.trx' + - task: PublishBuildArtifacts@1 + displayName: Upload artifacts + condition: eq(variables['system.pullrequest.isfork'], false) + inputs: + pathtoPublish: ./artifacts/ + artifactName: artifacts-macOS-Release + artifactType: Container + +- phase: Linux + dependsOn: + - Windows + - macOS + queue: + name: DotNetCore-Linux + matrix: + Release: + BuildConfiguration: Release + variables: + CI: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download artifacts + inputs: + artifactName: artifacts-Windows-Release + downloadPath: $(Build.SourcesDirectory)/.deps + itemPattern: '**/*.nupkg' + - task: DownloadBuildArtifacts@0 + displayName: Download Windows artifacts + inputs: + artifactName: artifacts-Windows-Release + downloadPath: $(Build.SourcesDirectory)/.r + itemPattern: '**/aspnetcore-runtime-*' + - task: DownloadBuildArtifacts@0 + displayName: Download macOS artifacts + inputs: + artifactName: artifacts-macOS-Release + downloadPath: $(Build.SourcesDirectory)/.r + itemPattern: '**/aspnetcore-runtime-*' + # Workaround https://github.com/Microsoft/vsts-tasks/issues/6739 + - task: CopyFiles@2 + displayName: Copy package assets to correct folder + inputs: + sourceFolder: $(Build.SourcesDirectory)/.deps/artifacts-Windows-Release + targetFolder: $(Build.SourcesDirectory)/.deps + # TODO: Make the cumulative zips build in their own step + - task: CopyFiles@2 + displayName: Copy package assets to correct folder + inputs: + sourceFolder: $(Build.SourcesDirectory)/.r/artifacts-Windows-Release + targetFolder: $(Build.SourcesDirectory)/artifacts/ + - task: CopyFiles@2 + displayName: Copy package assets to correct folder + inputs: + sourceFolder: $(Build.SourcesDirectory)/.r/artifacts-macOS-Release + targetFolder: $(Build.SourcesDirectory)/artifacts/ + - script: > + ./build.sh + --ci + /t:Prepare + /t:Restore + /t:GeneratePropsFiles + /t:BuildSharedFx + /p:SharedFxRID=linux-x64 + /p:BuildNumber=$(Build.BuildNumber) + displayName: Build linux-x64 runtime + - script: > + ./build.sh + --ci + /t:BuildSharedFx + /p:SharedFxRID=linux-arm + /p:BuildNumber=$(Build.BuildNumber) + displayName: Build linux-arm runtime + - script: > + ./dockerbuild.sh + alpine + /t:Prepare + /t:GeneratePropsFiles + /t:BuildSharedFx + /p:SharedFxRID=linux-musl-x64 + /p:BuildNumber=$(Build.BuildNumber) + displayName: Build linux-musl-x64 runtime + # TODO: configure installers to run in one build.sh invocation + - script: > + ./build.sh + --ci + /t:BuildInstallers + /p:_SharedFxSourceDir=$(Build.SourcesDirectory)/artifacts/runtime/ + displayName: Build linux installers + - task: PublishTestResults@2 + displayName: Publish test results + condition: always() + inputs: + testRunner: vstest + testResultsFiles: 'artifacts/logs/**/*.trx' + - task: PublishBuildArtifacts@1 + displayName: Upload artifacts + condition: eq(variables['system.pullrequest.isfork'], false) + inputs: + pathtoPublish: ./artifacts/ + artifactName: artifacts-Linux-Release + artifactType: Container diff --git a/.azure/pipelines/e2e-tests.yml b/.azure/pipelines/e2e-tests.yml new file mode 100644 index 0000000000..fecf598d59 --- /dev/null +++ b/.azure/pipelines/e2e-tests.yml @@ -0,0 +1,134 @@ +trigger: none +phases: +- phase: Host_Windows + queue: + name: Hosted VS2017 + parallel: 8 + matrix: + Portable_Node8: + Test.RuntimeIdentifier: none + Node.Version: 8.x + Portable_Node10: + Test.RuntimeIdentifier: none + Node.Version: 10.x + SelfContainedWindows_Node8: + Test.RuntimeIdentifier: win-x64 + Node.Version: 8.x + SelfContainedWindows_Node10: + Test.RuntimeIdentifier: win-x64 + Node.Version: 10.x + SelfContainedLinux_Node8: + Test.RuntimeIdentifier: linux-x64 + Node.Version: 8.x + SelfContainedLinux_Node10: + Test.RuntimeIdentifier: linux-x64 + Node.Version: 10.x + SelfContainedMacOs_Node8: + Test.RuntimeIdentifier: osx-x64 + Node.Version: 8.x + SelfContainedMacOs_Node10: + Test.RuntimeIdentifier: osx-x64 + Node.Version: 10.x + steps: + - task: NodeTool@0 + displayName: Install Node $(Node.Version) + inputs: + versionSpec: $(Node.Version) + - powershell: | + test/Cli.FunctionalTests/run-tests.ps1 -ci -ProdConManifestUrl $env:PRODCONMANIFESTURL -TestRuntimeIdentifier $(Test.RuntimeIdentifier) -AdditionalRestoreSources $env:ADDITIONALRESTORESOURCES + condition: ne(variables['PB_SkipTests'], 'true') + displayName: Run E2E tests + - task: PublishTestResults@2 + displayName: Publish test results + condition: always() + inputs: + testRunner: vstest + testResultsFiles: 'artifacts/logs/**/*.trx' +- phase: Host_macOS + queue: + name: Hosted macOS + parallel: 8 + matrix: + Portable_Node8: + Test.RuntimeIdentifier: none + Node.Version: 8.x + Portable_Node10: + Test.RuntimeIdentifier: none + Node.Version: 10.x + SelfContainedWindows_Node8: + Test.RuntimeIdentifier: win-x64 + Node.Version: 8.x + SelfContainedWindows_Node10: + Test.RuntimeIdentifier: win-x64 + Node.Version: 10.x + SelfContainedLinux_Node8: + Test.RuntimeIdentifier: linux-x64 + Node.Version: 8.x + SelfContainedLinux_Node10: + Test.RuntimeIdentifier: linux-x64 + Node.Version: 10.x + SelfContainedMacOs_Node8: + Test.RuntimeIdentifier: osx-x64 + Node.Version: 8.x + SelfContainedMacOs_Node10: + Test.RuntimeIdentifier: osx-x64 + Node.Version: 10.x + steps: + - task: NodeTool@0 + displayName: Install Node $(Node.Version) + inputs: + versionSpec: $(Node.Version) + - powershell: | + test/Cli.FunctionalTests/run-tests.ps1 -ci -ProdConManifestUrl $env:PRODCONMANIFESTURL -TestRuntimeIdentifier $(Test.RuntimeIdentifier) -AdditionalRestoreSources $env:ADDITIONALRESTORESOURCES + condition: ne(variables['PB_SkipTests'], 'true') + displayName: Run E2E tests + - task: PublishTestResults@2 + displayName: Publish test results + condition: always() + inputs: + testRunner: vstest + testResultsFiles: 'artifacts/logs/**/*.trx' +- phase: Host_Linux + queue: + name: Hosted Linux Preview + parallel: 8 + matrix: + Portable_Node8: + Test.RuntimeIdentifier: none + Node.Version: 8.x + Portable_Node10: + Test.RuntimeIdentifier: none + Node.Version: 10.x + SelfContainedWindows_Node8: + Test.RuntimeIdentifier: win-x64 + Node.Version: 8.x + SelfContainedWindows_Node10: + Test.RuntimeIdentifier: win-x64 + Node.Version: 10.x + SelfContainedLinux_Node8: + Test.RuntimeIdentifier: linux-x64 + Node.Version: 8.x + SelfContainedLinux_Node10: + Test.RuntimeIdentifier: linux-x64 + Node.Version: 10.x + SelfContainedMacOs_Node8: + Test.RuntimeIdentifier: osx-x64 + Node.Version: 8.x + SelfContainedMacOs_Node10: + Test.RuntimeIdentifier: osx-x64 + Node.Version: 10.x + steps: + - task: NodeTool@0 + displayName: Install Node $(Node.Version) + inputs: + versionSpec: $(Node.Version) + - powershell: | + test/Cli.FunctionalTests/run-tests.ps1 -ci -ProdConManifestUrl $env:PRODCONMANIFESTURL -TestRuntimeIdentifier $(Test.RuntimeIdentifier) -AdditionalRestoreSources $env:ADDITIONALRESTORESOURCES + condition: ne(variables['PB_SkipTests'], 'true') + displayName: Run E2E tests + - task: PublishTestResults@2 + displayName: Publish test results + condition: always() + inputs: + testRunner: vstest + testResultsFiles: 'artifacts/logs/**/*.trx' diff --git a/.azure/pipelines/fast-pr-validation.yml b/.azure/pipelines/fast-pr-validation.yml new file mode 100644 index 0000000000..2126e161d9 --- /dev/null +++ b/.azure/pipelines/fast-pr-validation.yml @@ -0,0 +1,28 @@ +trigger: +- master +- release/* + +# See https://github.com/aspnet/BuildTools +resources: + repositories: + - repository: buildtools + type: github + endpoint: DotNet-Bot GitHub Connection + name: aspnet/BuildTools + ref: refs/heads/master + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools + parameters: + buildArgs: "/t:CheckUniverse" +- phase: DataProtection + queue: Hosted VS2017 + steps: + - script: src/DataProtection/build.cmd -ci + displayName: Run src/DataProtection/build.cmd + - task: PublishTestResults@2 + displayName: Publish test results + condition: always() + inputs: + testRunner: vstest + testResultsFiles: 'src/DataProtection/artifacts/logs/**/*.trx' diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..4eb7559fce --- /dev/null +++ b/.editorconfig @@ -0,0 +1,29 @@ +; EditorConfig to support per-solution formatting. +; Use the EditorConfig VS add-in to make this work. +; http://editorconfig.org/ + +; This is the default for the codeline. +root = true + +[*] +indent_style = space +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{cs}] +indent_size = 4 +dotnet_sort_system_directives_first = true:warning + +[*.{xml,config,*proj,nuspec,props,resx,targets,yml,tasks}] +indent_size = 2 + +[*.json] +indent_size = 2 + +[*.{ps1,psm1}] +indent_size = 4 + +[*.sh] +indent_size = 4 +end_of_line = lf diff --git a/.gitattributes b/.gitattributes index bdaa5ba982..ebc27b82d2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,50 +1,68 @@ -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto -*.jpg binary -*.png binary -*.gif binary +############################################################################### +# Make sh files under the build directory always have LF as line endings +############################################################################### +*.sh eol=lf -*.cs text=auto diff=csharp -*.vb text=auto -*.resx text=auto -*.c text=auto -*.cpp text=auto -*.cxx text=auto -*.h text=auto -*.hxx text=auto -*.py text=auto -*.rb text=auto -*.java text=auto -*.html text=auto -*.htm text=auto -*.css text=auto -*.scss text=auto -*.sass text=auto -*.less text=auto -*.js text=auto -*.lisp text=auto -*.clj text=auto -*.sql text=auto -*.php text=auto -*.lua text=auto -*.m text=auto -*.asm text=auto -*.erl text=auto -*.fs text=auto -*.fsx text=auto -*.hs text=auto +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp -*.csproj text=auto -*.vbproj text=auto -*.fsproj text=auto -*.dbproj text=auto -*.sln text=auto eol=crlf +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 331b644f16..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,45 +0,0 @@ -To address your issues more quickly, please open the issue in the most appropriate repository. - -If you're not sure exactly where to log the bug, please log the issue here and we will redirect it. - -ASP.NET Core: - - General issues: https://github.com/aspnet/Home (this repo) - - MVC and Razor Pages: https://github.com/aspnet/Mvc - - SignalR: https://github.com/aspnet/SignalR - - Kestrel HTTP Server: https://github.com/aspnet/KestrelHttpServer - - Docker: https://github.com/aspnet/aspnet-docker - - Documentation: https://github.com/aspnet/Docs - - Microsoft.NET.Sdk.Web: https://github.com/aspnet/websdk - - See a full list here: https://github.com/aspnet - - Note: Some repos do not have active issue trackers, so if you see such a warning, please log the issue here - -ASP.NET 4.x: - - ASP.NET MVC/Web API (not Core): https://github.com/aspnet/AspNetWebStack - - Katana: https://github.com/aspnet/AspNetKatana - -Entity Framework: - - Entity Framework Core: https://github.com/aspnet/EntityFrameworkCore - - Entity Framework 6: https://github.com/aspnet/EntityFramework6 - -Other common projects: - - .NET Core CLI and SDK: https://github.com/dotnet/core - - .NET Core runtime: https://github.com/dotnet/coreclr - - .NET Core libraries: https://github.com/dotnet/corefx - - NuGet: https://github.com/NuGet/home - - Visual Studio: https://developercommunity.visualstudio.com - - Visual Studio Code: https://github.com/microsoft/vscode - - Omnisharp (C# support for VS Code): https://github.com/omnisharp/omnisharp-vscode - -If you believe you have an issue that affects the security of the platform please do NOT create an issue and instead email your issue details to secure@microsoft.com. Your report may be eligible for our [bug bounty](https://technet.microsoft.com/en-us/mt764065.aspx). - ---- - -Tips for opening great bugs: - -1. Try enabling logging (in the most verbose level) and see if the details help you in fixing the issue you are seeing. Share the logs too if it helps in diagnosing the issue faster. More info: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging -2. If you are seeing an exception, include the full exceptions details (message and stack trace). More info: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling -3. Please try to include as much information as possible: - 1. Description of the problem: - 2. Steps to reproduce (preferrably a link to a GitHub repo with a repro project) - 3. The version of `Microsoft.AspNetCore.App` or `Microsoft.AspNetCore.All` - 4. The output of `dotnet --info` diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..825102492c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug report +about: Create a report about something that is not working +--- + +### Describe the bug +A clear and concise description of what the bug is. + +### To Reproduce +Steps to reproduce the behavior: +1. Using this version of ASP.NET Core '...' +2. Run this code '....' +3. With these arguments '....' +4. See error + +### Expected behavior +A clear and concise description of what you expected to happen. + +### Screenshots +If applicable, add screenshots to help explain your problem. + +### Additional context +Add any other context about the problem here. +Include the output of `dotnet --info` diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..3b4122bc71 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for this project +--- + +### Is your feature request related to a problem? Please describe. +A clear and concise description of what the problem is. +Example. I'm am trying to do [...] but [...] + +### Describe the solution you'd like +A clear and concise description of what you want to happen. + +### Describe alternatives you've considered +A clear and concise description of any alternative solutions or features you've considered. + +### Additional context +Add any other context or screenshots about the feature request here. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..c07fa37b2b --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,5 @@ +Summary of the changes (Less than 80 chars) + - Detail 1 + - Detail 2 + +Addresses #bugnumber (in this specific format) diff --git a/.gitignore b/.gitignore index ec80ffa907..ba949609e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,27 +1,26 @@ -[Oo]bj/ -[Bb]in/ -TestResults/ -.nuget/ +bin/ +obj/ .vs/ -_ReSharper.*/ -packages/ -artifacts/ -PublishProfiles/ -*.user *.suo -*.cache -*.docstates +*.user _ReSharper.* -nuget.exe -*net45.csproj -*k10.csproj -*.psess -*.vsp -*.pidb +*.DS_Store *.userprefs -*DS_Store -*.ncrunchsolution -*.*sdf -*.ipch -*.sln.ide -project.lock.json \ No newline at end of file +*.pidb +*.vspx +*.psess +*.binlog +*.log +artifacts/ +StyleCop.Cache +node_modules/ +*.snk +.nuget +.r +.w +.deps +msbuild.ProjectImports.zip +.env +scripts/tmp/ +.dotnet/ +.tools/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..6436140b01 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,176 @@ +[submodule "modules/AADIntegration"] + path = modules/AADIntegration + url = https://github.com/aspnet/AADIntegration.git + branch = master +[submodule "modules/Antiforgery"] + path = modules/Antiforgery + url = https://github.com/aspnet/Antiforgery.git + branch = master +[submodule "modules/AuthSamples"] + path = modules/AuthSamples + url = https://github.com/aspnet/AuthSamples.git + branch = master +[submodule "modules/AzureIntegration"] + path = modules/AzureIntegration + url = https://github.com/aspnet/AzureIntegration.git + branch = master +[submodule "modules/BasicMiddleware"] + path = modules/BasicMiddleware + url = https://github.com/aspnet/BasicMiddleware.git + branch = master +[submodule "modules/BrowserLink"] + path = modules/BrowserLink + url = https://github.com/aspnet/BrowserLink.git + branch = master +[submodule "modules/Caching"] + path = modules/Caching + url = https://github.com/aspnet/Caching.git + branch = master +[submodule "modules/Common"] + path = modules/Common + url = https://github.com/aspnet/Common.git + branch = master +[submodule "modules/Configuration"] + path = modules/Configuration + url = https://github.com/aspnet/Configuration.git + branch = master +[submodule "modules/CORS"] + path = modules/CORS + url = https://github.com/aspnet/CORS.git + branch = master +[submodule "modules/DependencyInjection"] + path = modules/DependencyInjection + url = https://github.com/aspnet/DependencyInjection.git + branch = master +[submodule "modules/Diagnostics"] + path = modules/Diagnostics + url = https://github.com/aspnet/Diagnostics.git + branch = master +[submodule "modules/DotNetTools"] + path = modules/DotNetTools + url = https://github.com/aspnet/DotNetTools.git + branch = master +[submodule "modules/EntityFrameworkCore"] + path = modules/EntityFrameworkCore + url = https://github.com/aspnet/EntityFrameworkCore.git + branch = master +[submodule "modules/EventNotification"] + path = modules/EventNotification + url = https://github.com/aspnet/EventNotification.git + branch = master +[submodule "modules/FileSystem"] + path = modules/FileSystem + url = https://github.com/aspnet/FileSystem.git + branch = master +[submodule "modules/Hosting"] + path = modules/Hosting + url = https://github.com/aspnet/Hosting.git + branch = master +[submodule "modules/HtmlAbstractions"] + path = modules/HtmlAbstractions + url = https://github.com/aspnet/HtmlAbstractions.git + branch = master +[submodule "modules/HttpAbstractions"] + path = modules/HttpAbstractions + url = https://github.com/aspnet/HttpAbstractions.git + branch = master +[submodule "modules/HttpClientFactory"] + path = modules/HttpClientFactory + url = https://github.com/aspnet/HttpClientFactory.git + branch = master +[submodule "modules/HttpSysServer"] + path = modules/HttpSysServer + url = https://github.com/aspnet/HttpSysServer.git + branch = master +[submodule "modules/Identity"] + path = modules/Identity + url = https://github.com/aspnet/Identity.git + branch = master +[submodule "modules/IISIntegration"] + path = modules/IISIntegration + url = https://github.com/aspnet/IISIntegration.git + branch = master +[submodule "modules/JavaScriptServices"] + path = modules/JavaScriptServices + url = https://github.com/aspnet/JavaScriptServices.git + branch = master +[submodule "modules/JsonPatch"] + path = modules/JsonPatch + url = https://github.com/aspnet/JsonPatch.git + branch = master +[submodule "modules/KestrelHttpServer"] + path = modules/KestrelHttpServer + url = https://github.com/aspnet/KestrelHttpServer.git + branch = master +[submodule "modules/Localization"] + path = modules/Localization + url = https://github.com/aspnet/Localization.git + branch = master +[submodule "modules/Logging"] + path = modules/Logging + url = https://github.com/aspnet/Logging.git + branch = master +[submodule "modules/MetaPackages"] + path = modules/MetaPackages + url = https://github.com/aspnet/MetaPackages.git + branch = master +[submodule "modules/Microsoft.Data.Sqlite"] + path = modules/Microsoft.Data.Sqlite + url = https://github.com/aspnet/Microsoft.Data.Sqlite.git + branch = master +[submodule "modules/MusicStore"] + path = modules/MusicStore + url = https://github.com/aspnet/MusicStore.git + branch = master +[submodule "modules/Mvc"] + path = modules/Mvc + url = https://github.com/aspnet/Mvc.git + branch = master +[submodule "modules/Options"] + path = modules/Options + url = https://github.com/aspnet/Options.git + branch = master +[submodule "modules/Razor"] + path = modules/Razor + url = https://github.com/aspnet/Razor.git + branch = master +[submodule "modules/ResponseCaching"] + path = modules/ResponseCaching + url = https://github.com/aspnet/ResponseCaching.git + branch = master +[submodule "modules/Routing"] + path = modules/Routing + url = https://github.com/aspnet/Routing.git + branch = master +[submodule "modules/Scaffolding"] + path = modules/Scaffolding + url = https://github.com/aspnet/Scaffolding.git + branch = master +[submodule "modules/Security"] + path = modules/Security + url = https://github.com/aspnet/Security.git + branch = master +[submodule "modules/ServerTests"] + path = modules/ServerTests + url = https://github.com/aspnet/ServerTests.git + branch = master +[submodule "modules/Session"] + path = modules/Session + url = https://github.com/aspnet/Session.git + branch = master +[submodule "modules/SignalR"] + path = modules/SignalR + url = https://github.com/aspnet/SignalR.git + branch = master +[submodule "modules/StaticFiles"] + path = modules/StaticFiles + url = https://github.com/aspnet/StaticFiles.git + branch = master +[submodule "modules/Templating"] + path = modules/Templating + url = https://github.com/aspnet/Templating.git + branch = master +[submodule "modules/WebSockets"] + path = modules/WebSockets + url = https://github.com/aspnet/WebSockets.git + branch = master diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..a869097c1c --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "ms-vscode.csharp", + "ms-vscode.PowerShell", + "EditorConfig.EditorConfig" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000..f967d60789 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "PowerShell", + "request": "launch", + "name": "ps: Interactive Session", + "cwd": "${workspaceRoot}" + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..89a3c7cca0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.trimTrailingWhitespace": true, + "files.associations": { + "*.*proj": "xml", + "*.props": "xml", + "*.targets": "xml", + "*.tasks": "xml" + } +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d0cae1018a..c0e07c6cc6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,28 +1,22 @@ # How to contribute -One of the easiest ways to contribute is to participate in discussions and discuss issues. You can also contribute by submitting pull requests with code changes. +One of the easiest ways to contribute is to participate in discussions on GitHub issues. You can also contribute by submitting pull requests with code changes. ## General feedback and discussions? -Please start a discussion on the [Home repo issue tracker](https://github.com/aspnet/Home/issues). +Please start a discussion on the [repo issue tracker](https://github.com/aspnet/AspNetCore/issues). ## Bugs and feature requests? For non-security related bugs please log a new issue in the appropriate GitHub repo. Here are some of the most common repos: -* [DependencyInjection](https://github.com/aspnet/DependencyInjection) * [Docs](https://github.com/aspnet/Docs) -* [EntityFramework](https://github.com/aspnet/EntityFramework) -* [Identity](https://github.com/aspnet/Identity) -* [MVC](https://github.com/aspnet/Mvc) -* [Razor](https://github.com/aspnet/Razor) -* [Templating](https://github.com/aspnet/templating) +* [Entity Framework Core](https://github.com/aspnet/EntityFrameworkCore) * [Tooling](https://github.com/aspnet/Tooling) -* [SignalR](https://github.com/aspnet/SignalR) +* [Extensions](https://github.com/aspnet/Extensions) Or browse the full list of repos in the [aspnet](https://github.com/aspnet/) organization. - ## Reporting security issues and bugs Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the [Security TechCenter](https://technet.microsoft.com/en-us/security/ff852094.aspx). @@ -34,53 +28,18 @@ Our team members also monitor several other discussion forums: * [Stack Overflow](https://stackoverflow.com/) with the [`asp.net-core`](https://stackoverflow.com/questions/tagged/asp.net-core), [`asp.net-core-mvc`](https://stackoverflow.com/questions/tagged/asp.net-core-mvc), or [`entity-framework-core`](https://stackoverflow.com/questions/tagged/entity-framework-core) tags. -## Filing issues -When filing issues, please use our [bug filing templates](https://github.com/aspnet/Home/wiki/Functional-bug-template). -The best way to get your bug fixed is to be as detailed as you can be about the problem. -Providing a minimal project with steps to reproduce the problem is ideal. -Here are questions you can answer before you file a bug to make sure you're not missing any important information. - -1. Did you read the [documentation](https://github.com/aspnet/home/wiki)? -2. Did you include the snippet of broken code in the issue? -3. What are the *EXACT* steps to reproduce this problem? -4. What package versions are you using (you can see these in the `.csproj` file)? -5. What operating system are you using? -6. What version of IIS are you using? - -GitHub supports [markdown](https://help.github.com/articles/github-flavored-markdown/), so when filing bugs make sure you check the formatting before clicking submit. - - ## Contributing code and content ### Identifying the scale If you would like to contribute to one of our repositories, first identify the scale of what you would like to contribute. If it is small (grammar/spelling or a bug fix) feel free to start working on a fix. If you are submitting a feature or substantial code contribution, please discuss it with the team and ensure it follows the product roadmap. You might also read these two blogs posts on contributing code: [Open Source Contribution Etiquette](http://tirania.org/blog/archive/2010/Dec-31.html) by Miguel de Icaza and [Don't "Push" Your Pull Requests](https://www.igvita.com/2011/12/19/dont-push-your-pull-requests/) by Ilya Grigorik. Note that all code submissions will be rigorously reviewed and tested by the ASP.NET and Entity Framework teams, and only those that meet an extremely high bar for both quality and design/roadmap appropriateness will be merged into the source. -### Obtaining the source code - -If you are an outside contributor, please fork the ASP.NET repository you would like to contribute to your account. See the GitHub documentation for [forking a repo](https://help.github.com/articles/fork-a-repo/) if you have any questions about this. - -### Building our Repositories - -As our repositories use the latest bits of our code, we have a custom build script to fetch and use them. Please go through [building our repositories from source](https://github.com/aspnet/Home/wiki/Building-from-source) to understand and fix any issues. - ### Submitting a pull request You will need to sign a [Contributor License Agreement](https://cla.dotnetfoundation.org/) when submitting your pull request. To complete the Contributor License Agreement (CLA), you will need to follow the instructions provided by the CLA bot when you send the pull request. This needs to only be done once for any .NET Foundation OSS project. -If you don't know what a pull request is read this article: https://help.github.com/articles/using-pull-requests. Make sure the respository can build and all tests pass. Familiarize yourself with the project workflow and our coding conventions. The coding, style, and general engineering guidelines are published on the [Engineering guidelines](https://github.com/aspnet/Home/wiki/Engineering-guidelines) page. +If you don't know what a pull request is read this article: https://help.github.com/articles/using-pull-requests. Make sure the respository can build and all tests pass. Familiarize yourself with the project workflow and our coding conventions. The coding, style, and general engineering guidelines are published on the [Engineering guidelines](https://github.com/aspnet/AspNetCore/wiki/Engineering-guidelines) page. -Pull requests should all be done to the **release/2.2** (for the next release) or **master** (for 3.0 work) branch. - -### Commit/Pull Request Format - -``` -Summary of the changes (Less than 80 chars) - - Detail 1 - - Detail 2 - -Addresses #bugnumber (in this specific format) -``` ### Tests @@ -91,7 +50,7 @@ Addresses #bugnumber (in this specific format) ### Feedback -Your pull request will now go through extensive checks by the subject matter experts on our team. Please be patient; we have hundreds of pull requests across all of our repositories. Update your pull request according to feedback until it is approved by one of the ASP.NET team members. After that, one of our team members will add the pull request to **release/2.2** or **master**. +Your pull request will now go through extensive checks by the subject matter experts on our team. Please be patient; we have hundreds of pull requests across all of our repositories. Update your pull request according to feedback until it is approved by one of the ASP.NET team members. After that, one of our team members may adjust the branch you merge into based on the expected release schedule. ## Code of conduct diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000000..531b5d8745 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,28 @@ + + + + + Microsoft ASP.NET Core + $(MSBuildThisFileDirectory) + https://github.com/aspnet/Universe + git + $(MSBuildThisFileDirectory)eng\AspNetCore.snk + true + true + + + + + + + $(RepositoryRoot)artifacts\ + $(ArtifactsDir)obj\ + $(ArtifactsDir)$(Configuration)\ + $(ArtifactsConfigurationDir)bin\ + $(ArtifactsConfigurationDir)packages\ + + + + + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000000..6bd26321ea --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,14 @@ + + + $(MicrosoftNETCoreApp20PackageVersion) + $(MicrosoftNETCoreApp21PackageVersion) + $(MicrosoftNETCoreApp22PackageVersion) + $(MicrosoftNETCoreApp30PackageVersion) + $(NETStandardLibrary20PackageVersion) + + 99.9 + + + + + diff --git a/Microsoft.AspNetCore.sln b/Microsoft.AspNetCore.sln new file mode 100644 index 0000000000..809b017e25 --- /dev/null +++ b/Microsoft.AspNetCore.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{EE2CAA71-82AA-41C0-AE87-5B4FB77D6CFE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedFx.UnitTests", "test\SharedFx.UnitTests\SharedFx.UnitTests.csproj", "{99CC38EC-902B-4B3F-AD33-177018110199}" +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(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {99CC38EC-902B-4B3F-AD33-177018110199}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Debug|x64.ActiveCfg = Debug|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Debug|x64.Build.0 = Debug|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Debug|x86.ActiveCfg = Debug|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Debug|x86.Build.0 = Debug|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Release|Any CPU.Build.0 = Release|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Release|x64.ActiveCfg = Release|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Release|x64.Build.0 = Release|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Release|x86.ActiveCfg = Release|Any CPU + {99CC38EC-902B-4B3F-AD33-177018110199}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {99CC38EC-902B-4B3F-AD33-177018110199} = {EE2CAA71-82AA-41C0-AE87-5B4FB77D6CFE} + EndGlobalSection +EndGlobal diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000000..cec9479a72 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/README.md b/README.md index 2bda91b8ce..1e8a4ef412 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,40 @@ - -# ASP.NET Core - -[app-metapackage-nuget]: https://nuget.org/packages/Microsoft.AspNetCore.All -[app-metapackage-nuget-badge]: http://img.shields.io/nuget/v/Microsoft.AspNetCore.All.svg?style=flat-square&label=aspnet@stable -[app-metapackage-myget]: https://dotnet.myget.org/feed/dotnet-core/package/nuget/Microsoft.AspNetCore.App -[app-metapackage-myget-badge]: http://img.shields.io/dotnet.myget/dotnet-core/v/Microsoft.AspNetCore.App.svg?style=flat-square&label=aspnet@preview - -[![][app-metapackage-nuget-badge]][app-metapackage-nuget] -[![][app-metapackage-myget-badge]][app-metapackage-myget] - -[![Join the chat at https://gitter.im/aspnet/Home](https://badges.gitter.im/aspnet/Home.svg)](https://gitter.im/aspnet/Home?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -This is the home page of the ASP.NET Core source code repositories and is intended for those contributing to ASP.NET Core or using bleeding edge nightly builds. - -ASP.NET Core is a new open-source and cross-platform framework for building modern cloud based internet connected applications, such as web apps, IoT apps and mobile backends. ASP.NET Core apps can run on .NET Core or on the full .NET Framework. It was architected to provide an optimized development framework for apps that are deployed to the cloud or run on-premises. It consists of modular components with minimal overhead, so you retain flexibility while constructing your solutions. You can develop and run your ASP.NET Core apps cross-platform on Windows, Mac and Linux. [Learn more about ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/). - -ASP.NET Core 1.1 is now available! See the [release notes](https://github.com/aspnet/Home/releases/tag/1.1.0) for further details. - -ASP.NET Core 2.0 is now available! See the [release notes](https://github.com/aspnet/Home/releases/tag/2.0.0) for further details and check our [releases](https://github.com/aspnet/home/releases) for the latest patch release. - -ASP.NET Core 2.1 is now available! See the [release notes](https://github.com/aspnet/Home/releases/tag/2.1.0) for further details and check our [releases](https://github.com/aspnet/Home/releases/) for the latest patch release. - -## Get Started - -Follow the [Getting Started](https://docs.microsoft.com/en-us/aspnet/core/getting-started) instructions in the [ASP.NET Core docs](https://docs.microsoft.com/en-us/aspnet/index). - -Also checkout the [.NET Homepage](https://www.microsoft.com/net) for released versions of .NET, getting started guides, and learning resources. - -## Daily builds - -If you want to use the latest daily build then you need to: - -- Obtain the latest [build of the .NET Core SDK](https://github.com/dotnet/cli#installers-and-binaries) -- Add a NuGet.Config to your app with the following content: - - ```xml - - - - - - - - - ``` - - *NOTE: This NuGet.Config should be with your application unless you want nightly packages to potentially start being restored for other apps on the machine.* - -Prerelease tooling builds for Visual Studio are available in the [Visual Studio Preview](https://www.visualstudio.com/vs/preview/). - - -## Community and roadmap - -To follow along with the development of ASP.NET Core: - -- [Community Standup](http://live.asp.net): The community standup is held every week and streamed live to YouTube. You can view past standups in the linked playlist. -- [Roadmap](https://github.com/aspnet/Home/wiki/Roadmap): The schedule and milestone themes for ASP.NET Core. - -## Repos and projects - -These are some of the most common repos: - -* [DependencyInjection](https://github.com/aspnet/DependencyInjection) - basic dependency injection infrastructure and default implementation -* [Docs](https://github.com/aspnet/Docs) - documentation sources for https://docs.microsoft.com/en-us/aspnet/core/ -* [EntityFrameworkCore](https://github.com/aspnet/EntityFrameworkCore) - data access technology -* [Identity](https://github.com/aspnet/Identity) - users and membership system -* [MVC](https://github.com/aspnet/Mvc) - MVC framework for web apps and services -* [Razor](https://github.com/aspnet/Razor) - template language and syntax for CSHTML files -* [SignalR](https://github.com/aspnet/SignalR) - library to add real-time web functionality -* [Templating](https://github.com/aspnet/Templating) - project templates for Visual Studio and the .NET Core SDK -* [Tooling](https://github.com/aspnet/Tooling) - Visual Studio tooling, editors, and dialogs - -## NuGet feeds and branches - -See the [NuGet feeds](https://github.com/aspnet/Home/wiki/NuGet-feeds) wiki page. - -# Feedback - -Check out the [contributing](CONTRIBUTING.md) page to see the best places to log issues and start discussions. - -# Code of conduct - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +ASP.NET Core +============ + +ASP.NET Core is an open-source and cross-platform framework for building modern cloud based internet connected applications, such as web apps, IoT apps and mobile backends. ASP.NET Core apps can run on .NET Core or on the full .NET Framework. It was architected to provide an optimized development framework for apps that are deployed to the cloud or run on-premises. It consists of modular components with minimal overhead, so you retain flexibility while constructing your solutions. You can develop and run your ASP.NET Core apps cross-platform on Windows, Mac and Linux. [Learn more about ASP.NET Core](https://docs.microsoft.com/aspnet/core/). + +ASP.NET Core 2.1 is now available! See the [release notes](https://github.com/aspnet/AspNetCore/releases/tag/2.1.0) for further details and check our [releases](https://github.com/aspnet/AspNetCore/releases/) for the latest patch release. + +## Get Started + +Follow the [Getting Started](https://docs.microsoft.com/aspnet/core/getting-started) instructions in the [ASP.NET Core docs](https://docs.microsoft.com/aspnet/index). + +Also check out the [.NET Homepage](https://www.microsoft.com/net) for released versions of .NET, getting started guides, and learning resources. + +## How to Engage, Contribute, and Give Feedback + +Some of the best ways to contribute are to try things out, file issues, join in design conversations, +and make pull-requests. + +* [Download our latest daily builds](./docs/daily-builds.md) +* Follow along with the development of ASP.NET Core: + * [Community Standup](http://live.asp.net): The community standup is held every week and streamed live to YouTube. You can view past standups in the linked playlist. + * [Roadmap](https://github.com/aspnet/AspNetCore/wiki/Roadmap): The schedule and milestone themes for ASP.NET Core. +* [Build ASP.NET Core source code](./docs/build-from-source.md) +* Check out the [contributing](CONTRIBUTING.md) page to see the best places to log issues and start discussions. + +## Reporting security issues and bugs + +Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the [Security TechCenter](https://technet.microsoft.com/en-us/security/ff852094.aspx). + +## Related projects + +These are some other repos for related projects: + +* [Documentation](https://github.com/aspnet/Docs) - documentation sources for https://docs.microsoft.com/aspnet/core/ +* [Entity Framework Core](https://github.com/aspnet/EntityFrameworkCore) - data access technology +* [Tooling](https://github.com/aspnet/Tooling) - Visual Studio tooling, editors, and dialogs + +## Code of conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/THIRD-PARTY-NOTICES.txt b/THIRD-PARTY-NOTICES.txt new file mode 100644 index 0000000000..d1bf499032 --- /dev/null +++ b/THIRD-PARTY-NOTICES.txt @@ -0,0 +1,86 @@ +.NET Core uses third-party libraries or other resources that may be +distributed under licenses different than the .NET Core software. + +In the event that we accidentally failed to list a required notice, please +bring it to our attention. Post an issue or email us: + + dotnet@microsoft.com + +The attached notices are provided for information only. + +License notice for dotnet-deb-tool +------------------------------------ + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +License notice for IIS-Common +------------------------------------ + +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE + +License notice for IIS-Setup +------------------------------------ + +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000000..c0050bda12 --- /dev/null +++ b/build.cmd @@ -0,0 +1,2 @@ +@ECHO OFF +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..98a4b22765 --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) +chmod +x "$DIR/run.sh"; sync +"$DIR/run.sh" default-build "$@" diff --git a/build/AzureIntegration.targets b/build/AzureIntegration.targets new file mode 100644 index 0000000000..8df9536eb7 --- /dev/null +++ b/build/AzureIntegration.targets @@ -0,0 +1,30 @@ + + + $(MSBuildThisFileDirectory)..\modules\AzureIntegration\ + + + + + + AspNetUniverseBuildOffline=true; + RepositoryRoot=$(AzureIntegrationProjectRoot); + DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath); + DotNetPackageVersionPropsPath=$(GeneratedPackageVersionPropsPath); + BuildNumber=$(BuildNumber); + Configuration=$(Configuration); + IsFinalBuild=$(IsFinalBuild); + + + + + + + + + + + + + diff --git a/build/PackageArchive.targets b/build/PackageArchive.targets new file mode 100644 index 0000000000..bb892d102c --- /dev/null +++ b/build/PackageArchive.targets @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath); + DotNetPackageVersionPropsPath=$(GeneratedPackageVersionPropsPath); + OutputPath=$(ArtifactsDir)lzma\; + _BuildToolsAssembly=$(_BuildToolsAssembly) + + + + + + + + + + diff --git a/build/Publish.targets b/build/Publish.targets new file mode 100644 index 0000000000..3a62447d1c --- /dev/null +++ b/build/Publish.targets @@ -0,0 +1,330 @@ + + + + $(RepositoryRoot).deps\assets\ + $(RepositoryRoot).deps\packages\ + + aspnetcore_base_runtime.version + $(IntermediateDir)$(BaseRuntimeVersionFileName) + latest.version + $(IntermediateDir)$(LatestRuntimeVersionFileName) + + + ResolveCommitHash; + PrepareOutputPaths; + GetFilesToPublish; + PublishToLocalFolder; + PublishToAzureFeed; + PublishToTransportFeed; + PublishToMyGet; + + + + 10 + false + 8 + assets + $(BlobFileRelativePathBase)/ + + + + + + + + + + + + + + + + + + + + + + + aspnetcore/Runtime/$(PackageVersion)/ + aspnetcore/npm/ + aspnetcore/jar/ + aspnetcore/Runtime/$(SharedFxCliBlobChannel)/ + runtime-site-extension-internal-$(PackageVersion).zip + aspnetcore-runtime-$(PackageVersion) + aspnetcore-runtime-latest + aspnetcore-runtime-internal-$(PackageVersion) + dotnet-hosting-$(PackageVersion)-win.exe + + + + + + $(BlobBasePath)$(WindowsHostingBundleInstallerFileName) + ShipInstaller=dotnetcli + + + + + $(BlobBasePath)nuGetPackagesArchive-ci-server-$(PackageVersion).zip + ShipInstaller=dotnetcli + + + + $(BlobBasePath)nuGetPackagesArchive-ci-server-$(PackageVersion).patch.zip + ShipInstaller=dotnetcli + + + + $(BlobBasePath)nuGetPackagesArchive-ci-server-compat-$(PackageVersion).patch.zip + ShipInstaller=dotnetcli + + + + + $(BlobBasePath)$(SiteExtensionArchiveFileName) + ShipInstaller=dotnetcli + + + + $(BlobBasePath)nuGetPackagesArchive-$(PackageVersion).lzma + ShipInstaller=dotnetcli + + + + $(BlobBasePath)$(IntermediateInstallerBaseFileName)-%(IntermediateInstaller.Identity)%(IntermediateInstaller.FileExt) + ShipInstaller=dotnetcli + + + + $(BlobBasePath)$(BaseRuntimeVersionFileName) + ShipInstaller=dotnetcli + text/plain + + + + + $(BlobBasePath)$(InstallerBaseFileName)-%(NativeInstaller.Identity)%(NativeInstaller.FileExt) + ShipInstaller=dotnetcli + + + + + $(AliasBlobBasePath)$(InstallerAliasBaseFileName)-%(NativeInstaller.Identity)%(NativeInstaller.FileExt) + ShipInstaller=dotnetcli + true + + true + + + + $(AliasBlobBasePath)%(SharedFxVersionBadge.FileName)%(SharedFxVersionBadge.Extension) + ShipInstaller=dotnetcli + no-cache, no-store, must-revalidate + image/svg+xml + true + + + + $(AliasBlobBasePath)$(LatestRuntimeVersionFileName) + ShipInstaller=dotnetcli + no-cache, no-store, must-revalidate + text/plain + true + + + + <_PackageArtifactInfo + Include="@(ArtifactInfo)" + ArtifactPath="$(DependencyPackagesDir)%(ArtifactInfo.PackageId).%(ArtifactInfo.Version).nupkg" + Condition="'%(ArtifactInfo.ArtifactType)' == 'NuGetPackage'" /> + + <_SymbolsPackageArtifactInfo + Include="@(ArtifactInfo)" + ArtifactPath="$(DependencyPackagesDir)%(ArtifactInfo.PackageId).%(ArtifactInfo.Version).symbols.nupkg" + Condition="'%(ArtifactInfo.ArtifactType)' == 'NuGetSymbolsPackage'" /> + + + $(JarBlobBasePath)%(ArtifactInfo.FileName)%(ArtifactInfo.Extension) + Type=JavaJar + + + + $(JarBlobBasePath)%(ArtifactInfo.FileName)%(ArtifactInfo.Extension) + + + + $(NpmBlobBasePath)%(ArtifactInfo.PackageId)/%(ArtifactInfo.FileName)%(ArtifactInfo.Extension) + Type=NpmPackage + application/tar+gzip + + + + + + + + + + + + + + + + <_MissingArtifactFile Include="@(FilesToPublish)" Condition="!Exists(%(FilesToPublish.Identity))" /> + <_MissingArtifactFile Include="@(NpmPackageToPublish)" Condition="!Exists(%(NpmPackageToPublish.Identity))" /> + <_MissingArtifactFile Include="@(PackageToPublish)" Condition="!Exists(%(PackageToPublish.Identity))" /> + + + + + + + + + + + + + + + + + + + + + + + + + + $(PublishMyGetNpmRegistryUrl.Replace("https:", "")):_authToken + + + + + + + + + + + + + + + + + + + + + $(AzureBlobRelativePathBase)/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/RepositoryBuild.targets b/build/RepositoryBuild.targets new file mode 100644 index 0000000000..95e08cb4cb --- /dev/null +++ b/build/RepositoryBuild.targets @@ -0,0 +1,191 @@ + + + + + false + + <_NoBuildRepos>$(NoBuild) + <_BuildScriptToExecute Condition="'$(OS)'!='Windows_NT'">build.sh + <_BuildScriptToExecute Condition="'$(OS)'=='Windows_NT'">build.cmd + + + + + + $(SubmoduleRoot)%(Identity)\ + + + %(RepositoryBuildOrder.Order) + %(RepositoryBuildOrder.Identity) + + RepositoryToBuild=%(RepositoryBuildOrder.Identity); + BuildRepositoryRoot=$([MSBuild]::NormalizeDirectory(%(RepositoryBuildOrder.RootPath))) + + + + + + + + + + <_NoBuildRepos>true + + + + + + + + + + + + + + + + + + + + + + + true + + $(RepositoryBuildArguments) -ci + $(RepositoryBuildArguments) --dotnet-home '$(DOTNET_HOME)' + $(RepositoryBuildArguments) -DotNetHome '$(DOTNET_HOME)' + + $(RepositoryBuildArguments) /p:AspNetUniverseBuildOffline=true + + $(RepositoryBuildArguments) /p:DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath) + $(RepositoryBuildArguments) /p:DotNetPackageVersionPropsPath=$(GeneratedPackageVersionPropsPath) + + $(RepositoryBuildArguments) /p:SignType=$(SignType) + $(RepositoryBuildArguments) /p:BuildNumber=$(BuildNumber) + $(RepositoryBuildArguments) /p:Configuration=$(Configuration) + $(RepositoryBuildArguments) /p:IsFinalBuild=$(IsFinalBuild) + $(RepositoryBuildArguments) /noconsolelogger '/l:RepoTasks.FlowLogger,$(MSBuildThisFileDirectory)tasks\bin\publish\RepoTasks.dll;Summary;FlowId=$(RepositoryToBuild)' + $(RepositoryBuildArguments) '/p:DotNetAssetRootAccessTokenSuffix=$(DotNetAssetRootAccessTokenSuffix)' + $(RepositoryBuildArguments) '/p:DotNetAssetRootUrl=$(DotNetAssetRootUrl)' + $(RepositoryBuildArguments) /p:SkipAspNetCoreRuntimeInstall=true + + $(RepositoryRoot)korebuild-lock.txt + $(BuildRepositoryRoot)korebuild-lock.txt + $(IntermediateDir)$(RepositoryToBuild)-korebuild-lock.txt + $(BuildRepositoryRoot)global.json + $(IntermediateDir)$(RepositoryToBuild)-global.json + + + + + + + + + + + + + + + + + + + + + /t:CleanArtifacts /t:Build /p:SkipTests=true $(RepositoryBuildArguments) + $(BuildArguments) /bl:$(LogOutputDir)$(RepositoryToBuild).build.binlog + $(BuildRepositoryRoot)artifacts\ + $(RepositoryArtifactsRoot)build\ + $(RepositoryArtifactsRoot)msbuild\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + /t:Test /p:NoBuild=$(_NoBuildRepos) $(RepositoryBuildArguments) + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/SharedFx.props b/build/SharedFx.props new file mode 100644 index 0000000000..ca4aba4602 --- /dev/null +++ b/build/SharedFx.props @@ -0,0 +1,79 @@ + + + + <_WorkRoot>$(RepositoryRoot).w\$(SharedFxRID)\ + <_WorkLayoutDir>$(_WorkRoot).l\ + <_WorkOutputDir>$(_WorkRoot).o\ + <_MetapackageSrcRoot>$(RepositoryRoot)src\Packages\ + <_TemplatesDir>$(MSBuildThisFileDirectory)tools\templates\ + <_DockerDir>$(MSBuildThisFileDirectory)tools\docker\ + <_PackagingDir>$(MSBuildThisFileDirectory)tools\packaging\ + <_SharedFxSourceDir>$(RepositoryRoot).deps\Signed\SharedFx\ + <_InstallerSourceDir>$(RepositoryRoot).deps\Installers\ + <_SymbolsSourceDir>$(RepositoryRoot).deps\symbols\ + <_DockerRootDir>/opt/code/ + <_InstallersOutputDir>$(ArtifactsDir)installers\ + + : + %3B + .tar.gz + .zip + + lib + .so + .dll + .dylib + .exe + netcoreapp3.0 + + + aspnetcore-runtime + + $(SharedFxInstallerName)-internal + $(_PackagingDir)debian_config.json.in + https://dotnetcli.blob.core.windows.net/dotnet/ + + + $(PublicCoreFeedPrefix) + + dotnet-runtime-$(MicrosoftNETCoreAppPackageVersion) + $(DotNetAssetRootUrl)Runtime/$(MicrosoftNETCoreAppPackageVersion)/$(DotnetRuntimeFileNamePrefix) + + $(_SharedFxSourceDir)$(SharedFxIntermediateArchiveBaseName)-$(PackageVersion) + + + + $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + $(InstallerIdVersion).$(AspNetCorePatchVersion) + + $(InstallerPackageVersion) + $(DebInstallerPackageVersion)~$(PackageVersionSuffix) + 1 + + $(PackageRevision) + 0.1.$(PackageVersionSuffix) + $([System.String]::Copy('$(RpmPackageRevision)').Replace('-', '_')) + + + Microsoft + nugetaspnet@microsoft.com + https://www.asp.net/ + /usr/share/dotnet + Apache-2.0 + Microsoft ASP.NET Core $(PackageVersion) Shared Framework + Shared Framework for hosting of Microsoft ASP.NET Core applications. It is open source, cross-platform and is supported by Microsoft. We hope you enjoy using it! If you do, please consider joining the active community of developers that are contributing to the project on GitHub (https://github.com/aspnet/home). We happily accept issues and PRs. + + + + + + + + + + + + diff --git a/build/SharedFx.targets b/build/SharedFx.targets new file mode 100644 index 0000000000..9987e815a5 --- /dev/null +++ b/build/SharedFx.targets @@ -0,0 +1,566 @@ + + + + + $([MSBuild]::NormalizeDirectory($(ArtifactsDir)))runtime\ + + + + + <_MetapackageProject Include="$(RepositoryRoot)src\Packages\Microsoft.AspNetCore.All\Microsoft.AspNetCore.All.csproj" /> + <_MetapackageProject Include="$(RepositoryRoot)src\Packages\Microsoft.AspNetCore.App\Microsoft.AspNetCore.App.csproj" /> + <_MetapackageProject Include="$(RepositoryRoot)src\Packages\Microsoft.AspNetCore.Analyzers\Microsoft.AspNetCore.Analyzers.csproj" /> + + + + + + + + + <_SharedFrameworkSymbolsPackage Include="@(SharedFrameworkName)" Condition="'%(AllSharedFxRIDs.CrossgenSymbols)' != 'false' AND '%(AllSharedFxRIDs.Crossgen)' != 'false'"> + %(AllSharedFxRIDs.Identity) + + <_SharedFrameworkSymbolsPackage Update="@(_SharedFrameworkSymbolsPackage)" PackageId="runtime.%(Rid).%(Identity)" /> + + NuGetSymbolsPackage + %(_SharedFrameworkSymbolsPackage.PackageId) + $(PackageVersion) + shipoob + + + + + + + $(_MetapackageSrcRoot)$(MetapackageName)\ + $(_WorkRoot)pkg\$(MetapackageName)\ + + $(CommonProps);Configuration=$(Configuration) + $(CommonProps);DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath) + $(CommonProps);DotNetBuildOffline=true + $(CommonProps);AspNetUniverseBuildOffline=true + $(CommonProps);RuntimeFrameworkVersion=$(MicrosoftNETCoreApp30PackageVersion) + $(CommonProps);AppMetapackageVersion=$(PackageVersion) + + + + + + + + + + + + + + + + + + + + + + + + + + + <_MetapackageBuilderProject Include="$(MSBuildProjectFullPath)"> + + MetapackageName=Microsoft.AspNetCore.App; + MetapackageReferenceType=AppMetapackage; + MetapackageDependencyVersionRangeType=MajorMinor + + + + <_MetapackageBuilderProject Include="$(MSBuildProjectFullPath)"> + + MetapackageName=Microsoft.AspNetCore.All; + MetapackageReferenceType=AllMetapackage; + MetapackageDependencyVersionRangeType=Minimum + + + + <_MetapackageBuilderProject Include="$(MSBuildProjectFullPath)"> + + MetapackageName=Microsoft.AspNetCore.Analyzers; + MetapackageReferenceType=Analyzer; + MetapackageDependencyVersionRangeType=Minimum + + + + + + + + + + true + false + true + false + true + + + + + + $(_WorkRoot)AppSharedFx\ + $(_WorkRoot)AllSharedFx\ + $(_WorkRoot)Publish\ + $(_WorkRoot)CrossGen\ + $(_WorkRoot)CrossGenSymbols\ + $(_WorkRoot)CrossGenTool\ + $(_WorkRoot)CrossGenRsp\ + $(SharedFxIntermediateOutputPath)shared\Microsoft.AspNetCore.App\$(PackageVersion)\ + $(SharedFxIntermediateOutputPath)shared\Microsoft.AspNetCore.All\$(PackageVersion)\ + $(SharedFxRID) + + + : + %3B + + Configuration=$(Configuration);RuntimeIdentifier=$(SharedFxRestoreRid) + $(CommonSharedFxProps);DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath) + $(CommonSharedFxProps);DotNetBuildOffline=true + $(CommonSharedFxProps);AspNetUniverseBuildOffline=true + + + + + + $(CommonSharedFxProps) + $(RestoreProps);SharedFxPackage=$(SharedFxPackage) + $(RestoreProps);SharedFxPackageVersion=$(PackageVersion) + $(RestoreProps);SharedFxBase=$(SharedFxBase) + $(RestoreProps);SharedFxBaseVersion=$(SharedFxBaseVersion) + + + + + + + + + + + + + + + + RepositoryCommit=$(RepositoryCommit);SharedFxWorkDirectory=$(AppSharedFxWorkDirectory) + $(AppSharedFxProps);RuntimeFrameworkVersion=$(MicrosoftNETCoreApp30PackageVersion) + $(AppSharedFxProps);SharedFxPackage=Microsoft.AspNetCore.App + RepositoryCommit=$(RepositoryCommit);SharedFxWorkDirectory=$(AllSharedFxWorkDirectory) + $(AllSharedFxProps);RuntimeFrameworkVersion=$(MicrosoftNETCoreApp30PackageVersion) + $(AllSharedFxProps);SharedFxPackage=Microsoft.AspNetCore.All + $(AllSharedFxProps);SharedFxDep=Microsoft.AspNetCore.App + $(AllSharedFxProps);SharedFxDepVersion=$(PackageVersion) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + win + linux + osx + + + + + + + + + + + + + + + SharedFxPackage=Microsoft.AspNetCore.App + $(AppSharedFxProps);SharedFxWorkDirectory=$(AppSharedFxWorkDirectory) + $(AppSharedFxProps);SharedFxPublishDirectory=$(AppSharedFxPublishDirectory) + SharedFxPackage=Microsoft.AspNetCore.All + $(AllSharedFxProps);SharedFxWorkDirectory=$(AllSharedFxWorkDirectory) + $(AllSharedFxProps);SharedFxPublishDirectory=$(AllSharedFxPublishDirectory) + + + + + + + + + + + Microsoft.NETCore.App + crossgen + $(CrossGenTool).exe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_AppRuntimeAssemblies Include="@(AppPublishAssemblies)" Condition="'%(AssetType)' == 'runtime'"> + %(PackageName).%(PackageVersion).symbols.nupkg + %(RootDir)%(Directory)%(Filename).pdb + + <_AllRuntimeAssemblies Include="@(AllPublishAssemblies)" Exclude="@(_AppRuntimeAssemblies)" Condition="'%(AssetType)' == 'runtime'"> + %(PackageName).%(PackageVersion).symbols.nupkg + %(RootDir)%(Directory)%(Filename).pdb + + + <_AssembliesToCrossgen Include="$(SharedFxIntermediateOutputPath)**\*.dll" /> + + + + + + + + + + + + + + + + + + + + %(FullPath) + $(SharedFxCrossGenRspDirectory)%(RecursiveDir)%(Filename).rsp + $(SharedFxCrossGenRspDirectory)%(RecursiveDir)%(Filename).symbols.rsp + $(SharedFxCrossGenDirectory)%(RecursiveDir)%(Filename)%(Extension) + $(SharedFxCrossGenDirectory)%(RecursiveDir) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CreatePerfMap + CreatePDB + + + + + + + + + + + + + + + + + + + + runtime.$(SharedFxRID).$(SymbolsNuspecIdSuffix) + + + + <_SymbolFiles Include="$(SymbolsWorkDir)**\*.pdb;$(SymbolsWorkDir)**\*.map;$(SymbolsWorkDir)**\*.dll" /> + + %(RecursiveDir)%(Filename)%(Extension) + + + + + + + + + + + + + $(SharedFxCrossGenDirectory)shared\Microsoft.AspNetCore.App\$(PackageVersion)\ + $(SharedFxCrossGenDirectory)shared\Microsoft.AspNetCore.All\$(PackageVersion)\ + $(_WorkRoot)Symbols\Microsoft.AspNetCore.App\ + $(_WorkRoot)Symbols\Microsoft.AspNetCore.All\ + + + + + + + + + + + + + + + + + + + + + + + + + + SymbolsWorkDir=$(AppSharedFxSymbolsDirectory) + $(AppSymbolsArguments);SymbolsNuspecIdSuffix=Microsoft.AspNetCore.App + $(AppSymbolsArguments);Description=Symbol packages for Microsoft.AspNetCore.App shared framework + SymbolsWorkDir=$(AllSharedFxSymbolsDirectory) + $(AllSymbolsArguments);SymbolsNuspecIdSuffix=Microsoft.AspNetCore.All + $(AllSymbolsArguments);Description=Symbol packages for Microsoft.AspNetCore.All shared framework + + + + + + + + + + + + + + + + + + + + + + + $(RepositoryRoot)\test\SharedFx.UnitTests\SharedFx.UnitTests.csproj + + + $(LogOutputDir)SharedFx-UnitTests-$(Version).trx + + $(UnitTestFxTrxLogFile) + $(HostMachineRepositoryRoot)/artifacts/logs/SharedFx-UnitTests.trx + + + DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath); + DotNetPackageVersionPropsPath=$(GeneratedPackageVersionPropsPath); + SharedFxOutputPath=$(SharedFxIntermediateOutputPath); + RepositoryCommit=$(RepositoryCommit); + VSTestLogger=$([MSBuild]::Escape('trx;LogFileName=$(UnitTestFxTrxLogFile)')); + SharedFxRuntimeIdentifier=$(SharedFXRid) + + + + + + + + + + + + + + + diff --git a/build/SharedFxInstaller.targets b/build/SharedFxInstaller.targets new file mode 100644 index 0000000000..50cfb4d5a5 --- /dev/null +++ b/build/SharedFxInstaller.targets @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + .tar.gz + .zip + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DATE=$([System.DateTime]::UtcNow.ToString(ddd MMM dd yyyy)) + $(ChangeLogProps);MAINTAINER_NAME=$(RpmMaintainerName) + $(ChangeLogProps);MAINTAINER_EMAIL=$(RpmMaintainerEmail) + $(ChangeLogProps);PACKAGE_VERSION=$(RpmPackageVersion) + $(ChangeLogProps);PACKAGE_REVISION=$(RpmRevision) + + + + + + + + + + + + rhel.7 + .NET Foundation + /opt/rh/rh-dotnet20/root/usr/lib64/dotnet + dotnet-runtime-$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + $(MicrosoftNETCoreAppPackageVersion.Split('-')[0]) + + + + + + + + + + + + + @(RpmSharedFxDependencies->' -d "%(Identity) >= %(Version)"', ' ') + $(RpmSharedFxArguments) @(RpmRHSharedFxDirectories->' --directories "%(FullPath)"', ' ') + $(RpmSharedFxArguments) @(RpmGenericSharedFxDirectories->' --directories "%(FullPath)"', ' ') + + Image=$(Image);RpmVendor=$(RpmVendor);RpmName=$(SharedFxInstallerName) + $(RpmCommonProps);RpmMaintainerName=$(MaintainerName);RpmMaintainerEmail=$(MaintainerEmail) + $(RpmCommonProps);RpmHomepage=$(Homepage);RpmRevision=$(RpmPackageRevision) + $(RpmCommonProps);RpmLicense=$(LicenseType) + $(RpmCommonProps);SharedFxArchive=$(SharedFxIntermediateArchiveFilePrefix)-linux-x64.tar.gz + $(RpmCommonProps);RpmMSummary=$(SharedFxSummary);RpmDescription=$(SharedFxDescription) + RpmInstallRoot=$(InstallRoot) + RpmInstallRoot=$(RHInstallRoot) + RpmIdVersion=$(InstallerIdVersion);RpmPackageVersion=$(InstallerPackageVersion);RpmFileVersion=$(PackageVersion) + + $(RpmCommonProps);$(RpmGenericProps);$(RpmProps);RpmArguments=$(RpmGenericSharedFxArguments);RpmFileSuffix=x64.rpm + $(RpmCommonProps);$(RpmRHProps);$(RpmProps);RpmArguments=$(RpmRHSharedFxArguments);RpmFileSuffix=rh.rhel.7-x64.rpm + + + + + + + + + + + + + + + $(RepositoryRoot)src/Installers/Debian/build.sh + + + + + + + + + + + + + + + + + + MAINTAINER_NAME=$(MaintainerName) + $(DebConfigProps);MAINTAINER_EMAIL=$(MaintainerEmail) + $(DebConfigProps);HOMEPAGE=$(Homepage) + $(DebConfigProps);INSTALL_ROOT=$(InstallRoot) + $(DebConfigProps);PACKAGE_NAME=$(DebPrefix) + $(DebConfigProps);PACKAGE_REVISION=$(PackageRevision) + $(DebConfigProps);LICENSE_TYPE=$(LicenseType) + $(DebConfigProps);SHORT_DESCRIPTION=$(DebSummary) + $(DebConfigProps);LONG_DESCRIPTION=$(DebDescription) + $(DebConfigProps);DEBIAN_DEPENDENCIES=$(DebDependencies) + + + + + + + + + + + + + + + + + + + + + dotnet-runtime-$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + $(MicrosoftNETCoreAppPackageVersion) + + $(Deb_DotnetRuntimeDependencyVersion.Substring(0, $(Deb_DotnetRuntimeDependencyVersion.IndexOf('-'))))~$(Deb_DotnetRuntimeDependencyVersion.Substring($([MSBuild]::Add($(Deb_DotnetRuntimeDependencyVersion.IndexOf('-')), 1)))) + + + + <_DebSharedFxDependencies Include="$(Deb_DotnetRuntimeDependencyId)" Version="$(Deb_DotnetRuntimeDependencyVersion)"/> + + + + ubuntu.14.04 + + @(_DebSharedFxDependencies->'"%(Identity)": { "package_version": "%(Version)" }', ', ') + + Image=$(Image);DebPrefix=$(SharedFxInstallerName) + $(DebCommonProps);DebSummary=$(SharedFxSummary);DebDescription=$(SharedFxDescription) + $(DebCommonProps);SharedFxArchive=$(SharedFxIntermediateArchiveFilePrefix)-linux-x64.tar.gz + + DebIdVersion=$(InstallerIdVersion);DebPackageVersion=$(DebInstallerPackageVersion);DebFileVersion=$(PackageVersion);DebDependencies=$(DebSharedFxDependencies) + + + + + + + + + + + diff --git a/build/artifacts.props b/build/artifacts.props new file mode 100644 index 0000000000..1265fb285a --- /dev/null +++ b/build/artifacts.props @@ -0,0 +1,298 @@ + + + + + + false + + false + + false + + Dependency + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/buildorder.props b/build/buildorder.props new file mode 100644 index 0000000000..073ba5c494 --- /dev/null +++ b/build/buildorder.props @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/dependencies.props b/build/dependencies.props new file mode 100644 index 0000000000..3caec25f6b --- /dev/null +++ b/build/dependencies.props @@ -0,0 +1,184 @@ + + + + 4.6.0-preview1-26907-04 + 3.0.0-preview1-26907-05 + + 3.0.0-preview1-26907-05 + 3.0.0-preview1-26907-05 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 1.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26717-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 1.7.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.10.0-preview1-26907-04 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26829-04 + + + + + + + $(MicrosoftNETCoreAppPackageVersion) + + + $(KoreBuildVersion) + $(KoreBuildVersion) + $(KoreBuildVersion) + + + + + 0.9.9 + 0.10.13 + + + 2.1.1 + 2.1.1 + 2.1.1 + 0.43.0 + 2.1.1.1 + 2.1.1 + + 4.2.1 + 2.2.0-preview1-03124-01 + 2.0.0 + 8.7.0 + 4.2.1 + 3.1.0 + 1.10.0 + 1.7.3.4 + 2.1.1 + 2.2.1 + 5.2.6 + 1.7.1 + 2.3.2 + 1.1.3 + 1.0.1 + 15.8.166 + 15.8.166 + 15.8.166 + 15.8.166 + 15.8.166 + 2.8.0 + 2.8.0 + 2.8.0 + 1.7.0 + 0.2.0-beta-63019-01 + 1.0.0-rc3-003121 + 1.1.0 + 3.19.8 + 5.3.0 + 5.3.0 + 2.1.1 + 1.0.12 + 1.1.9 + 2.0.9 + 2.1.3 + 2.2.0-preview3-27014-02 + $(MicrosoftNETCoreApp21PackageVersion) + $(MicrosoftNETCoreApp22PackageVersion) + 1.0.1 + 15.6.1 + 3.0.1 + 3.0.1 + 3.0.1 + 15.8.525 + 15.8.525 + 15.8.28010 + 15.8.525 + 15.8.525 + 7.10.6071 + 15.8.243 + 2.0.6142705 + 15.8.243 + 15.8.28010 + 10.0.30320 + 11.0.61031 + 12.0.30111 + 8.0.50728 + 9.0.30730 + 7.10.6072 + 15.8.525 + 15.8.168 + 11.1.0 + 1.4.0 + 4.3.0.1 + 1.3.8 + 1.0.1 + 4.10.0 + 1.6.1 + 2.0.3 + 1.15.1 + 1.15.0 + 1.15.0-pre001 + 1.0.1 + 11.0.2 + 4.7.0 + 12.2.1100 + 2.0.1 + 6.0.1 + 2.2.0 + 0.20.0 + 3.12.1 + 17.17134.0 + 3.12.1 + 1.4.0 + 4.0.0 + 1.1.11 + 1.1.11 + 1.1.11 + 1.2.6 + 2.0.513 + 1.4.128 + 1.0.0 + 5.3.0 + 3.2.0 + 4.3.2 + 3.1.1 + 4.3.0 + 4.3.0 + 1.3.7 + 9.0.1 + 2.9.0-beta4-62911-02 + 2.9.0-beta4-62911-02 + 2.9.0-beta4-62911-02 + 2.9.0-beta4-62911-02 + 2.9.0-beta4-62911-02 + 2.9.0-beta4-62911-02 + 2.9.0-beta4-62911-02 + 2.9.0-beta4-62911-02 + 2.9.0-beta4-62911-02 + 2.9.0-beta4-62911-02 + 8.1.4 + 2.0.1 + 0.10.0 + 2.3.1 + 2.3.1 + 2.3.1 + 2.3.1 + 2.3.1 + 2.4.0 + + diff --git a/build/docker/alpine.Dockerfile b/build/docker/alpine.Dockerfile new file mode 100644 index 0000000000..ae9cbab56f --- /dev/null +++ b/build/docker/alpine.Dockerfile @@ -0,0 +1,27 @@ +FROM microsoft/dotnet:2.1.0-preview1-runtime-deps-alpine +ARG USER +ARG USER_ID +ARG GROUP_ID + +WORKDIR /code/build +RUN mkdir -p "/home/$USER" && chown "${USER_ID}:${GROUP_ID}" "/home/$USER" +ENV HOME "/home/$USER" + +RUN apk add --no-cache \ + bash \ + wget \ + git \ + jq \ + curl \ + icu-libs \ + openssl + +USER $USER_ID:$GROUP_ID + +# Disable the invariant mode (set in base image) +ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false +ENV LC_ALL en_US.UTF-8 +ENV LANG en_US.UTF-8 + +# Skip package initilization +ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 diff --git a/build/external-dependencies.props b/build/external-dependencies.props new file mode 100644 index 0000000000..a980476968 --- /dev/null +++ b/build/external-dependencies.props @@ -0,0 +1,192 @@ + + + + + + + + + false + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/lineups/Internal.AspNetCore.Universe.Lineup.nuspec b/build/lineups/Internal.AspNetCore.Universe.Lineup.nuspec new file mode 100644 index 0000000000..cc35b59699 --- /dev/null +++ b/build/lineups/Internal.AspNetCore.Universe.Lineup.nuspec @@ -0,0 +1,16 @@ + + + + Internal.AspNetCore.Universe.Lineup + $version$ + Microsoft + This package used to unify ASP.NET Core package versions across all Universe repos. Internal use only. + + + + + + + + + diff --git a/build/repo.beforecommon.props b/build/repo.beforecommon.props new file mode 100644 index 0000000000..0550358981 --- /dev/null +++ b/build/repo.beforecommon.props @@ -0,0 +1,10 @@ + + + + true + + diff --git a/build/repo.props b/build/repo.props new file mode 100644 index 0000000000..719d646fe7 --- /dev/null +++ b/build/repo.props @@ -0,0 +1,83 @@ + + + + true + + false + true + false + + $(RepositoryRoot)modules\ + + $(RepositoryRoot).deps\build\ + $(RepositoryRoot).deps\Signed\Packages\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + true + + + true + + + + + + + diff --git a/build/repo.targets b/build/repo.targets new file mode 100644 index 0000000000..f4a116d48d --- /dev/null +++ b/build/repo.targets @@ -0,0 +1,281 @@ + + + + + + + + + + + $(IntermediateDir)dependencies.g.props + $(IntermediateDir)sources.g.props + $(IntermediateDir)branding.g.props + + SetTeamCityBuildNumberToVersion;$(PrepareDependsOn);VerifyPackageArtifactConfig;VerifyExternalDependencyConfig;PrepareOutputPaths + $(CleanDependsOn);CleanArtifacts;CleanUniverseArtifacts + $(RestoreDependsOn);InstallDotNet + $(CompileDependsOn);BuildRepositories + $(PackageDependsOn);BuildMetapackages;CheckExpectedPackagesExist + $(TestDependsOn);_TestRepositories + $(GetArtifactInfoDependsOn);ResolveRepoInfo + + + + + + + + + + MicrosoftNETCoreAppPackageVersion=$(MicrosoftNETCoreAppPackageVersion); + $(DesignTimeBuildProps);MicrosoftNETCoreApp30PackageVersion=$(MicrosoftNETCoreApp30PackageVersion); + $(DesignTimeBuildProps);MicrosoftNETCoreApp22PackageVersion=$(MicrosoftNETCoreApp22PackageVersion); + $(DesignTimeBuildProps);MicrosoftNETCoreApp21PackageVersion=$(MicrosoftNETCoreApp21PackageVersion); + $(DesignTimeBuildProps);MicrosoftNETCoreApp20PackageVersion=$(MicrosoftNETCoreApp20PackageVersion); + + + + + + + + + + + + + + + + + + + + + <_Temp Remove="@(_Temp)" /> + <_Temp Include="@(PackageArtifact)" /> + + + + + + + + + + + + <_PackageArtifactWithoutMatchingInfo Include="@(_Temp)" Exclude="@(PackageArtifact)" /> + + + + + + + + %(ShippedArtifactInfo.Version) + + + + <_PackageArtifactSpec Include="@(PackageArtifact)" /> + + + + + <_ShippedSolution Update="@(_ShippedSolution)" Build="false" IsPatching="false" /> + <_NoBuildSolution Update="@(_NoBuildSolution)" Build="false" /> + + + + + + + + + + NuGetPackage + Internal.AspNetCore.Universe.Lineup + $(PackageVersion) + noship + true + + + + + + + <_LineupPackages Include="@(ExternalDependency)" /> + <_LineupPackages Include="%(ArtifactInfo.PackageId)" Version="%(ArtifactInfo.Version)" Condition=" '%(ArtifactInfo.ArtifactType)' == 'NuGetPackage' " /> + + <_RestoreSources Include="$(DependencyPackageDir)" Condition="'$(DependencyPackageDir)' != '' AND Exists('$(DependencyPackageDir)')" /> + <_RestoreSources Include="$(SignedDependencyPackageDir)" Condition="'$(SignedDependencyPackageDir)' != '' AND Exists('$(SignedDependencyPackageDir)')" /> + <_RestoreSources Include="$(BuildDir)" /> + <_RestoreSources Include="$(RestoreSources)" /> + + + + + + + + + + + + + + + $(AspNetCoreMajorVersion) + $(AspNetCoreMinorVersion) + $(AspNetCorePatchVersion) + $(PreReleaseLabel) + $(BuildNumber) + $(PackageBrandingVersion) + + +]]> + + + + + + + + + + + + + + + + + + + <_RepositoriesToInclude Include="$(KOREBUILD_REPOSITORY_INCLUDE)" /> + + + + + + <_RepositoriesToExclude Include="$(KOREBUILD_REPOSITORY_EXCLUDE)" /> + + + + + + + + + + + + + + + + + + + + + + + + + <_UndeclaredPackageArtifact Include="%(ArtifactInfo.PackageId)" Condition="'%(ArtifactInfo.ArtifactType)' == 'NuGetPackage'" /> + <_UndeclaredPackageArtifact Remove="@(PackageArtifact)" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/sources.props b/build/sources.props new file mode 100644 index 0000000000..5b458ddf09 --- /dev/null +++ b/build/sources.props @@ -0,0 +1,25 @@ + + + + + + + $(DotNetAdditionalRestoreSources); + $(DotNetRestoreSources); + + + $(RestoreSources); + https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; + https://api.nuget.org/v3/index.json; + + + $(RestoreSources); + https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-master/api/v3/index.json; + https://dotnet.myget.org/F/roslyn/api/v3/index.json; + https://vside.myget.org/F/vssdk/api/v3/index.json; + https://vside.myget.org/F/vsmac/api/v3/index.json + + + diff --git a/build/submodules.props b/build/submodules.props new file mode 100644 index 0000000000..8f60821673 --- /dev/null +++ b/build/submodules.props @@ -0,0 +1,87 @@ + + + + true + + + ProductChangesOnly + + + + false + ProductChangesOnly + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/tasks/AddMetapackageReferences.cs b/build/tasks/AddMetapackageReferences.cs new file mode 100644 index 0000000000..3cb11666ab --- /dev/null +++ b/build/tasks/AddMetapackageReferences.cs @@ -0,0 +1,134 @@ +// 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 System.Xml; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using NuGet.Versioning; +using RepoTasks.Utilities; + +namespace RepoTasks +{ + public class AddMetapackageReferences : Task + { + [Required] + public string ReferencePackagePath { get; set; } + + [Required] + public string MetapackageReferenceType { get; set; } + + [Required] + public string DependencyVersionRangeType { get; set; } + + // MSBuild doesn't allow binding to enums directly. + private enum VersionRangeType + { + Minimum, // [1.1.1, ) + MajorMinor, // [1.1.1, 1.2.0) + } + + [Required] + public ITaskItem[] PackageArtifacts { get; set; } + + [Required] + public ITaskItem[] ExternalDependencies { get; set; } + + public override bool Execute() + { + if (!Enum.TryParse(DependencyVersionRangeType, out var dependencyVersionType)) + { + Log.LogError("Unexpected value {0} for DependencyVersionRangeType", DependencyVersionRangeType); + return false; + } + + // Parse input + var metapackageArtifacts = PackageArtifacts.Where(p => p.GetMetadata(MetapackageReferenceType) == "true"); + var externalArtifacts = ExternalDependencies.Where(p => p.GetMetadata(MetapackageReferenceType) == "true"); + + var xmlDoc = new XmlDocument(); + xmlDoc.Load(ReferencePackagePath); + + // Project + var projectElement = xmlDoc.FirstChild; + + // Items + var itemGroupElement = xmlDoc.CreateElement("ItemGroup"); + Log.LogMessage(MessageImportance.High, $"{MetapackageReferenceType} will include the following packages"); + + foreach (var package in metapackageArtifacts) + { + var packageName = package.ItemSpec; + var packageVersion = package.GetMetadata("Version"); + if (string.IsNullOrEmpty(packageVersion)) + { + Log.LogError("Missing version information for package {0}", packageName); + continue; + } + + var packageVersionValue = GetDependencyVersion(dependencyVersionType, packageName, packageVersion); + Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersionValue}"); + + var packageReferenceElement = xmlDoc.CreateElement("PackageReference"); + packageReferenceElement.SetAttribute("Include", packageName); + packageReferenceElement.SetAttribute("Version", packageVersionValue); + packageReferenceElement.SetAttribute("PrivateAssets", "None"); + + itemGroupElement.AppendChild(packageReferenceElement); + } + + foreach (var package in externalArtifacts) + { + var packageName = package.ItemSpec; + var packageVersion = package.GetMetadata("Version"); + + if (string.IsNullOrEmpty(packageVersion)) + { + Log.LogError("Missing version information for package {0}", packageName); + continue; + } + + var packageVersionValue = + Enum.TryParse(package.GetMetadata("MetapackageVersionRangeType"), out var packageVersionType) + ? GetDependencyVersion(packageVersionType, packageName, packageVersion) + : GetDependencyVersion(dependencyVersionType, packageName, packageVersion); + + Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersionValue}"); + + var packageReferenceElement = xmlDoc.CreateElement("PackageReference"); + packageReferenceElement.SetAttribute("Include", packageName); + packageReferenceElement.SetAttribute("Version", packageVersionValue); + packageReferenceElement.SetAttribute("PrivateAssets", "None"); + + itemGroupElement.AppendChild(packageReferenceElement); + } + + projectElement.AppendChild(itemGroupElement); + + // Save updated file + xmlDoc.AppendChild(projectElement); + xmlDoc.Save(ReferencePackagePath); + + return !Log.HasLoggedErrors; + } + + private string GetDependencyVersion(VersionRangeType dependencyVersionType, string packageName, string packageVersion) + { + switch (dependencyVersionType) + { + case VersionRangeType.MajorMinor: + if (!NuGetVersion.TryParse(packageVersion, out var nugetVersion)) + { + Log.LogError("Invalid NuGet version '{0}' for package {1}", packageVersion, packageName); + return null; + } + return $"[{packageVersion}, {nugetVersion.Major}.{nugetVersion.Minor + 1}.0)"; + case VersionRangeType.Minimum: + return packageVersion; + default: + throw new NotImplementedException(); + } + } + } +} diff --git a/build/tasks/CheckExpectedPackagesExist.cs b/build/tasks/CheckExpectedPackagesExist.cs new file mode 100644 index 0000000000..0df55e5d47 --- /dev/null +++ b/build/tasks/CheckExpectedPackagesExist.cs @@ -0,0 +1,69 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Microsoft.Build.Framework; +using NuGet.Packaging; +using NuGet.Packaging.Core; +using RepoTasks.Utilities; + +namespace RepoTasks +{ + public class CheckExpectedPackagesExist : Microsoft.Build.Utilities.Task + { + /// + /// The item group containing the nuget packages to split in different folders. + /// + [Required] + public ITaskItem[] Packages { get; set; } + + [Required] + public ITaskItem[] Files { get; set; } + + public override bool Execute() + { + if (Files?.Length == 0) + { + Log.LogError("No packages were found."); + return false; + } + + var expectedPackages = new HashSet(Packages.Select(i => i.ItemSpec), StringComparer.OrdinalIgnoreCase); + + foreach (var file in Files) + { + PackageIdentity identity; + using (var reader = new PackageArchiveReader(file.ItemSpec)) + { + identity = reader.GetIdentity(); + } + + if (!expectedPackages.Contains(identity.Id)) + { + Log.LogError($"Unexpected package artifact with id: {identity.Id}"); + continue; + } + + expectedPackages.Remove(identity.Id); + } + + if (expectedPackages.Count != 0) + { + var error = new StringBuilder(); + foreach (var id in expectedPackages) + { + error.Append(" - ").AppendLine(id); + } + + Log.LogError($"Expected the following packages, but they were not found:" + error.ToString()); + return false; + } + + return !Log.HasLoggedErrors; + } + } +} diff --git a/build/tasks/CheckVersionOverrides.cs b/build/tasks/CheckVersionOverrides.cs new file mode 100644 index 0000000000..ad75aa8b2b --- /dev/null +++ b/build/tasks/CheckVersionOverrides.cs @@ -0,0 +1,45 @@ +// 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.Build.Construction; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace RepoTasks +{ + public class CheckVersionOverrides : Task + { + [Required] + public string DotNetPackageVersionPropsPath { get; set; } + + [Required] + public string DependenciesFile { get; set; } + + public override bool Execute() + { + Log.LogMessage($"Verifying versions set in {DotNetPackageVersionPropsPath} match expected versions set in {DependenciesFile}"); + + var versionOverrides = ProjectRootElement.Open(DotNetPackageVersionPropsPath); + var dependencies = ProjectRootElement.Open(DependenciesFile); + var pinnedVersions = dependencies.PropertyGroups + .Where(p => !string.Equals("Package Versions: Auto", p.Label)) + .SelectMany(p => p.Properties) + .ToDictionary(p => p.Name, p => p.Value, StringComparer.OrdinalIgnoreCase); + + foreach (var prop in versionOverrides.Properties) + { + if (pinnedVersions.TryGetValue(prop.Name, out var pinnedVersion)) + { + if (!string.Equals(pinnedVersion, prop.Value, StringComparison.OrdinalIgnoreCase)) + { + Log.LogError($"The imported package version props file conflicts with a pinned version variable {prop.Name}. Imported value: {prop.Value}, Pinned value: {pinnedVersion}"); + } + } + } + + return !Log.HasLoggedErrors; + } + } +} diff --git a/build/tasks/CreateLzma.cs b/build/tasks/CreateLzma.cs new file mode 100644 index 0000000000..96e3d403b7 --- /dev/null +++ b/build/tasks/CreateLzma.cs @@ -0,0 +1,70 @@ +// 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.IO; +using System.Threading; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Microsoft.DotNet.Archive; + +namespace RepoTasks +{ + public class CreateLzma : Task, ICancelableTask + { + private readonly CancellationTokenSource _cts = new CancellationTokenSource(); + + [Required] + public string OutputPath { get; set; } + + [Required] + public string[] Sources { get; set; } + + public void Cancel() => _cts.Cancel(); + + public override bool Execute() + { + var progress = new MSBuildProgressReport(Log, _cts.Token); + using (var archive = new IndexedArchive()) + { + foreach (var source in Sources) + { + if (Directory.Exists(source)) + { + var trimmedSource = source.TrimEnd(new []{ '\\', '/' }); + Log.LogMessage(MessageImportance.High, $"Adding directory: {trimmedSource}"); + archive.AddDirectory(trimmedSource, progress); + } + else + { + Log.LogMessage(MessageImportance.High, $"Adding file: {source}"); + archive.AddFile(source, Path.GetFileName(source)); + } + } + + archive.Save(OutputPath, progress); + } + + return !Log.HasLoggedErrors; + } + + private class MSBuildProgressReport : IProgress + { + private TaskLoggingHelper _log; + private readonly CancellationToken _cancellationToken; + + public MSBuildProgressReport(TaskLoggingHelper log, CancellationToken cancellationToken) + { + _log = log; + _cancellationToken = cancellationToken; + } + + public void Report(ProgressReport value) + { + var complete = (double)value.Ticks / value.Total; + _log.LogMessage(MessageImportance.Low, $"Progress: {value.Phase} - {complete:P}"); + _cancellationToken.ThrowIfCancellationRequested(); // because LZMA apis don't take a cancellation token, throw from the logger (yes, its ugly, but it works.) + } + } + } +} diff --git a/build/tasks/GenerateRestoreSourcesPropsFile.cs b/build/tasks/GenerateRestoreSourcesPropsFile.cs new file mode 100644 index 0000000000..2d27ba4e6a --- /dev/null +++ b/build/tasks/GenerateRestoreSourcesPropsFile.cs @@ -0,0 +1,55 @@ +// 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 System.IO; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace RepoTasks +{ + public class GenerateRestoreSourcesPropsFile : Task + { + [Required] + public ITaskItem[] Sources { get; set; } + + [Required] + public string OutputPath { get; set; } + + public override bool Execute() + { + OutputPath = OutputPath.Replace('\\', '/'); + Directory.CreateDirectory(Path.GetDirectoryName(OutputPath)); + + var sources = new XElement("DotNetRestoreSources"); + var propertyGroup = new XElement("PropertyGroup", sources); + var doc = new XDocument(new XElement("Project", propertyGroup)); + + propertyGroup.Add(new XElement("MSBuildAllProjects", "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)")); + + var sb = new StringBuilder(); + + foreach (var source in Sources) + { + sb.Append(source.ItemSpec).AppendLine(";"); + } + + sources.SetValue(sb.ToString()); + + var settings = new XmlWriterSettings + { + OmitXmlDeclaration = true, + }; + using (var writer = XmlWriter.Create(OutputPath, settings)) + { + Log.LogMessage(MessageImportance.Normal, $"Generate {OutputPath}"); + doc.Save(writer); + } + return !Log.HasLoggedErrors; + } + } +} diff --git a/build/tasks/GetDocXmlFiles.cs b/build/tasks/GetDocXmlFiles.cs new file mode 100644 index 0000000000..9053f0c6ad --- /dev/null +++ b/build/tasks/GetDocXmlFiles.cs @@ -0,0 +1,64 @@ +// 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 Microsoft.Build.Framework; +using System; +using System.Collections.Concurrent; +using System.IO; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace RepoTasks +{ + /// + /// Filters a list of .xml files to only those that are .NET Xml docs files + /// + public class GetDocXmlFiles : Microsoft.Build.Utilities.Task + { + [Required] + public ITaskItem[] Files { get; set; } + + [Output] + public ITaskItem[] XmlDocFiles { get; set; } + + public override bool Execute() + { + var xmlDocs = new ConcurrentBag(); + Parallel.ForEach(Files, f => + { + try + { + using (var file = File.OpenRead(f.ItemSpec)) + using (var reader = new StreamReader(file)) + { + string line; + for (var i = 0; i < 2; i++) + { + line = reader.ReadLine(); + if (i == 0 && line.StartsWith("") + 2); + } + + if (line.StartsWith("", StringComparison.OrdinalIgnoreCase) || line.StartsWith(" GetKeyValue(LeftKey, item), + item => GetKeyValue(RightKey, item), + (left, right) => + { + // If including all metadata from left items and none from right items, just return left items directly + if (useAllLeftMetadata && + string.IsNullOrEmpty(LeftKey) && + string.IsNullOrEmpty(LeftItemSpec) && + (RightMetadata == null || RightMetadata.Length == 0)) + { + return left; + } + + // If including all metadata from right items and none from left items, just return the right items directly + if (useAllRightMetadata && + string.IsNullOrEmpty(RightKey) && + string.IsNullOrEmpty(LeftItemSpec) && + (LeftMetadata == null || LeftMetadata.Length == 0)) + { + return right; + } + + var ret = new TaskItem(GetKeyValue(newItemSpec, left)); + + // Weird ordering here is to prefer left metadata in all cases, as CopyToMetadata doesn't overwrite any existing metadata + if (useAllLeftMetadata) + { + // CopyMetadata adds an OriginalItemSpec, which we don't want. So we subsequently remove it + left.CopyMetadataTo(ret); + ret.RemoveMetadata("OriginalItemSpec"); + } + + if (!useAllRightMetadata && RightMetadata != null) + { + foreach (string name in RightMetadata) + { + ret.SetMetadata(name, right.GetMetadata(name)); + } + } + + if (!useAllLeftMetadata && LeftMetadata != null) + { + foreach (string name in LeftMetadata) + { + ret.SetMetadata(name, left.GetMetadata(name)); + } + } + + if (useAllRightMetadata) + { + // CopyMetadata adds an OriginalItemSpec, which we don't want. So we subsequently remove it + right.CopyMetadataTo(ret); + ret.RemoveMetadata("OriginalItemSpec"); + } + + return (ITaskItem)ret; + }, + StringComparer.OrdinalIgnoreCase).ToArray(); + + return true; + } + + static string GetKeyValue(string key, ITaskItem item) + { + if (string.IsNullOrEmpty(key)) + { + return item.ItemSpec; + } + else + { + return item.GetMetadata(key); + } + } + } +} diff --git a/build/tasks/Logger/FlowLogger.cs b/build/tasks/Logger/FlowLogger.cs new file mode 100644 index 0000000000..e6a214fdff --- /dev/null +++ b/build/tasks/Logger/FlowLogger.cs @@ -0,0 +1,61 @@ +// 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.Build.Framework; +using Microsoft.Build.Logging; + +namespace RepoTasks +{ + public class FlowLogger : ConsoleLogger + { + private volatile bool _initialized; + + public FlowLogger() + { + } + + public override void Initialize(IEventSource eventSource, int nodeCount) + { + PreInit(eventSource); + base.Initialize(eventSource, nodeCount); + } + + public override void Initialize(IEventSource eventSource) + { + PreInit(eventSource); + base.Initialize(eventSource); + } + + private void PreInit(IEventSource eventSource) + { + if (_initialized) return; + _initialized = true; + + var flowId = GetFlowId(); + var prefix = $"{flowId,-22}| "; + var write = WriteHandler; + WriteHandler = msg => write(prefix + msg); + + eventSource.BuildStarted += (o, e) => + { + WriteHandler(e.Message + Environment.NewLine); + }; + } + + private string GetFlowId() + { + var parameters = Parameters?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + if (parameters == null || parameters.Length == 0) + { + return null; + } + + const string flowIdParamName = "FlowId="; + return parameters + .FirstOrDefault(p => p.StartsWith(flowIdParamName, StringComparison.Ordinal)) + ?.Substring(flowIdParamName.Length); + } + } +} diff --git a/build/tasks/Logger/MSBuildLogger.cs b/build/tasks/Logger/MSBuildLogger.cs new file mode 100644 index 0000000000..458bd698d9 --- /dev/null +++ b/build/tasks/Logger/MSBuildLogger.cs @@ -0,0 +1,200 @@ +// 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 Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using NuGet.Common; + +namespace NuGet.Build +{ + /// + /// TaskLoggingHelper -> ILogger + /// + internal class MSBuildLogger : LoggerBase, Common.ILogger + { + private readonly TaskLoggingHelper _taskLogging; + + private delegate void LogMessageWithDetails(string subcategory, + string code, + string helpKeyword, + string file, + int lineNumber, + int columnNumber, + int endLineNumber, + int endColumnNumber, + MessageImportance importance, + string message, + params object[] messageArgs); + + private delegate void LogErrorWithDetails(string subcategory, + string code, + string helpKeyword, + string file, + int lineNumber, + int columnNumber, + int endLineNumber, + int endColumnNumber, + string message, + params object[] messageArgs); + + private delegate void LogMessageAsString(MessageImportance importance, + string message, + params object[] messageArgs); + + private delegate void LogErrorAsString(string message, + params object[] messageArgs); + + public MSBuildLogger(TaskLoggingHelper taskLogging) + { + _taskLogging = taskLogging ?? throw new ArgumentNullException(nameof(taskLogging)); + } + + public override void Log(ILogMessage message) + { + if (DisplayMessage(message.Level)) + { + if (RuntimeEnvironmentHelper.IsMono) + { + LogForMono(message); + return; + } + else + { + var logMessage = message as IRestoreLogMessage; + + if (logMessage == null) + { + logMessage = new RestoreLogMessage(message.Level, message.Message) + { + Code = message.Code, + FilePath = message.ProjectPath + }; + } + LogForNonMono(logMessage); + } + } + } + + /// + /// Log using with metadata for non mono platforms. + /// + private void LogForNonMono(IRestoreLogMessage message) + { + switch (message.Level) + { + case LogLevel.Error: + LogError(message, _taskLogging.LogError, _taskLogging.LogError); + break; + + case LogLevel.Warning: + LogError(message, _taskLogging.LogWarning, _taskLogging.LogWarning); + break; + + case LogLevel.Minimal: + LogMessage(message, MessageImportance.High, _taskLogging.LogMessage, _taskLogging.LogMessage); + break; + + case LogLevel.Information: + LogMessage(message, MessageImportance.Normal, _taskLogging.LogMessage, _taskLogging.LogMessage); + break; + + case LogLevel.Debug: + case LogLevel.Verbose: + default: + // Default to LogLevel.Debug and low importance + LogMessage(message, MessageImportance.Low, _taskLogging.LogMessage, _taskLogging.LogMessage); + break; + } + } + + /// + /// Log using basic methods to avoid missing methods on mono. + /// + private void LogForMono(ILogMessage message) + { + switch (message.Level) + { + case LogLevel.Error: + _taskLogging.LogError(message.Message); + break; + + case LogLevel.Warning: + _taskLogging.LogWarning(message.Message); + break; + + case LogLevel.Minimal: + _taskLogging.LogMessage(MessageImportance.High, message.Message); + break; + + case LogLevel.Information: + _taskLogging.LogMessage(MessageImportance.Normal, message.Message); + break; + + case LogLevel.Debug: + case LogLevel.Verbose: + default: + // Default to LogLevel.Debug and low importance + _taskLogging.LogMessage(MessageImportance.Low, message.Message); + break; + } + + return; + } + + private void LogMessage(IRestoreLogMessage logMessage, + MessageImportance importance, + LogMessageWithDetails logWithDetails, + LogMessageAsString logAsString) + { + if (logMessage.Code > NuGetLogCode.Undefined) + { + // NuGet does not currently have a subcategory while throwing logs, hence string.Empty + logWithDetails(string.Empty, + Enum.GetName(typeof(NuGetLogCode), logMessage.Code), + Enum.GetName(typeof(NuGetLogCode), logMessage.Code), + logMessage.FilePath, + logMessage.StartLineNumber, + logMessage.StartColumnNumber, + logMessage.EndLineNumber, + logMessage.EndColumnNumber, + importance, + logMessage.Message); + } + else + { + logAsString(importance, logMessage.Message); + } + } + + private void LogError(IRestoreLogMessage logMessage, + LogErrorWithDetails logWithDetails, + LogErrorAsString logAsString) + { + if (logMessage.Code > NuGetLogCode.Undefined) + { + // NuGet does not currently have a subcategory while throwing logs, hence string.Empty + logWithDetails(string.Empty, + Enum.GetName(typeof(NuGetLogCode), logMessage.Code), + Enum.GetName(typeof(NuGetLogCode), logMessage.Code), + logMessage.FilePath, + logMessage.StartLineNumber, + logMessage.StartColumnNumber, + logMessage.EndLineNumber, + logMessage.EndColumnNumber, + logMessage.Message); + } + else + { + logAsString(logMessage.Message); + } + } + + public override System.Threading.Tasks.Task LogAsync(ILogMessage message) + { + Log(message); + + return System.Threading.Tasks.Task.FromResult(0); + } + } +} diff --git a/build/tasks/OrderBy.cs b/build/tasks/OrderBy.cs new file mode 100644 index 0000000000..a761d6f093 --- /dev/null +++ b/build/tasks/OrderBy.cs @@ -0,0 +1,28 @@ +// 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.Build.Framework; +using Microsoft.Build.Utilities; + +namespace RepoTasks +{ + public class OrderBy : Task + { + [Required] + [Output] + public ITaskItem[] Items { get; set; } + + public string Key { get; set; } + + public override bool Execute() + { + var key = string.IsNullOrEmpty(Key) + ? "Identity" + : Key; + Items = Items.OrderBy(k => k.GetMetadata(key)).ToArray(); + return true; + } + } +} diff --git a/build/tasks/ProcessSharedFrameworkDeps.cs b/build/tasks/ProcessSharedFrameworkDeps.cs new file mode 100644 index 0000000000..87250780a8 --- /dev/null +++ b/build/tasks/ProcessSharedFrameworkDeps.cs @@ -0,0 +1,76 @@ +// 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. +// Sourced from https://github.com/dotnet/core-setup/tree/be8d8e3486b2bf598ed69d39b1629a24caaba45e/tools-local/tasks, needs to be kept in sync + +using System; +using System.IO; +using System.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Microsoft.Extensions.DependencyModel; +using NuGet.Common; +using NuGet.ProjectModel; +using RepoTasks.Utilities; + +namespace RepoTasks +{ + public partial class ProcessSharedFrameworkDeps : Task + { + [Required] + public string AssetsFilePath { get; set; } + + [Required] + public string DepsFilePath { get; set; } + + public string[] PackagesToRemove { get; set; } + + [Required] + public string Runtime { get; set; } + + public override bool Execute() + { + ExecuteCore(); + + return true; + } + + private void ExecuteCore() + { + DependencyContext context; + using (var depsStream = File.OpenRead(DepsFilePath)) + { + context = new DependencyContextJsonReader().Read(depsStream); + } + + LockFile lockFile = LockFileUtilities.GetLockFile(AssetsFilePath, NullLogger.Instance); + if (lockFile == null) + { + throw new ArgumentException($"Could not load a LockFile at '{AssetsFilePath}'.", nameof(AssetsFilePath)); + } + + var manager = new RuntimeGraphManager(); + var graph = manager.Collect(lockFile); + var expandedGraph = manager.Expand(graph, Runtime); + + var trimmedRuntimeLibraries = context.RuntimeLibraries; + + if (PackagesToRemove != null && PackagesToRemove.Any()) + { + trimmedRuntimeLibraries = RuntimeReference.RemoveReferences(context.RuntimeLibraries, PackagesToRemove); + } + + context = new DependencyContext( + context.Target, + context.CompilationOptions, + context.CompileLibraries, + trimmedRuntimeLibraries, + expandedGraph + ); + + using (var depsStream = File.Create(DepsFilePath)) + { + new DependencyContextWriter().Write(context, depsStream); + } + } + } +} \ No newline at end of file diff --git a/build/tasks/PublishToAzureBlob.cs b/build/tasks/PublishToAzureBlob.cs new file mode 100644 index 0000000000..86150d0be3 --- /dev/null +++ b/build/tasks/PublishToAzureBlob.cs @@ -0,0 +1,144 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Build.Framework; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Blob; + +namespace RepoTasks +{ + /// + /// Publish files to an Azure storage blob + /// + public class PublishToAzureBlob : Microsoft.Build.Utilities.Task, ICancelableTask + { + private CancellationTokenSource _cts = new CancellationTokenSource(); + + /// + /// The files to publish. + /// + [Required] + public ITaskItem[] Files { get; set; } + + /// + /// The Azure blob storage account name. + /// + [Required] + public string AccountName { get; set; } + + /// + /// The SAS token used to write to Azure. + /// + [Required] + public string SharedAccessToken { get; set; } + + /// + /// The Azure blob storage container name + /// + [Required] + public string ContainerName { get; set; } + + /// + /// The maximum number of parallel pushes. + /// + public int MaxParallelism { get; set; } = 8; + + public void Cancel() => _cts.Cancel(); + + public override bool Execute() + => ExecuteAsync().Result; + + private async Task ExecuteAsync() + { + var connectionString = $"BlobEndpoint=https://{AccountName}.blob.core.windows.net;SharedAccessSignature={SharedAccessToken}"; + + var account = CloudStorageAccount.Parse(connectionString); + var client = account.CreateCloudBlobClient(); + var container = client.GetContainerReference(ContainerName); + + var ctx = new OperationContext(); + var tasks = new List(); + + using (var throttler = new SemaphoreSlim(MaxParallelism)) + { + foreach (var item in Files) + { + _cts.Token.ThrowIfCancellationRequested(); + await throttler.WaitAsync( _cts.Token); + tasks.Add( + Task.Run(async () => + { + try + { + await PushFileAsync(ctx, container, item, _cts.Token); + } + finally + { + throttler.Release(); + } + })); + } + + await Task.WhenAll(tasks); + } + + return !Log.HasLoggedErrors; + } + + private async Task PushFileAsync(OperationContext ctx, CloudBlobContainer container, ITaskItem item, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + // normalize slashes + var dest = item.GetMetadata("RelativeBlobPath") + .Replace('\\', '/') + .Replace("//", "/"); + var contentType = item.GetMetadata("ContentType"); + var cacheControl = item.GetMetadata("CacheControl"); + + if (string.IsNullOrEmpty(dest)) + { + Log.LogError($"Item {item.ItemSpec} is missing required metadata 'RelativeBlobPath'"); + return; + } + + var blob = container.GetBlockBlobReference(dest); + + if (!string.IsNullOrEmpty(cacheControl)) + { + blob.Properties.CacheControl = cacheControl; + } + + if (!string.IsNullOrEmpty(contentType)) + { + blob.Properties.ContentType = contentType; + } + + Log.LogMessage(MessageImportance.High, $"Beginning push of {item.ItemSpec} to https://{AccountName}.blob.core.windows.net/{ContainerName}/{dest}"); + + var accessCondition = bool.TryParse(item.GetMetadata("Overwrite"), out var overwrite) && overwrite + ? AccessCondition.GenerateEmptyCondition() + : AccessCondition.GenerateIfNotExistsCondition(); + + try + { + await blob.UploadFromFileAsync(item.ItemSpec, accessCondition, new BlobRequestOptions(), ctx, cancellationToken); + } + catch (Exception ex) + { + Log.LogError($"Error publishing {item.ItemSpec}: {ex}"); + return; + } + finally + { + Log.LogMessage(MessageImportance.High, $"Done publishing {item.ItemSpec} to https://{AccountName}.blob.core.windows.net/{ContainerName}/{dest}"); + } + } + } +} diff --git a/build/tasks/RepoTasks.csproj b/build/tasks/RepoTasks.csproj new file mode 100644 index 0000000000..6be1f375d2 --- /dev/null +++ b/build/tasks/RepoTasks.csproj @@ -0,0 +1,17 @@ + + + + + netcoreapp2.0 + + + + + + + + + + + + diff --git a/build/tasks/RepoTasks.tasks b/build/tasks/RepoTasks.tasks new file mode 100644 index 0000000000..5339c01d01 --- /dev/null +++ b/build/tasks/RepoTasks.tasks @@ -0,0 +1,29 @@ + + + <_RepoTaskAssembly>$(MSBuildThisFileDirectory)bin\publish\RepoTasks.dll + + + + + + + + + + + + + + + + + + $(NUGET_PACKAGES) + $(USERPROFILE)\.nuget\packages\ + $(HOME)\.nuget\packages\ + $([MSBuild]::NormalizeDirectory($(NuGetPackagesPath))) + <_MicrosoftDotNetBuildTasksFeedTaskDir>$(NuGetPackagesPath)microsoft.dotnet.build.tasks.feed\$(DevDependency_MicrosoftDotNetBuildTasksFeedPackageVersion.ToLowerInvariant())\build\netstandard1.5\ + + + + diff --git a/build/tasks/ResolveSymbolsRecursivePath.cs b/build/tasks/ResolveSymbolsRecursivePath.cs new file mode 100644 index 0000000000..21dd795fcd --- /dev/null +++ b/build/tasks/ResolveSymbolsRecursivePath.cs @@ -0,0 +1,29 @@ +// 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.IO; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using RepoTasks.Utilities; + +namespace RepoTasks +{ + public class ResolveSymbolsRecursivePath : Task + { + [Required] + [Output] + public ITaskItem[] Symbols { get; set; } + + public override bool Execute() + { + foreach (var symbol in Symbols) + { + var fullPath = symbol.GetMetadata("PortablePDB"); + symbol.SetMetadata("SymbolsRecursivePath", fullPath.Substring(fullPath.IndexOf($"{Path.DirectorySeparatorChar}lib{Path.DirectorySeparatorChar}"))); + } + + return true; + } + } +} diff --git a/build/tasks/TrimDeps.cs b/build/tasks/TrimDeps.cs new file mode 100644 index 0000000000..b63bdb35cc --- /dev/null +++ b/build/tasks/TrimDeps.cs @@ -0,0 +1,60 @@ +// 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.IO; +using System.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace RepoTasks +{ + public class TrimDeps : Task + { + [Required] + public ITaskItem[] DepsFiles { get; set; } + + public override bool Execute() + { + foreach (var depsFile in DepsFiles) + { + ChangeEntryPointLibraryName(depsFile.GetMetadata("Identity")); + } + + // Parse input + return true; + } + + + private void ChangeEntryPointLibraryName(string depsFile) + { + JToken deps; + using (var file = File.OpenText(depsFile)) + using (JsonTextReader reader = new JsonTextReader(file)) + { + deps = JObject.ReadFrom(reader); + } + + foreach (JProperty target in deps["targets"]) + { + var targetLibrary = target.Value.Children().FirstOrDefault(); + if (targetLibrary == null) + { + continue; + } + + targetLibrary.Remove(); + } + + var library = deps["libraries"].Children().First(); + library.Remove(); + + using (var file = File.CreateText(depsFile)) + using (var writer = new JsonTextWriter(file) { Formatting = Formatting.Indented }) + { + deps.WriteTo(writer); + } + } + } +} diff --git a/build/tasks/Utilities/RuntimeGraphManager.cs b/build/tasks/Utilities/RuntimeGraphManager.cs new file mode 100644 index 0000000000..d3552f36be --- /dev/null +++ b/build/tasks/Utilities/RuntimeGraphManager.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Sourced from https://github.com/dotnet/core-setup/tree/be8d8e3486b2bf598ed69d39b1629a24caaba45e/tools-local/tasks, needs to be kept in sync + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Extensions.DependencyModel; +using NuGet.Frameworks; +using NuGet.Packaging; +using NuGet.ProjectModel; +using NuGet.RuntimeModel; + +namespace RepoTasks.Utilities +{ + internal class RuntimeGraphManager + { + private const string RuntimeJsonFileName = "runtime.json"; + + public RuntimeGraph Collect(LockFile lockFile) + { + string userPackageFolder = lockFile.PackageFolders.FirstOrDefault()?.Path; + var fallBackFolders = lockFile.PackageFolders.Skip(1).Select(f => f.Path); + var packageResolver = new FallbackPackagePathResolver(userPackageFolder, fallBackFolders); + + var graph = RuntimeGraph.Empty; + foreach (var library in lockFile.Libraries) + { + if (string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase)) + { + var runtimeJson = library.Files.FirstOrDefault(f => f == RuntimeJsonFileName); + if (runtimeJson != null) + { + var libraryPath = packageResolver.GetPackageDirectory(library.Name, library.Version); + var runtimeJsonFullName = Path.Combine(libraryPath, runtimeJson); + graph = RuntimeGraph.Merge(graph, JsonRuntimeFormat.ReadRuntimeGraph(runtimeJsonFullName)); + } + } + } + return graph; + } + + public IEnumerable Expand(RuntimeGraph runtimeGraph, string runtime) + { + var importers = FindImporters(runtimeGraph, runtime); + foreach (var importer in importers) + { + // ExpandRuntime return runtime itself as first item so we are skiping it + yield return new RuntimeFallbacks(importer, runtimeGraph.ExpandRuntime(importer).Skip(1)); + } + } + + private IEnumerable FindImporters(RuntimeGraph runtimeGraph, string runtime) + { + foreach (var runtimePair in runtimeGraph.Runtimes) + { + var expanded = runtimeGraph.ExpandRuntime(runtimePair.Key); + if (expanded.Contains(runtime)) + { + yield return runtimePair.Key; + } + } + } + } +} \ No newline at end of file diff --git a/build/tasks/Utilities/RuntimeReference.cs b/build/tasks/Utilities/RuntimeReference.cs new file mode 100644 index 0000000000..4907a73723 --- /dev/null +++ b/build/tasks/Utilities/RuntimeReference.cs @@ -0,0 +1,63 @@ +// 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. +// Sourced from https://github.com/dotnet/core-setup/tree/be8d8e3486b2bf598ed69d39b1629a24caaba45e/tools-local/tasks, needs to be kept in sync + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.DependencyModel; + +namespace RepoTasks.Utilities +{ + internal class RuntimeReference + { + public static List RemoveReferences(IReadOnlyList runtimeLibraries, IEnumerable packages) + { + List result = new List(); + + foreach (var runtimeLib in runtimeLibraries) + { + if (string.IsNullOrEmpty(packages.FirstOrDefault(elem => runtimeLib.Name.Equals(elem, StringComparison.OrdinalIgnoreCase)))) + { + List toRemoveDependecy = new List(); + foreach (var dependency in runtimeLib.Dependencies) + { + if (!string.IsNullOrEmpty(packages.FirstOrDefault(elem => dependency.Name.Equals(elem, StringComparison.OrdinalIgnoreCase)))) + { + toRemoveDependecy.Add(dependency); + } + } + + if (toRemoveDependecy.Count > 0) + { + List modifiedDependencies = new List(); + foreach (var dependency in runtimeLib.Dependencies) + { + if (!toRemoveDependecy.Contains(dependency)) + { + modifiedDependencies.Add(dependency); + } + } + + + result.Add(new RuntimeLibrary(runtimeLib.Type, + runtimeLib.Name, + runtimeLib.Version, + runtimeLib.Hash, + runtimeLib.RuntimeAssemblyGroups, + runtimeLib.NativeLibraryGroups, + runtimeLib.ResourceAssemblies, + modifiedDependencies, + runtimeLib.Serviceable)); + + } + else if (string.IsNullOrEmpty(packages.FirstOrDefault(elem => runtimeLib.Name.Equals(elem, StringComparison.OrdinalIgnoreCase)))) + { + result.Add(runtimeLib); + } + } + } + return result; + } + } +} \ No newline at end of file diff --git a/build/tasks/tasks.sln b/build/tasks/tasks.sln new file mode 100644 index 0000000000..917ff4ff83 --- /dev/null +++ b/build/tasks/tasks.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RepoTasks", "RepoTasks.csproj", "{A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}" +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(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Debug|x64.ActiveCfg = Debug|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Debug|x64.Build.0 = Debug|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Debug|x86.ActiveCfg = Debug|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Debug|x86.Build.0 = Debug|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Release|Any CPU.Build.0 = Release|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Release|x64.ActiveCfg = Release|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Release|x64.Build.0 = Release|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Release|x86.ActiveCfg = Release|Any CPU + {A114791F-35B7-4E5B-8E5B-9A91E0B6E4AE}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/build/tools/docker/rhel.7/Dockerfile b/build/tools/docker/rhel.7/Dockerfile new file mode 100644 index 0000000000..331cb6335b --- /dev/null +++ b/build/tools/docker/rhel.7/Dockerfile @@ -0,0 +1,23 @@ +# +# 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. +# + +# Dockerfile that creates a container suitable to build dotnet-cli +FROM microsoft/dotnet-buildtools-prereqs:rhel-7-rpmpkg-e1b4a89-20175311035359 + +# Setup User to match Host User, and give superuser permissions +ARG USER_ID=0 +RUN useradd -m code_executor -u ${USER_ID} -g root +RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +# With the User Change, we need to change permssions on these directories +RUN chmod -R a+rwx /usr/local +RUN chmod -R a+rwx /home +RUN chown root:root /usr/bin/sudo && chmod 4755 /usr/bin/sudo + +# Set user to the one we just created +USER ${USER_ID} + +# Set working directory +WORKDIR /opt/code diff --git a/build/tools/docker/ubuntu.14.04/Dockerfile b/build/tools/docker/ubuntu.14.04/Dockerfile new file mode 100644 index 0000000000..f039506971 --- /dev/null +++ b/build/tools/docker/ubuntu.14.04/Dockerfile @@ -0,0 +1,52 @@ +# +# 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. +# + +# Dockerfile that creates a container suitable to build dotnet-cli +FROM ubuntu:14.04 + +# Misc Dependencies for build +RUN apt-get update && \ + apt-get -qqy install \ + curl \ + unzip \ + gettext \ + sudo \ + libunwind8 \ + libkrb5-3 \ + libicu52 \ + liblttng-ust0 \ + libssl1.0.0 \ + zlib1g \ + libuuid1 \ + debhelper \ + build-essential \ + devscripts \ + git \ + cmake \ + clang-3.5 \ + lldb-3.6 \ + wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Use clang as c++ compiler +RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-3.5 100 +RUN update-alternatives --set c++ /usr/bin/clang++-3.5 + +# Setup User to match Host User, and give superuser permissions +ARG USER_ID=0 +RUN useradd -m code_executor -u ${USER_ID} -g sudo +RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +# With the User Change, we need to change permissions on these directories +RUN chmod -R a+rwx /usr/local +RUN chmod -R a+rwx /home +RUN chmod -R 755 /usr/lib/sudo + +# Set user to the one we just created +USER ${USER_ID} + +# Set working directory +WORKDIR /opt/code diff --git a/build/tools/packaging/changelog.in b/build/tools/packaging/changelog.in new file mode 100644 index 0000000000..9196011924 --- /dev/null +++ b/build/tools/packaging/changelog.in @@ -0,0 +1,2 @@ +* ${DATE} ${MAINTAINER_NAME} <${MAINTAINER_EMAIL}> - ${PACKAGE_VERSION}-${PACKAGE_REVISION} +- \ No newline at end of file diff --git a/build/tools/packaging/debian_config.json.in b/build/tools/packaging/debian_config.json.in new file mode 100644 index 0000000000..d7449760c4 --- /dev/null +++ b/build/tools/packaging/debian_config.json.in @@ -0,0 +1,34 @@ +{ + "maintainer_name": "${MAINTAINER_NAME}", + "maintainer_email": "${MAINTAINER_EMAIL}", + + "package_name": "${PACKAGE_NAME}", + "install_root": "${INSTALL_ROOT}", + + "short_description": "${SHORT_DESCRIPTION}", + "long_description": "${LONG_DESCRIPTION}", + "homepage": "${HOMEPAGE}", + + "release":{ + "package_version":"0.0.0.0", + "package_revision":"${PACKAGE_REVISION}", + "urgency" : "low", + "changelog_message" : "" + }, + + "control": { + "priority":"standard", + "section":"devel", + "architecture":"any" + }, + + "copyright": "Microsoft", + "license": { + "type": "${LICENSE_TYPE}", + "full_text": "Copyright (c) .NET Foundation. All rights reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\nthese files except in compliance with the License. You may obtain a copy of the\nLicense at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed\nunder the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\nCONDITIONS OF ANY KIND, either express or implied. See the License for the\nspecific language governing permissions and limitations under the License." + }, + + "debian_dependencies": { + ${DEBIAN_DEPENDENCIES} + } +} \ No newline at end of file diff --git a/build/tools/templates/SharedFx/SharedFx.csproj b/build/tools/templates/SharedFx/SharedFx.csproj new file mode 100644 index 0000000000..8070ebbfe6 --- /dev/null +++ b/build/tools/templates/SharedFx/SharedFx.csproj @@ -0,0 +1,35 @@ + + + + netcoreapp3.0 + true + true + + + + + + + + + + + + + + + + + + + + diff --git a/build/tools/templates/SharedFxSymbols/SharedFrameworkSymbols.nuspec b/build/tools/templates/SharedFxSymbols/SharedFrameworkSymbols.nuspec new file mode 100644 index 0000000000..1ba4b6c85d --- /dev/null +++ b/build/tools/templates/SharedFxSymbols/SharedFrameworkSymbols.nuspec @@ -0,0 +1,18 @@ + + + + $ID$ + $VERSION$ + $DESCRIPTION$ + Microsoft + Microsoft + Copyright © Microsoft Corporation + https://raw.githubusercontent.com/aspnet/Home/2.0.0/LICENSE.txt + https://go.microsoft.com/fwlink/?LinkID=288859 + https://asp.net + true + true + aspnetcore + + + diff --git a/dockerbuild.sh b/dockerbuild.sh new file mode 100755 index 0000000000..d401522921 --- /dev/null +++ b/dockerbuild.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# +# variables +# + +RESET="\033[0m" +RED="\033[0;31m" +YELLOW="\033[0;33m" +MAGENTA="\033[0;95m" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +build_args=() +docker_args=() + +# +# Functions +# +__usage() { + echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] ...]" + echo "" + echo "Arguments:" + echo " image The docker image to use." + echo " ... Arguments passed to the command. Variable number of arguments allowed." + echo "" + echo "Options:" + echo " -v, --volume An additional volume mount to add to the build container" + echo "" + echo "Description:" + echo " This will run build.sh inside the dockerfile as defined in build/docker/\$image.Dockerfile." + + if [[ "${1:-}" != '--no-exit' ]]; then + exit 2 + fi +} + + +__error() { + echo -e "${RED}error: $*${RESET}" 1>&2 +} + +__warn() { + echo -e "${YELLOW}warning: $*${RESET}" +} + +__machine_has() { + hash "$1" > /dev/null 2>&1 + return $? +} + +# +# main +# + +image="${1:-}" +shift || True + +while [[ $# -gt 0 ]]; do + case $1 in + -\?|-h|--help) + __usage --no-exit + exit 0 + ;; + -v|--volume) + shift + volume_spec="${1:-}" + [ -z "$volume_spec" ] && __error "Missing value for parameter --volume" && __usage + docker_args[${#docker_args[*]}]="--volume" + docker_args[${#docker_args[*]}]="$volume_spec" + ;; + *) + build_args[${#build_args[*]}]="$1" + ;; + esac + shift +done + +if [ -z "$image" ]; then + __usage --no-exit + __error 'Missing required argument: image' + exit 1 +fi + +if ! __machine_has docker; then + __error 'Missing required command: docker' + exit 1 +fi + +dockerfile="$DIR/build/docker/$image.Dockerfile" +tagname="universe-build-$image" + +docker build "$(dirname "$dockerfile")" \ + --build-arg "USER=$(whoami)" \ + --build-arg "USER_ID=$(id -u)" \ + --build-arg "GROUP_ID=$(id -g)" \ + --tag $tagname \ + -f "$dockerfile" + +docker run \ + --rm \ + -t \ + -e CI \ + -e TEAMCITY_VERSION \ + -e DOTNET_CLI_TELEMETRY_OPTOUT \ + -e Configuration \ + -v "$DIR:/code/build" \ + ${docker_args[@]+"${docker_args[@]}"} \ + $tagname \ + ./build.sh \ + ${build_args[@]+"${build_args[@]}"} \ + "-p:HostMachineRepositoryRoot=$DIR" diff --git a/docs/CrossRepoBreakingChanges.md b/docs/CrossRepoBreakingChanges.md new file mode 100644 index 0000000000..09299b4b37 --- /dev/null +++ b/docs/CrossRepoBreakingChanges.md @@ -0,0 +1,33 @@ +## A pattern for making cross-repo breaking changes + +The engineering team has come up with a pattern for making cross-repo breaking changes without destabilizing local \ CI builds using feature branches. I’ll explain it in terms of a breaking change in Configuration that affects Options: + +1) Start by making a feature branch in the Configuration repo. A feature branch is any branch that starts with the prefix "feature/" e.g. feature/bring-back-web-config + +`git checkout feature/bring-back-web-config` + +2) Make your changes in this feature branch and push it to GitHub. You can ordinarily continue using this branch to get your PR reviewed. +3) TeamCity's individual Project configuration (http://aspnetci/project.html?projectId=Lite&tab=projectOverview) has always built feature branches. We've enabled an additional step to it that pushes packages produced from feature branches to https://dotnet.myget.org/f/aspnetcore-dev. +Packages produced from feature branches will have a branch name suffix in their release label to distinguish them from our regular builds. For instance, a package produced for the branch pushed earlier might look like '2.1.0-preview2-bring-back-web-config-10012'. + +4) In the Options repo, create a working branch like you normally do: + +`git checkout prkrishn/react-to-config` + +5) Once again in the options repo, edit build/dependencies.props to reference the feature branch package that got produced. +a) If `build/dependencies.props` already has a reference to Configuration, update the version of the Options package in `build/dependencies.props` to point to the package produced from the feature branch. +b) If `build/dependencies.props` does not have a reference to the package version of Configuration, i.e. the package is transitively referenced: + * Add a new entry in `build/dependencies.props` + * And a PackageReference to the feature branch package in your project. + +```xml +// build/dependencies.props +2.1.0-preview2-bring-back-web-config-10012 +``` + +5) Now that you reference the package with breaking changes, make your fixup changes to Options. +6) Get your code reviewed +7) Check in to dev both sets of changes i.e. the feature branch from Configuration and your reaction changes in Options including changes to build/dependencies.props. +7) File a tracking task in Options to clean up build/dependencies.props. Build automation should fix up this version for you when it does it weekly update of dependencies.props, but it's good to manually verify that this is fixed up before we branch or create tags. + +**tl,dr**: Push feature branches. TeamCity will build packages with release labels derived from branch name. You can edit and check in changes to build/dependencies.props to reference these packages. diff --git a/docs/PackageArchives.md b/docs/PackageArchives.md new file mode 100644 index 0000000000..99ebe79cc3 --- /dev/null +++ b/docs/PackageArchives.md @@ -0,0 +1,68 @@ +Package Archives +================ + +This repo builds multiple package archives which contain a NuGet fallback folder (also known as the fallback or offline package cache). The fallback folder is a set of NuGet packages that is bundled in the .NET Core SDK installers and available in Azure Web App service. + +Package archives are available in four varieties. + +* **LZMA** - `nuGetPackagesArchive-$(Version).lzma` - The LZMA is a compressed file format, similar to a .zip. On first use or on install, the .NET Core CLI will expand this LZMA file, extracting the packages inside to %DOTNET_INSTALL_DIR%/sdk/NuGetFallbackFolder. This contains all NuGet packages and their complete contents. +* **ci-server** - `nuGetPackagesArchive-ci-server-$(Version).zip` - this archive is optimized for CI server environments. It contains the same contents as the LZMA, but trimmed of xml docs (these are only required for IDEs) and .nupkg files (not required for NuGet as for the 2.0 SDK). +* **ci-server-patch** - `nuGetPackagesArchive-ci-server-$(Version).patch.zip` - this archive is the same as the ci-server archive, but each release is incremental - i.e. it does not bundle files that were present in a previous ci-server archive release. This can be used by first starting with a baseline `nuGetPackagesArchive-ci-server-$(Version).zip` and then applying the `.patch.zip` version for subsequent updates. +* **ci-server-compat-patch** - `nuGetPackagesArchive-ci-server-compat-$(Version).patch.zip` - similar to the ci-server-patch archive, but this includes .nupkg files to satisfy CI environments that may have older NuGet clients. + +These archives are built using the projects in [src/PackageArchive/Archive.\*/](/src/PackageArchive/). + +## Using a fallback folder + +NuGet restore takes a list of fallback folders in the MSBuild property `RestoreAdditionalProjectFallbackFolders`. Unlike a folder restore source, restore will not copy the packages from a fallback folder into the global NuGet cache. + +By default, the .NET Core SDK adds `$(DotNetInstallRoot)/sdk/NuGetFallbackFolder/` to this list. The .NET Core CLI expands its bundled `nuGetPackagesArchive.lzma` file into this location on first use or when the installers run. (See [Microsoft.NET.NuGetOfflineCache.targets](https://github.com/dotnet/sdk/blob/v2.1.300/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.NuGetOfflineCache.targets)). + +## Scenarios + +The following scenarios are used to determine which packages go into the fallback package cache. +These requirements are formalized as project files in [src/PackageArchive/Scenario.\*/](/src/PackageArchive/). + + - A user should be able to restore the following templates and only use packages from the offline cache: + - `dotnet new console` + - `dotnet new library` + - `dotnet new web` + - `dotnet new razor` + - `dotnet new mvc` + +The following packages are NOT included in the offline cache. + - Packages required for standalone publishing, aka projects that set a Runtime Identifier during restore + - Packages required for F# and VB templates + - Packages required for Visual Studio code generation in ASP.NET Core projects + - Packages required to restore .NET Framework projects + - Packages required to restore test projects, such as xunit, MSTest, NUnit + +The result of this typically means including the transitive graph of the following packages: + + - Packages that match bundled runtimes + - Microsoft.NETCore.App + - Microsoft.AspNetCore.App + - Microsoft.AspNetCore.All + - Packages that Microsoft.NET.Sdk adds implicitly + - Microsoft.NETCore.App + - NETStandard.Library + - Packages that are a PackageReference/DotNetCliToolReference in basic ASP.NET Core templates. In addition to packages above, this typically includes: + - Microsoft.EntityFrameworkCore.Tools{.DotNet} + - Microsoft.VisualStudio.Web.CodeGeneration.Design + - Microsoft.VisualStudio.Web.BrowserLink + +### Example + +Given the following parameters: + - LatestNETCoreAppTFM = netcoreapp2.1 + - DefaultRuntimeVersion = 2.1 + - BundledRuntimeVersion = 2.1.8 + - BundledAspNetRuntimeVersion = 2.1.7 + - LatestNETStandardLibraryTFM = netstandard2.0 + - BundledNETStandardLibraryVersion = 2.0.1 + +The LZMA should contain + - Microsoft.NETCore.App/2.1.0 + netcoreapp2.1 dependencies (Microsoft.NET.Sdk will implicitly reference "2.1", which NuGet to 2.1.0) + - Microsoft.NETCore.App/2.1.8 + netcoreapp2.1 dependencies (Matches the runtime in shared/Microsoft.NETCore.App/2.1.8/) + - Microsoft.AspNetCore.All/2.1.7 + netcoreapp2.1 dependencies (Matches the runtime in shared/Microsoft.AspNetCore.All/2.1.7/) + - NETStandard.Library/2.0.1 + netstandard2.0 dependencies (Microsoft.NET.Sdk will implicitly reference "2.0.1") diff --git a/docs/Submodules.md b/docs/Submodules.md new file mode 100644 index 0000000000..501e7884d3 --- /dev/null +++ b/docs/Submodules.md @@ -0,0 +1,84 @@ +Submodules +========== + +This repository composes ASP.NET Core repos from a collection of many submodules. +Working with submodules in git requires using commands not used in a normal git workflow. +Here are some tips for working with submodules. + +For full information, see the [official docs for git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules). + +## Fundamental concept + +The parent repo (aspnet/Universe) stores two pieces of info about each submodule. + +1. Where to clone the submodule from. This is stored in the .gitmodules file +2. The commit hash of the submodule to use. + +This means you cannot commit a submodule's branch or a tag to the parent repo. +Other info may appear in the .gitmodules file, but it is only used when attempting to +[update a submodule.](#updating-submodules) + +## Cloning + +By default, submodules will not be present. Use `--recursive` to clone all submodules. + + git clone https://github.com/aspnet/Universe.git --recursive + +If you have already cloned, run this to initialize all submodules. + + git submodule update --init + +## Pulling updates + +When you execute `git pull`, submodules do not automatically snap to the version +used in new commits of the parent repo. Update all submodules to match the parent repo's +expected version by running this command. + + git submodule update + +## Executing a command on each submodule + + git submodule foreach '' + +For example, to clean and reset each submodule: + + git submodule foreach 'git reset --hard; git clean -xfd' + +## Updating submodules + +Updating all submodules to newer versions can be done like this. + + git submodule update --remote + +Updating just one subumodule. + + git submodule update --remote modules/EntityFrameworkCore/ + +This uses the remote url and branch info configuration stored in .gitmodules to pull new commits. +This does not guarantee the commit is going to be a fast-forward commit. + +## Diff + +You can see which commits have changed in submodules from the last parent repo commit by adding `--submodule` to git-diff. + + git diff --submodule + +## Saving an update to a submodule + +To move the parent repo to use a new commit, you must create a commit in the parent repo +that contains the new commit. + + git submodule update --remote modules/KestrelHttpServer/ + git add modules/KestrelhttpServer/ + git commit -m "Update Kestrel to latest version" + +## PowerShell is slow in aspnet/Universe + +Many users have post-git, and extension that shows git status on the prompt line. Because `git status` with submodules +on Windows is very slow, it can make PowerShell unbearable to use. + +To workaround this, disable checking git-status for each prompt. +```ps1 +$GitPromptSettings.EnableFileStatus = $false +``` +You can disable this permanently by adding to your `$PROFILE` file. (`notepad $PROFILE`) diff --git a/docs/build-from-source.md b/docs/build-from-source.md new file mode 100644 index 0000000000..31977ae751 --- /dev/null +++ b/docs/build-from-source.md @@ -0,0 +1,129 @@ +Build ASP.NET Core from Source +============================== + +Building ASP.NET Core from source allows you tweak and customize ASP.NET Core, and +to contribute your improvements back to the project. + +## Install pre-requistes + +### Windows + +Building ASP.NET Core on Windows requires: + +* Windows 7 or higher +* At least 10 GB of disk space and a good internet connection (our build scripts download a lot of tools and dependencies) +* Visual Studio 2017. +* Git. +* (Optional) some optional components, like the SignalR Java client, may require + * NodeJS + * Java Development Kit 10 or newer. Either: + * OpenJDK + * Oracle's JDK + +### macOS/Linux + +Building ASP.NET Core on macOS or Linux requires: + +* If using macOS, you need macOS Sierra or newer. +* If using Linux, you need a machine with all .NET Core Linux prerequisites: +* At least 10 GB of disk space and a good internet connection (our build scripts download a lot of tools and dependencies) +* Git +* (Optional) some optional components, like the SignalR Java client, may require + * NodeJS + * Java Development Kit 10 or newer. Either: + * OpenJDK + * Oracle's JDK + +## Clone the source code + +ASP.NET Core uses git submodules to include source from a few other projects. + +For a new copy of the project, run: +``` +git clone --recursive https://github.com/aspnet/AspNetCore +``` + +To update an existing copy, run: +``` +git submodule update --init --recursive +``` + +## Building in Visual Studio / Code + +Before opening our .sln files in Visual Studio or VS Code, executing the following on command-line: +``` +.\build.cmd /t:Restore +``` +This will download required tools. + +#### PATH + +For VS Code and Visual Studio to work correctly, you must place the following location in your PATH. +``` +Windows: %USERPROFILE%\.dotnet\x64 +Linux/macOS: $HOME/.dotnet +``` +This must come **before** any other installation of `dotnet`. In Windows, we recommend removing `C:\Program Files\dotnet` from PATH in system variables and adding `%USERPROFILE%\.dotnet\x64` to PATH in user variables. + + + +## Building on command-line + +You can also build the entire project on command line with the `build.cmd`/`.sh` scripts. + +On Windows: +``` +.\build.cmd +``` + +On macOS/Linux: +``` +./build.sh +``` + +#### Build properties + +Additional properties can be added as an argument in the form `/property:$name=$value`, or `/p:$name=$value` for short. For example: +``` +.\build.cmd /p:Configuration=Release +``` + +Common properties include: + +Property | Description +-------------------------|--------------------------------------------------------- +BuildNumber | (string). A specific build number, typically from a CI counter +Configuration | `Debug` or `Release`. Default = `Debug`. +SkipTests | `true` or `false`. When true, builds without running tests. +NoBuild | `true` or `false`. Runs tests without rebuilding. + +## Use the result of your build + +After building ASP.NET Core from source, you will need to install and use your local version of ASP.NET Core. + +- Run the installers produced in `artifacts/installers/` for your platform. +- Add a NuGet.Config to your project directory with the following content: + + ```xml + + + + + + + + + ``` + + *NOTE: This NuGet.Config should be with your application unless you want nightly packages to potentially start being restored for other apps on the machine.* + +- Update the versions on `PackageReference` items in your .csproj project file to point to the version from your local build. + ```xml + + + + ``` + + +Some features, such as new target frameworks, may require prerelease tooling builds for Visual Studio. +These are available in the [Visual Studio Preview](https://www.visualstudio.com/vs/preview/). diff --git a/docs/daily-builds.md b/docs/daily-builds.md new file mode 100644 index 0000000000..c1c04db7ee --- /dev/null +++ b/docs/daily-builds.md @@ -0,0 +1,99 @@ +How to get daily builds of ASP.NET Core +======================================= + +Daily builds include the latest source code changes. They are not supported for production use and are subject to frequent changes, but we strive to make sure daily builds function correctly. + +If you want to download the latest daily build and use it in a project, then you need to: + +- Obtain the latest [build of the .NET Core SDK](https://github.com/dotnet/core-sdk#installers-and-binaries) +- Add a NuGet.Config to your project directory with the following content: + + ```xml + + + + + + + + + ``` + + *NOTE: This NuGet.Config should be with your application unless you want nightly packages to potentially start being restored for other apps on the machine.* + +Some features, such as new target frameworks, may require prerelease tooling builds for Visual Studio. +These are available in the [Visual Studio Preview](https://www.visualstudio.com/vs/preview/). + +## NuGet packages + +Daily builds of ackages can be found on . This feed may include +packages that will not be supported in a officially released build. + +Commonly referenced packages: + +[app-metapackage-myget]: https://dotnet.myget.org/feed/dotnet-core/package/nuget/Microsoft.AspNetCore.App +[app-metapackage-myget-badge]: https://img.shields.io/dotnet.myget/dotnet-core/vpre/Microsoft.AspNetCore.App.svg?style=flat-square&label=myget + +[metapackage-myget]: https://dotnet.myget.org/feed/dotnet-core/package/nuget/Microsoft.AspNetCore +[metapackage-myget-badge]: https://img.shields.io/dotnet.myget/dotnet-core/vpre/Microsoft.AspNetCore.svg?style=flat-square&label=myget + +Package | MyGet +:---------------------------------|:--------------------------------------------------------- +Microsoft.AspNetCore.App | [![][app-metapackage-myget-badge]][app-metapackage-myget] +Microsoft.AspNetCore | [![][metapackage-myget-badge]][metapackage-myget] + +## Runtime installers + +Updated versions of the ASP.NET Core runtime can be installed separately from SDK updates. Runtime-only installers can be downloaded here: + +[badge-master]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-win-x64-version-badge.svg +[win-x64-zip]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-win-x64.zip +[win-x64-exe]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-win-x64.exe +[win-x86-zip]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-win-x86.zip +[win-x86-exe]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-win-x86.exe +[linux-x64-tar]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-linux-x64.tar.gz +[linux-arm-tar]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-linux-arm.tar.gz +[linux-arm64-tar]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-linux-arm64.tar.gz +[osx-x64-tar]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-osx-x64.tar.gz +[debian-x64-deb]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-x64.deb +[redhat-x64-rpm]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-x64.rpm +[linux-musl-x64-tar]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/master/aspnetcore-runtime-latest-linux-musl-x64.tar.gz + +[badge-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-win-x64-version-badge.svg +[win-x64-zip-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-win-x64.zip +[win-x64-exe-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-win-x64.exe +[win-x86-zip-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-win-x86.zip +[win-x86-exe-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-win-x86.exe +[linux-x64-tar-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-linux-x64.tar.gz +[osx-x64-tar-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-osx-x64.tar.gz +[debian-x64-deb-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-x64.deb +[redhat-x64-rpm-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-x64.rpm +[linux-arm-tar-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-linux-arm.tar.gz +[linux-musl-x64-tar-rel-22]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.2/aspnetcore-runtime-latest-linux-musl-x64.tar.gz + +[badge-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-win-x64-version-badge.svg +[win-x64-zip-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-win-x64.zip +[win-x64-exe-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-win-x64.exe +[win-x86-zip-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-win-x86.zip +[win-x86-exe-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-win-x86.exe +[linux-x64-tar-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-linux-x64.tar.gz +[osx-x64-tar-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-osx-x64.tar.gz +[debian-x64-deb-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-x64.deb +[redhat-x64-rpm-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-x64.rpm +[linux-arm-tar-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-linux-arm.tar.gz +[linux-musl-x64-tar-rel-21]: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/release/2.1/aspnetcore-runtime-latest-linux-musl-x64.tar.gz + +Platform | Latest (master branch)
![][badge-master] | release/2.2
![][badge-rel-22] | release/2.1
![][badge-rel-21] +:---------------------|:----------------------------------------------------------------|:------------------------------------------------------------------------- |:------------------------------------------------------------------------- +Channel name1 | `master` | `release/2.2` | `release/2.1` +Windows (x64) | [Installer (exe)][win-x64-exe]
[Archive (zip)][win-x64-zip] | [Installer (exe)][win-x64-exe-rel-22]
[Archive (zip)][win-x64-zip-rel-22] | [Installer (exe)][win-x64-exe-rel-21]
[Archive (zip)][win-x64-zip-rel-21] +Windows (x86) | [Installer (exe)][win-x86-exe]
[Archive (zip)][win-x86-zip] | [Installer (exe)][win-x86-exe-rel-22]
[Archive (zip)][win-x86-zip-rel-22] | [Installer (exe)][win-x86-exe-rel-21]
[Archive (zip)][win-x86-zip-rel-21] +macOS (x64) | [Archive (tar.gz)][osx-x64-tar] | [Archive (tar.gz)][osx-x64-tar-rel-22] | [Archive (tar.gz)][osx-x64-tar-rel-21] +Linux (x64)
_(for glibc based OS - most common)_ | [Archive (tar.gz)][linux-x64-tar] | [Archive (tar.gz)][linux-x64-tar-rel-22] | [Archive (tar.gz)][linux-x64-tar-rel-21] +Linux (x64 - musl)
_(for musl based OS, such as Alpine Linux)_ | [Archive (tar.gz)][linux-musl-x64-tar] | [Archive (tar.gz)][linux-musl-x64-tar-rel-22] | [Archive (tar.gz)][linux-musl-x64-tar-rel-21] +Linux (arm32) | [Archive (tar.gz)][linux-arm-tar] | [Archive (tar.gz)][linux-arm-tar-rel-22] | [Archive (tar.gz)][linux-arm-tar-rel-21] +Linux (arm64) | [Archive (tar.gz)][linux-arm64-tar] | | +Debian/Ubuntu (x64) | [Installer (deb)][debian-x64-deb] | [Installer (deb)][debian-x64-deb-rel-22] | [Installer (deb)][debian-x64-deb-rel-21] +RedHat/Fedora (x64) | [Installer (rpm)][redhat-x64-rpm] | [Installer (rpm)][redhat-x64-rpm-rel-22] | [Installer (rpm)][redhat-x64-rpm-rel-21] + +> 1 For use with the `-Channel` argument in [dotnet-install.ps1/sh](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script). diff --git a/eng/AspNetCore.snk b/eng/AspNetCore.snk new file mode 100644 index 0000000000..e10e4889c1 Binary files /dev/null and b/eng/AspNetCore.snk differ diff --git a/eng/targets/Cpp.Common.props b/eng/targets/Cpp.Common.props new file mode 100644 index 0000000000..f295dbafad --- /dev/null +++ b/eng/targets/Cpp.Common.props @@ -0,0 +1,11 @@ + + + + + true + + + + + + diff --git a/eng/targets/Cpp.Common.targets b/eng/targets/Cpp.Common.targets new file mode 100644 index 0000000000..f2cad0d8c0 --- /dev/null +++ b/eng/targets/Cpp.Common.targets @@ -0,0 +1,6 @@ + + + + + + diff --git a/eng/targets/MicroBuild.Plugin.props b/eng/targets/MicroBuild.Plugin.props new file mode 100644 index 0000000000..0101904811 --- /dev/null +++ b/eng/targets/MicroBuild.Plugin.props @@ -0,0 +1,12 @@ + + + + + $(MicroBuildOverridePluginDirectory) + + + $(NuGetPackageRoot) + $(NUGET_PACKAGES) + $(USERPROFILE)\.nuget\packages + + diff --git a/eng/targets/Wix.Common.props b/eng/targets/Wix.Common.props new file mode 100644 index 0000000000..d958514aba --- /dev/null +++ b/eng/targets/Wix.Common.props @@ -0,0 +1,32 @@ + + + + + 2.0 + 3.11 + 3.11.1 + + + + + net461 + $(BaseIntermediateOutputPath) + $(MSBuildProjectDir)\obj\ + $(MSBuildExtensionsPath)\..\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.targets + + + + + + + + + + true + $(WixExtDir)dark.exe + + + + + + diff --git a/eng/targets/Wix.Common.targets b/eng/targets/Wix.Common.targets new file mode 100644 index 0000000000..4b07606e19 --- /dev/null +++ b/eng/targets/Wix.Common.targets @@ -0,0 +1,50 @@ + + + + + + + Microsoft400 + + + Microsoft400 + + + Microsoft400 + + + Microsoft400 + + + + + + + + + + yes + $(OutputName.Replace('-', '_')).cab + $(ProductName) + + $(DefineConstants);Debug + $(DefineConstants);EmbedCab=$(EmbedCab) + $(DefineConstants);Cabinet=$(Cabinet) + + + + en-US + $(Culture) + $(Platform) + $(Platform) + $(OutputPath) + $(DefineConstants);BinPath=$(OutputPath)$(Culture)\ + $(WixVariables);$(DefineConstants) + + + + + + + + diff --git a/global.json b/global.json new file mode 100644 index 0000000000..ffa7db4c53 --- /dev/null +++ b/global.json @@ -0,0 +1,8 @@ +{ + "sdk": { + "version": "2.2.100-preview2-009404" + }, + "msbuild-sdks": { + "Internal.AspNetCore.Sdk": "3.0.0-alpha1-20181011.11" + } +} diff --git a/korebuild-lock.txt b/korebuild-lock.txt new file mode 100644 index 0000000000..27b605e3c6 --- /dev/null +++ b/korebuild-lock.txt @@ -0,0 +1,2 @@ +version:3.0.0-alpha1-20181011.11 +commithash:f57aa8ddda0abdd74ada55853587bedb4f364065 diff --git a/korebuild.json b/korebuild.json new file mode 100644 index 0000000000..2a75c43d76 --- /dev/null +++ b/korebuild.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", + "toolsets": { + "nodejs": { + "minVersion": "8.0", + "required": true + } + } +} diff --git a/modules/AADIntegration b/modules/AADIntegration new file mode 160000 index 0000000000..1ebe668a96 --- /dev/null +++ b/modules/AADIntegration @@ -0,0 +1 @@ +Subproject commit 1ebe668a965de3e4a759e5eadc57c4c742ae825c diff --git a/modules/Antiforgery b/modules/Antiforgery new file mode 160000 index 0000000000..926b3dfe97 --- /dev/null +++ b/modules/Antiforgery @@ -0,0 +1 @@ +Subproject commit 926b3dfe97df76d9a0c35db197f130147e3675e8 diff --git a/modules/AuthSamples b/modules/AuthSamples new file mode 160000 index 0000000000..7c3be6c7f8 --- /dev/null +++ b/modules/AuthSamples @@ -0,0 +1 @@ +Subproject commit 7c3be6c7f8d6692d6c87ed7f1cea7eec2fc8bb7a diff --git a/modules/AzureIntegration b/modules/AzureIntegration new file mode 160000 index 0000000000..1e6e066006 --- /dev/null +++ b/modules/AzureIntegration @@ -0,0 +1 @@ +Subproject commit 1e6e0660064a7e0438fea2d42af45ad5b92204bf diff --git a/modules/BasicMiddleware b/modules/BasicMiddleware new file mode 160000 index 0000000000..6339351ddc --- /dev/null +++ b/modules/BasicMiddleware @@ -0,0 +1 @@ +Subproject commit 6339351ddc1a6815e2cb8fe32da6fa341e877173 diff --git a/modules/BrowserLink b/modules/BrowserLink new file mode 160000 index 0000000000..0b083d1503 --- /dev/null +++ b/modules/BrowserLink @@ -0,0 +1 @@ +Subproject commit 0b083d15036e5643b2b6a9ea6e3d995c51a42e5a diff --git a/modules/CORS b/modules/CORS new file mode 160000 index 0000000000..f074714eb0 --- /dev/null +++ b/modules/CORS @@ -0,0 +1 @@ +Subproject commit f074714eb0a558d27c97f04c60de6b8730b4fd9c diff --git a/modules/Caching b/modules/Caching new file mode 160000 index 0000000000..b7cda012bc --- /dev/null +++ b/modules/Caching @@ -0,0 +1 @@ +Subproject commit b7cda012bca34704e5a835ace53a0f879b5f2a2d diff --git a/modules/Common b/modules/Common new file mode 160000 index 0000000000..b90ec23956 --- /dev/null +++ b/modules/Common @@ -0,0 +1 @@ +Subproject commit b90ec23956e81c462ab61fd9ee56b975464b834c diff --git a/modules/Configuration b/modules/Configuration new file mode 160000 index 0000000000..fdeabf6016 --- /dev/null +++ b/modules/Configuration @@ -0,0 +1 @@ +Subproject commit fdeabf601682d6d85b1f37a79449972f8d469e8a diff --git a/modules/DependencyInjection b/modules/DependencyInjection new file mode 160000 index 0000000000..ca90dc6871 --- /dev/null +++ b/modules/DependencyInjection @@ -0,0 +1 @@ +Subproject commit ca90dc687106ab6ecb46e4943f3fe5ceac3e6ef8 diff --git a/modules/Diagnostics b/modules/Diagnostics new file mode 160000 index 0000000000..0ce437875e --- /dev/null +++ b/modules/Diagnostics @@ -0,0 +1 @@ +Subproject commit 0ce437875e8feeb88bb935c7de07e96218be8be3 diff --git a/modules/DotNetTools b/modules/DotNetTools new file mode 160000 index 0000000000..581b3160f4 --- /dev/null +++ b/modules/DotNetTools @@ -0,0 +1 @@ +Subproject commit 581b3160f422180b3411d84b4458c10128c8cacb diff --git a/modules/EntityFrameworkCore b/modules/EntityFrameworkCore new file mode 160000 index 0000000000..12855cd0ed --- /dev/null +++ b/modules/EntityFrameworkCore @@ -0,0 +1 @@ +Subproject commit 12855cd0ed48d77f13ae7f6e9ef67cbbcac71a22 diff --git a/modules/EventNotification b/modules/EventNotification new file mode 160000 index 0000000000..08c615f093 --- /dev/null +++ b/modules/EventNotification @@ -0,0 +1 @@ +Subproject commit 08c615f0939fe0a7d7399eaa02be708dc92d9a10 diff --git a/modules/FileSystem b/modules/FileSystem new file mode 160000 index 0000000000..3cc768b93f --- /dev/null +++ b/modules/FileSystem @@ -0,0 +1 @@ +Subproject commit 3cc768b93fafb14aa74f93b050cfb4aba8ae6dfb diff --git a/modules/Hosting b/modules/Hosting new file mode 160000 index 0000000000..5a3c664566 --- /dev/null +++ b/modules/Hosting @@ -0,0 +1 @@ +Subproject commit 5a3c6645667ec24e09d6200fb1e949f2a2417b9a diff --git a/modules/HtmlAbstractions b/modules/HtmlAbstractions new file mode 160000 index 0000000000..45b7e2ddb7 --- /dev/null +++ b/modules/HtmlAbstractions @@ -0,0 +1 @@ +Subproject commit 45b7e2ddb796f0cb909d8f04bc4b5a5cf13b5e46 diff --git a/modules/HttpAbstractions b/modules/HttpAbstractions new file mode 160000 index 0000000000..3fe17b9faf --- /dev/null +++ b/modules/HttpAbstractions @@ -0,0 +1 @@ +Subproject commit 3fe17b9faf0ae413ecd5bea1d42c784854acfb57 diff --git a/modules/HttpClientFactory b/modules/HttpClientFactory new file mode 160000 index 0000000000..4dfcf7485e --- /dev/null +++ b/modules/HttpClientFactory @@ -0,0 +1 @@ +Subproject commit 4dfcf7485e62819d0d73c00d7e7eb53d75abdbd3 diff --git a/modules/HttpSysServer b/modules/HttpSysServer new file mode 160000 index 0000000000..1d989c2a50 --- /dev/null +++ b/modules/HttpSysServer @@ -0,0 +1 @@ +Subproject commit 1d989c2a50c62069b16879eda901e79e37276c2d diff --git a/modules/IISIntegration b/modules/IISIntegration new file mode 160000 index 0000000000..2bd2c1870a --- /dev/null +++ b/modules/IISIntegration @@ -0,0 +1 @@ +Subproject commit 2bd2c1870a236df4af389dbb74f04daca78d62b1 diff --git a/modules/Identity b/modules/Identity new file mode 160000 index 0000000000..81928f6c31 --- /dev/null +++ b/modules/Identity @@ -0,0 +1 @@ +Subproject commit 81928f6c31a2e47e72f631c1bb5cf1bb1a3f8cf6 diff --git a/modules/JavaScriptServices b/modules/JavaScriptServices new file mode 160000 index 0000000000..9c6a1b577f --- /dev/null +++ b/modules/JavaScriptServices @@ -0,0 +1 @@ +Subproject commit 9c6a1b577f04d845152532c66252811260b3f36a diff --git a/modules/JsonPatch b/modules/JsonPatch new file mode 160000 index 0000000000..0b76599c31 --- /dev/null +++ b/modules/JsonPatch @@ -0,0 +1 @@ +Subproject commit 0b76599c31b3fa367dc172272e81cee87a634ba9 diff --git a/modules/KestrelHttpServer b/modules/KestrelHttpServer new file mode 160000 index 0000000000..8fc57cd0a1 --- /dev/null +++ b/modules/KestrelHttpServer @@ -0,0 +1 @@ +Subproject commit 8fc57cd0a1e7aefc5151cb11249e117b1cc1743a diff --git a/modules/Localization b/modules/Localization new file mode 160000 index 0000000000..9ecc9abd23 --- /dev/null +++ b/modules/Localization @@ -0,0 +1 @@ +Subproject commit 9ecc9abd23d2264095aba5ab34624905d51aa79c diff --git a/modules/Logging b/modules/Logging new file mode 160000 index 0000000000..68748131c5 --- /dev/null +++ b/modules/Logging @@ -0,0 +1 @@ +Subproject commit 68748131c5f591309ccf619fa564220b1704a473 diff --git a/modules/MetaPackages b/modules/MetaPackages new file mode 160000 index 0000000000..3e0ee5a711 --- /dev/null +++ b/modules/MetaPackages @@ -0,0 +1 @@ +Subproject commit 3e0ee5a711556581ebda53082d11cab1c0c8d197 diff --git a/modules/Microsoft.Data.Sqlite b/modules/Microsoft.Data.Sqlite new file mode 160000 index 0000000000..c4dadf19d8 --- /dev/null +++ b/modules/Microsoft.Data.Sqlite @@ -0,0 +1 @@ +Subproject commit c4dadf19d8a5e2bc2a64552c1c1c8899a72af33c diff --git a/modules/MusicStore b/modules/MusicStore new file mode 160000 index 0000000000..5fe4ff7c27 --- /dev/null +++ b/modules/MusicStore @@ -0,0 +1 @@ +Subproject commit 5fe4ff7c27d3a811e3d505208097a6ca69d18125 diff --git a/modules/Mvc b/modules/Mvc new file mode 160000 index 0000000000..5f42d5063e --- /dev/null +++ b/modules/Mvc @@ -0,0 +1 @@ +Subproject commit 5f42d5063e1ecc4f6f1ce0af85c624841e479044 diff --git a/modules/Options b/modules/Options new file mode 160000 index 0000000000..621cd9d38a --- /dev/null +++ b/modules/Options @@ -0,0 +1 @@ +Subproject commit 621cd9d38a6a8c05d379de7bbbcd59c119827d7d diff --git a/modules/Razor b/modules/Razor new file mode 160000 index 0000000000..71ed050fa4 --- /dev/null +++ b/modules/Razor @@ -0,0 +1 @@ +Subproject commit 71ed050fa4ea7756ed69d3f029c02bf58f31fb55 diff --git a/modules/ResponseCaching b/modules/ResponseCaching new file mode 160000 index 0000000000..e7f8210970 --- /dev/null +++ b/modules/ResponseCaching @@ -0,0 +1 @@ +Subproject commit e7f8210970bd5566795e6f87155a8fd7c7ea4ab0 diff --git a/modules/Routing b/modules/Routing new file mode 160000 index 0000000000..1643b535b2 --- /dev/null +++ b/modules/Routing @@ -0,0 +1 @@ +Subproject commit 1643b535b26ff857ed80d36526625588ff61ee3f diff --git a/modules/Scaffolding b/modules/Scaffolding new file mode 160000 index 0000000000..a4fca717da --- /dev/null +++ b/modules/Scaffolding @@ -0,0 +1 @@ +Subproject commit a4fca717da581df687d7853e0d18cbd92fb87c06 diff --git a/modules/Security b/modules/Security new file mode 160000 index 0000000000..4dd9c6deef --- /dev/null +++ b/modules/Security @@ -0,0 +1 @@ +Subproject commit 4dd9c6deefba64aa7721430e7d1dc72d6e002416 diff --git a/modules/ServerTests b/modules/ServerTests new file mode 160000 index 0000000000..d5b83e32c6 --- /dev/null +++ b/modules/ServerTests @@ -0,0 +1 @@ +Subproject commit d5b83e32c62383a04003c269026c3f0e8b5d3522 diff --git a/modules/Session b/modules/Session new file mode 160000 index 0000000000..d5e4687a6f --- /dev/null +++ b/modules/Session @@ -0,0 +1 @@ +Subproject commit d5e4687a6fda304b2e15c79abe9de76dd8367f58 diff --git a/modules/SignalR b/modules/SignalR new file mode 160000 index 0000000000..df88a82a80 --- /dev/null +++ b/modules/SignalR @@ -0,0 +1 @@ +Subproject commit df88a82a8084b2775ed880f01c2a1a50787088d1 diff --git a/modules/StaticFiles b/modules/StaticFiles new file mode 160000 index 0000000000..4c8df8e5a4 --- /dev/null +++ b/modules/StaticFiles @@ -0,0 +1 @@ +Subproject commit 4c8df8e5a4e3abe5e7db51685dbd892d160c1e35 diff --git a/modules/SubmoduleGraph.dgml b/modules/SubmoduleGraph.dgml new file mode 100644 index 0000000000..2cd4f5c57e --- /dev/null +++ b/modules/SubmoduleGraph.dgml @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/Templating b/modules/Templating new file mode 160000 index 0000000000..bcc6a17c3d --- /dev/null +++ b/modules/Templating @@ -0,0 +1 @@ +Subproject commit bcc6a17c3d653faf129f33dbf5868b2f82946742 diff --git a/modules/WebSockets b/modules/WebSockets new file mode 160000 index 0000000000..34f161321a --- /dev/null +++ b/modules/WebSockets @@ -0,0 +1 @@ +Subproject commit 34f161321a5d3bd9f7c83e968c34dcd98416f061 diff --git a/run.cmd b/run.cmd new file mode 100644 index 0000000000..d52d5c7e68 --- /dev/null +++ b/run.cmd @@ -0,0 +1,2 @@ +@ECHO OFF +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" diff --git a/run.ps1 b/run.ps1 new file mode 100644 index 0000000000..6b7e36c6cf --- /dev/null +++ b/run.ps1 @@ -0,0 +1,251 @@ +#!/usr/bin/env powershell +#requires -version 4 + +<# +.SYNOPSIS +Executes KoreBuild commands. + +.DESCRIPTION +Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. + +.PARAMETER Command +The KoreBuild command to run. + +.PARAMETER Path +The folder to build. Defaults to the folder containing this script. + +.PARAMETER LockFile +The path to the korebuild-lock.txt file. Defaults to $Path/korebuild-lock.txt + +.PARAMETER Channel +The channel of KoreBuild to download. Overrides the value from the config file. + +.PARAMETER DotNetHome +The directory where .NET Core tools will be stored. + +.PARAMETER ToolsSource +The base url where build tools can be downloaded. Overrides the value from the config file. + +.PARAMETER Update +Updates KoreBuild to the latest version even if a lock file is present. + +.PARAMETER Reinstall +Re-installs KoreBuild + +.PARAMETER ConfigFile +The path to the configuration file that stores values. Defaults to korebuild.json. + +.PARAMETER CI +Sets up CI specific settings and variables. + +.PARAMETER PackageVersionPropsUrl +(optional) the url of the package versions props path containing dependency versions. + +.PARAMETER AssetRootUrl +(optional) the base url for acquiring build assets from an orchestrated build + +.PARAMETER AccessTokenSuffix +(optional) the query string to append to any blob store access for PackageVersionPropsUrl, if any. + +.PARAMETER RestoreSources +(optional) Semi-colon delimited list of additional NuGet feeds to use as part of restore. + +.PARAMETER ProductBuildId +(optional) The product build ID for correlation with orchestrated builds. + +.PARAMETER MSBuildArguments +Additional MSBuild arguments to be passed through. + +.NOTES +This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. +When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. + +The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set +in the file are overridden by command line parameters. + +.EXAMPLE +Example config file: +```json +{ + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", + "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" +} +``` +#> +[CmdletBinding(PositionalBinding = $false)] +param( + [Parameter(Mandatory=$true, Position = 0)] + [string]$Command, + [string]$Path = $PSScriptRoot, + [string]$LockFile, + [Alias('c')] + [string]$Channel, + [Alias('d')] + [string]$DotNetHome, + [Alias('s')] + [string]$ToolsSource, + [Alias('u')] + [switch]$Update, + [switch]$Reinstall, + [string]$ConfigFile = $null, + [switch]$CI, + [string]$PackageVersionPropsUrl = $null, + [string]$AccessTokenSuffix = $null, + [string]$RestoreSources = $null, + [string]$AssetRootUrl = $null, + [string]$ProductBuildId = $null, + [Parameter(ValueFromRemainingArguments = $true)] + [string[]]$MSBuildArguments +) + +Set-StrictMode -Version 2 +$ErrorActionPreference = 'Stop' + +# +# Functions +# + +function Get-KoreBuild { + + if (!(Test-Path $LockFile) -or $Update) { + Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $LockFile + } + + $version = Get-Content $LockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 + if (!$version) { + Write-Error "Failed to parse version from $LockFile. Expected a line that begins with 'version:'" + } + $version = $version.TrimStart('version:').Trim() + $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) + + if ($Reinstall -and (Test-Path $korebuildPath)) { + Remove-Item -Force -Recurse $korebuildPath + } + + if (!(Test-Path $korebuildPath)) { + Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" + New-Item -ItemType Directory -Path $korebuildPath | Out-Null + $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" + + try { + $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" + Get-RemoteFile $remotePath $tmpfile + if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { + # Use built-in commands where possible as they are cross-plat compatible + Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath + } + else { + # Fallback to old approach for old installations of PowerShell + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) + } + } + catch { + Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore + throw + } + finally { + Remove-Item $tmpfile -ErrorAction Ignore + } + } + + return $korebuildPath +} + +function Join-Paths([string]$path, [string[]]$childPaths) { + $childPaths | ForEach-Object { $path = Join-Path $path $_ } + return $path +} + +function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { + if ($RemotePath -notlike 'http*') { + Copy-Item $RemotePath $LocalPath + return + } + + $retries = 10 + while ($retries -gt 0) { + $retries -= 1 + try { + Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath + return + } + catch { + Write-Verbose "Request failed. $retries retries remaining" + } + } + + Write-Error "Download failed: '$RemotePath'." +} + +# +# Main +# + +# Load configuration or set defaults + +$Path = Resolve-Path $Path +if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } + +if (Test-Path $ConfigFile) { + try { + $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json + if ($config) { + if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } + if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} + } + } catch { + Write-Warning "$ConfigFile could not be read. Its settings will be ignored." + Write-Warning $Error[0] + } +} + +if (!$DotNetHome) { + $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` + elseif ($CI) { Join-Path $PSScriptRoot '.dotnet' } ` + elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` + elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` + else { Join-Path $PSScriptRoot '.dotnet'} +} + +if (!$LockFile) { $LockFile = Join-Path $Path 'korebuild-lock.txt' } +if (!$Channel) { $Channel = 'master' } +if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } + +if ($PackageVersionPropsUrl) { + $IntermediateDir = Join-Path $PSScriptRoot 'obj' + $PropsFilePath = Join-Path $IntermediateDir 'external-dependencies.props' + New-Item -ItemType Directory $IntermediateDir -ErrorAction Ignore | Out-Null + Get-RemoteFile "${PackageVersionPropsUrl}${AccessTokenSuffix}" $PropsFilePath + $MSBuildArguments += "-p:DotNetPackageVersionPropsPath=$PropsFilePath" +} + +if ($RestoreSources) { + $MSBuildArguments += "-p:DotNetAdditionalRestoreSources=$RestoreSources" +} + +if ($AssetRootUrl) { + $MSBuildArguments += "-p:DotNetAssetRootUrl=$AssetRootUrl" +} + +if ($AccessTokenSuffix) { + $MSBuildArguments += "-p:DotNetAssetRootAccessTokenSuffix=$AccessTokenSuffix" +} + +if ($ProductBuildId) { + $MSBuildArguments += "-p:DotNetProductBuildId=$ProductBuildId" +} + +# Execute + +$korebuildPath = Get-KoreBuild +Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') + +try { + Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI + Invoke-KoreBuildCommand $Command @MSBuildArguments +} +finally { + Remove-Module 'KoreBuild' -ErrorAction Ignore +} diff --git a/run.sh b/run.sh new file mode 100755 index 0000000000..cfc0a36904 --- /dev/null +++ b/run.sh @@ -0,0 +1,314 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# +# variables +# + +RESET="\033[0m" +RED="\033[0;31m" +YELLOW="\033[0;33m" +MAGENTA="\033[0;95m" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +verbose=false +update=false +reinstall=false +repo_path="$DIR" +lockfile_path='' +channel='' +tools_source='' +ci=false +package_version_props_url='' +asset_root_url='' +access_token_suffix='' +restore_sources='' +product_build_id='' +msbuild_args=() + +# +# Functions +# +__usage() { + echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]" + echo "" + echo "Arguments:" + echo " command The command to be run." + echo " ... Arguments passed to the command. Variable number of arguments allowed." + echo "" + echo "Options:" + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " --lockfile The path to the korebuild-lock.txt file. Defaults to \$repo_path/korebuild-lock.txt" + echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." + echo " --package-version-props-url The url of the package versions props path containing dependency versions." + echo " --access-token The query string to append to any blob store access for PackageVersionPropsUrl, if any." + echo " --restore-sources Semi-colon delimited list of additional NuGet feeds to use as part of restore." + echo " --product-build-id The product build ID for correlation with orchestrated builds." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo " --reinstall Reinstall KoreBuild." + echo " --ci Apply CI specific settings and environment variables." + echo "" + echo "Description:" + echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." + echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." + + if [[ "${1:-}" != '--no-exit' ]]; then + exit 2 + fi +} + +get_korebuild() { + local version + if [ ! -f "$lockfile_path" ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lockfile_path" + fi + version="$(grep 'version:*' -m 1 "$lockfile_path")" + if [[ "$version" == '' ]]; then + __error "Failed to parse version from $lockfile_path. Expected a line that begins with 'version:'" + return 1 + fi + version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + + if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then + rm -rf "$korebuild_path" + fi + + { + if [ ! -d "$korebuild_path" ]; then + mkdir -p "$korebuild_path" + local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" + tmpfile="$(mktemp)" + echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" + if __get_remote_file "$remote_path" "$tmpfile"; then + unzip -q -d "$korebuild_path" "$tmpfile" + fi + rm "$tmpfile" || true + fi + + source "$korebuild_path/KoreBuild.sh" + } || { + if [ -d "$korebuild_path" ]; then + echo "Cleaning up after failed installation" + rm -rf "$korebuild_path" || true + fi + return 1 + } +} + +__error() { + echo -e "${RED}error: $*${RESET}" 1>&2 +} + +__warn() { + echo -e "${YELLOW}warning: $*${RESET}" +} + +__machine_has() { + hash "$1" > /dev/null 2>&1 + return $? +} + +__get_remote_file() { + local remote_path=$1 + local local_path=$2 + + if [[ "$remote_path" != 'http'* ]]; then + cp "$remote_path" "$local_path" + return 0 + fi + + local failed=false + if __machine_has wget; then + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + else + failed=true + fi + + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + fi + + if [ "$failed" = true ]; then + __error "Download failed: $remote_path" 1>&2 + return 1 + fi +} + +# +# main +# + +command="${1:-}" +shift + +while [[ $# -gt 0 ]]; do + case $1 in + -\?|-h|--help) + __usage --no-exit + exit 0 + ;; + -c|--channel|-Channel) + shift + channel="${1:-}" + [ -z "$channel" ] && __error "Missing value for parameter --channel" && __usage + ;; + --config-file|-ConfigFile) + shift + config_file="${1:-}" + [ -z "$config_file" ] && __error "Missing value for parameter --config-file" && __usage + if [ ! -f "$config_file" ]; then + __error "Invalid value for --config-file. $config_file does not exist." + exit 1 + fi + ;; + -d|--dotnet-home|-DotNetHome) + shift + DOTNET_HOME="${1:-}" + [ -z "$DOTNET_HOME" ] && __error "Missing value for parameter --dotnet-home" && __usage + ;; + --path|-Path) + shift + repo_path="${1:-}" + [ -z "$repo_path" ] && __error "Missing value for parameter --path" && __usage + ;; + --[Ll]ock[Ff]ile) + shift + lockfile_path="${1:-}" + [ -z "$lockfile_path" ] && __error "Missing value for parameter --lockfile" && __usage + ;; + -s|--tools-source|-ToolsSource) + shift + tools_source="${1:-}" + [ -z "$tools_source" ] && __error "Missing value for parameter --tools-source" && __usage + ;; + --package-version-props-url|-PackageVersionPropsUrl) + shift + # This parameter can be an empty string, but it should be set + [ -z "${1+x}" ] && __error "Missing value for parameter --package-version-props-url" && __usage + package_version_props_url="$1" + ;; + --access-token-suffix|-AccessTokenSuffix) + shift + # This parameter can be an empty string, but it should be set + [ -z "${1+x}" ] && __error "Missing value for parameter --access-token-suffix" && __usage + access_token_suffix="$1" + ;; + --restore-sources|-RestoreSources) + shift + # This parameter can be an empty string, but it should be set + [ -z "${1+x}" ] && __error "Missing value for parameter --restore-sources" && __usage + restore_sources="$1" + ;; + --asset-root-url|-AssetRootUrl) + shift + # This parameter can be an empty string, but it should be set + [ -z "${1+x}" ] && __error "Missing value for parameter --asset-root-url" && __usage + asset_root_url="$1" + ;; + --product-build-id|-ProductBuildId) + shift + # This parameter can be an empty string, but it should be set + [ -z "${1+x}" ] && __error "Missing value for parameter --product-build-id" && __usage + product_build_id="$1" + ;; + -u|--update|-Update) + update=true + ;; + --reinstall|-Reinstall) + reinstall=true + ;; + --ci|-[Cc][Ii]) + ci=true + if [[ -z "${DOTNET_HOME:-}" ]]; then + DOTNET_HOME="$DIR/.dotnet" + fi + ;; + --verbose|-Verbose) + verbose=true + ;; + *) + msbuild_args[${#msbuild_args[*]}]="$1" + ;; + esac + shift +done + +if ! __machine_has unzip; then + __error 'Missing required command: unzip' + exit 1 +fi + +if ! __machine_has curl && ! __machine_has wget; then + __error 'Missing required command. Either wget or curl is required.' + exit 1 +fi + +[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" +if [ -f "$config_file" ]; then + if __machine_has jq ; then + if jq '.' "$config_file" >/dev/null ; then + config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" + config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" + else + __error "$config_file is invalid JSON. Its settings will be ignored." + exit 1 + fi + elif __machine_has python ; then + if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then + config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" + config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" + else + __error "$config_file is invalid JSON. Its settings will be ignored." + exit 1 + fi + else + __error 'Missing required command: jq or python. Could not parse the JSON file. Its settings will be ignored.' + exit 1 + fi + + [ ! -z "${config_channel:-}" ] && channel="$config_channel" + [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" +fi + +[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" + +if [ ! -z "$package_version_props_url" ]; then + intermediate_dir="$repo_path/obj" + props_file_path="$intermediate_dir/external-dependencies.props" + mkdir -p "$intermediate_dir" + __get_remote_file "$package_version_props_url" "$props_file_path" + msbuild_args[${#msbuild_args[*]}]="-p:DotNetPackageVersionPropsPath=$props_file_path" +fi + +if [ ! -z "$restore_sources" ]; then + msbuild_args[${#msbuild_args[*]}]="-p:DotNetAdditionalRestoreSources=$restore_sources" +fi + +if [ ! -z "$asset_root_url" ]; then + msbuild_args[${#msbuild_args[*]}]="-p:DotNetAssetRootUrl=$asset_root_url" +fi + +if [ ! -z "$access_token_suffix" ]; then + msbuild_args[${#msbuild_args[*]}]="-p:DotNetAssetRootAccessTokenSuffix=$access_token_suffix" +fi + +if [ ! -z "$product_build_id" ]; then + msbuild_args[${#msbuild_args[*]}]="-p:DotNetProductBuildId=$product_build_id" +fi + +[ -z "$lockfile_path" ] && lockfile_path="$repo_path/korebuild-lock.txt" +[ -z "$channel" ] && channel='master' +[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' + +get_korebuild +set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci" + +# This incantation avoids unbound variable issues if msbuild_args is empty +# https://stackoverflow.com/questions/7577052/bash-empty-array-expansion-with-set-u +invoke_korebuild_command "$command" ${msbuild_args[@]+"${msbuild_args[@]}"} diff --git a/scripts/GenerateTags.ps1 b/scripts/GenerateTags.ps1 new file mode 100755 index 0000000000..a0dc354f44 --- /dev/null +++ b/scripts/GenerateTags.ps1 @@ -0,0 +1,130 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Generates a tag on this repo and adds a tag for each submodule that corresponds + to the value in version.props +.PARAMETER Push + Push the tag to origin +.PARAMETER OutFile + When specified, generate a .csv with repo names and tags +.PARAMETER WhatIf + Dry run +#> +[cmdletbinding(PositionalBinding = $false, SupportsShouldProcess = $true)] +param( + [switch]$Push, + [string]$OutFile +) + +$ErrorActionPreference = 'Stop' +Import-Module -Scope Local -Force "$PSScriptRoot/common.psm1" +Set-StrictMode -Version 1 + +function New-GitTag { + [cmdletbinding(SupportsShouldProcess = $true)] + param( + [Parameter(Mandatory = $true)] + [string]$Repo, + [Parameter(Mandatory = $true)] + [string]$Tag + ) + + Push-Location $Repo + try { + git show-ref --tags --verify "refs/tags/$Tag" -q + $existingTag = $? + + if ($existingTag) { + Write-Warning "${Repo}: Tag '$Tag' already exists. Skipped adding tag" + } + else { + if ($PSCmdlet.ShouldProcess($Repo, "Tag $Tag")) { + Invoke-Block { & git tag -m "v$Tag" $Tag HEAD } + Write-Host -f Magenta "${Repo}: added tag '$Tag'" + } + } + + if ($Push -and $PSCmdlet.ShouldProcess($Repo, "Push tag $Tag to origin")) { + Invoke-Block { & git push origin refs/tags/$Tag } + } + } + finally { + Pop-Location + } +} + +# +# Gets the package version by invoking KoreBuild on a repo with a custom target that spits out the package version +# +function Get-PackageVersion([string]$repoRoot) { + $buildScript = if (-not $IsCoreCLR -or $IsWindows) { 'build.ps1' } else { 'build.sh' } + $inspectTarget = "/p:CustomAfterKoreBuildTargets=$PSScriptRoot/GetPackageVersion.targets" + Write-Verbose "Running `"$repoRoot/$buildScript`" $inspectTarget /v:m /p:IsFinalBuild=true /t:Noop /t:GetPackageVersion /p:BuildNumber=t000" + # Add the /t:Noop target which may be used by the bootstrapper to skip unimportant initialization + $output = & "$repoRoot/$buildScript" $inspectTarget /v:m /p:IsFinalBuild=true /t:Noop /t:GetPackageVersion /p:BuildNumber=t000 + $output | out-string | Write-Verbose + if (-not $? -or $LASTEXITCODE -ne 0) { + throw "$buildScript failed on $repoRoot. Exit code $LASTEXITCODE" + } + $packageVersion = $output | where-object { $_ -like '*PackageVersion=*' } | select-object -first 1 + $packageVersion = $packageVersion -replace 'PackageVersion=', '' + $packageVersion = $packageVersion -replace '-final', '' + $packageVersion = $packageVersion -replace '-t000', '' + if ($packageVersion) { $packageVersion = $packageVersion.Trim() } + if (-not $packageVersion) { + throw "Could not determine final package version for $repoRoot" + } + return $packageVersion.Trim() +} + +$repoRoot = Resolve-Path "$PSScriptRoot/../" + +Write-Warning "Make sure you have run ``git submodule update`` first to pin the submodules to the correct commit" +if (-not $PSCmdlet.ShouldContinue("Continue?", "This will apply tags to all submodules")) { + Write-Host "Exiting" + exit 1 +} + + +$universeTag = Get-PackageVersion $repoRoot +New-GitTag $repoRoot $universeTag -WhatIf:$WhatIfPreference + +$tags = @([pscustomobject] @{ + repo = $(git config remote.origin.url) + tag = $universeTag + commit = $(git rev-parse HEAD) + }) + +Get-Submodules $repoRoot | ForEach-Object { + $modPath = $_.path + $module = $_.module + if (-not (Test-Path (Join-Path $_.path 'version.props'))) { + Write-Warning "$module does not have a version.props file. Skipping" + return + } + + try { + $tag = Get-PackageVersion $_.path + if ($tag -ne $universeTag) { + Write-Warning "${module}: version ($tag) does not match universe ($universeTag)" + } + $tags += [pscustomobject] @{ + repo = $_.remote + tag = $tag + commit = $_.commit + } + } + catch { + Write-Warning "${module}: Could not automatically determine tag for $modPath. Skipping" + return + } + + New-GitTag $_.path $tag -WhatIf:$WhatIfPreference +} + +$tags | Format-Table + +if ($OutFile) { + $tags | Select-Object -Property * | Export-Csv -Path $OutFile -WhatIf:$false -NoTypeInformation +} diff --git a/scripts/GetPackageVersion.targets b/scripts/GetPackageVersion.targets new file mode 100644 index 0000000000..061c114027 --- /dev/null +++ b/scripts/GetPackageVersion.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/scripts/ListRepoVersions.ps1 b/scripts/ListRepoVersions.ps1 new file mode 100644 index 0000000000..06ba399166 --- /dev/null +++ b/scripts/ListRepoVersions.ps1 @@ -0,0 +1,23 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Lists the version of all submodules and this repo +.PARAMETER Shipping + Only list repos that are shipping +#> +[cmdletbinding(SupportsShouldProcess = $true)] +param( + [switch]$Shipping = $false +) + +Set-StrictMode -Version 2 +$ErrorActionPreference = 'Stop' + +Import-Module -Scope Local -Force "$PSScriptRoot/common.psm1" + +Assert-Git + +$RepoRoot = Resolve-Path "$PSScriptRoot/../" + +Get-Submodules $RepoRoot -Shipping:$Shipping | Format-Table -Property 'module','versionPrefix' diff --git a/scripts/PatchVersionPrefix.ps1 b/scripts/PatchVersionPrefix.ps1 new file mode 100755 index 0000000000..d8cce86487 --- /dev/null +++ b/scripts/PatchVersionPrefix.ps1 @@ -0,0 +1,111 @@ +#!/usr/bin/env pwsh -c + +<# +.SYNOPSIS + Updates the version.props file in repos to a newer patch version +.PARAMETER Repos + A list of the repositories that should be patched +.PARAMETER Mode + Version bump options: Major, Minor, Patch +.PARAMETER VersionSuffix + The version suffix to use +#> +[cmdletbinding(SupportsShouldProcess = $true)] +param( + [Parameter(Mandatory = $true)] + [string[]]$Repos, + [Parameter(Mandatory = $true)] + [ValidateSet('Major', 'Minor', 'Patch')] + [string]$Mode, + [string]$VersionSuffix = $null, + [switch]$NoCommit +) + +$ErrorActionPreference = 'Stop' + +Import-Module -Scope Local -Force "$PSScriptRoot/common.psm1" + +function SetVersionSuffix([System.Xml.XmlNode]$node) { + if (-not $node) { + return + } + $node.InnerText = $VersionSuffix + return "Setting $($node.Name) to $VersionSuffix" +} + +function BumpVersion([System.Xml.XmlNode]$node) { + if (-not $node) { + return + } + [version] $version = $node.InnerText + + $experimental = $version.Major -eq 0 + + switch ($mode) { + { ($_ -ne 'Patch') -and $experimental} { + $node.InnerText = "{0}.{1}.{2}" -f $version.Major, ($version.Minor + 1), 0 + } + { ($_ -eq 'Major') -and -not $experimental } { + $node.InnerText = "{0}.{1}.{2}" -f ($version.Major + 1), 0, 0 + } + { ($_ -eq 'Minor') -and -not $experimental } { + $node.InnerText = "{0}.{1}.{2}" -f $version.Major, ($version.Minor + 1), 0 + } + 'Patch' { + $node.InnerText = "{0}.{1}.{2}" -f $version.Major, $version.Minor, ($version.Build + 1) + } + default { + throw "Could not figure out how to apply patch policy $mode" + } + } + return "Bumping version from $version to $($node.InnerText)" +} + +foreach ($repo in $Repos) { + $repoPath = "$PSScriptRoot/../modules/$repo" + Push-Location $repoPath + try + { + $path = "$repoPath/version.props" + Write-Host -ForegroundColor Magenta "Updating $repo" + if (-not (Test-Path $path)) { + Write-Warning "$path does not exist" + continue + } + $path = Resolve-Path $path + Write-Verbose "$path" + [xml] $xml = LoadXml $path + + $suffix = $xml.SelectSingleNode('/Project/PropertyGroup/VersionSuffix') + if (-not $suffix) { + write-error "$path does not have VersionSuffix" + } + + if ($VersionSuffix) { + SetVersionSuffix $xml.SelectSingleNode('/Project/PropertyGroup/VersionSuffix') | write-host + SetVersionSuffix $xml.SelectSingleNode('/Project/PropertyGroup/ExperimentalProjectVersionSuffix') | write-host + SetVersionSuffix $xml.SelectSingleNode('/Project/PropertyGroup/ExperimentalVersionSuffix') | write-host + } + + $versionPrefix = $xml.SelectSingleNode('/Project/PropertyGroup/VersionPrefix') + $epxVersionPrefix = $xml.SelectSingleNode('/Project/PropertyGroup/ExperimentalProjectVersionPrefix') + $exVersionPrefix = $xml.SelectSingleNode('/Project/PropertyGroup/ExperimentalVersionPrefix') + BumpVersion $epxVersionPrefix | write-host + BumpVersion $exVersionPrefix | write-host + $message = BumpVersion $versionPrefix + Write-Host $message + + if ($PSCmdlet.ShouldProcess("Update $path")) { + SaveXml $xml $path + if (-not $NoCommit) { + Invoke-Block { & git add $path } + Invoke-Block { & git commit -m $message } + } + } + } + finally + { + Pop-Location + } +} + diff --git a/scripts/Tag-TeamCityBuild.ps1 b/scripts/Tag-TeamCityBuild.ps1 new file mode 100755 index 0000000000..d624d4f50c --- /dev/null +++ b/scripts/Tag-TeamCityBuild.ps1 @@ -0,0 +1,37 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Tags the given TeamCity build with the given tag. +.PARAMETER BuildId + The BuildId of the build to be tagged. +.PARAMETER Tag + The tag to put on this build. +#> + +[cmdletbinding(SupportsShouldProcess = $true)] +param( + [Parameter(Mandatory = $true)] + [string]$BuildId, + [Parameter(Mandatory = $true)] + [string]$Tag, + [Parameter(Mandatory = $true)] + [string]$UserName, + [Parameter(Mandatory = $true)] + [string]$Password +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version 2 + +$authInfo = "${UserName}:$Password" +$authEncoded = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($authInfo)) +$basicAuthValue = "Basic $authEncoded" + +$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" +$headers.Add("Authorization", $basicAuthValue) +$headers.Add("Content-Type", "text/plain") + +$uri = "http://aspnetci/app/rest/builds/$BuildId/tags/" + +Invoke-WebRequest -Uri $uri -Method 'POST' -Headers $headers -Body $Tag -ErrorAction SilentlyContinue diff --git a/scripts/TagRepos.ps1 b/scripts/TagRepos.ps1 new file mode 100644 index 0000000000..2bb595027c --- /dev/null +++ b/scripts/TagRepos.ps1 @@ -0,0 +1,66 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Tags each repo according to VersionPrefix in version.props of that repo +.PARAMETER Push + Push all updated tags +.PARAMETER ForceUpdateTag + This will call git tag --force +#> +[cmdletbinding(SupportsShouldProcess = $true)] +param( + [switch]$Push = $false, + [switch]$ForceUpdateTag = $false +) + +Set-StrictMode -Version 2 +$ErrorActionPreference = 'Stop' + +Import-Module -Scope Local -Force "$PSScriptRoot/common.psm1" + +Assert-Git + +$RepoRoot = Resolve-Path "$PSScriptRoot/../" + +Get-Submodules $RepoRoot -Shipping | % { + Push-Location $_.path | Out-Null + try { + + if (-not $_.versionPrefix) { + Write-Warning "Could not determine tag version for $(_.path)" + } + else { + $tag = $_.versionPrefix + Write-Host "$($_.module) => $tag" + + $gitTagArgs = @() + if ($ForceUpdateTag) { + $gitTagArgs += '--force' + } + + Invoke-Block { & git tag @gitTagArgs $tag } + + if ($Push) { + $gitPushArgs = @() + if ($WhatIfPreference) { + $gitPushArgs += '--dry-run' + } + Invoke-Block { & git push @gitPushArgs origin "refs/tags/${tag}" } + } + + if ($WhatIfPreference) { + Invoke-Block { & git tag -d $tag } | Out-Null + } + } + } + catch { + Write-Host -ForegroundColor Red "Could not update $_" + throw + } + finally { + Pop-Location + } +} + + diff --git a/scripts/UpdateBuildTools.ps1 b/scripts/UpdateBuildTools.ps1 new file mode 100755 index 0000000000..efcda1e03b --- /dev/null +++ b/scripts/UpdateBuildTools.ps1 @@ -0,0 +1,99 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Updates the build tools version and generates a commit message with the list of changes +.PARAMETER RepoRoot + The directory containing the repo +.PARAMETER GitAuthorName + The author name to use in the commit message. (Optional) +.PARAMETER GitAuthorEmail + The author email to use in the commit message. (Optional) +.PARAMETER GitCommitArgs + Additional arguments to pass into git-commit +.PARAMETER NoCommit + Make changes without executing git-commit +.PARAMETER ToolsSource + The location of the build tools +.PARAMETER Force + Specified this to make a commit with any changes +#> +[cmdletbinding(SupportsShouldProcess = $true)] +param( + [string]$RepoRoot, + [string]$GitAuthorName = $null, + [string]$GitAuthorEmail = $null, + [string[]]$GitCommitArgs = @(), + [string]$ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools', + [switch]$NoCommit, + [switch]$Force +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version 2 + +if (-not $RepoRoot) { + $RepoRoot = Resolve-Path "$PSScriptRoot\.." +} + +Import-Module "$PSScriptRoot/common.psm1" -Scope Local -Force + +function Get-KoreBuildVersion { + $lockFile = "$RepoRoot/korebuild-lock.txt" + if (!(Test-Path $lockFile)) { + return '' + } + $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 + if (!$version) { + Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" + } + $version = $version.TrimStart('version:').Trim() + return $version +} + +Push-Location $RepoRoot +try { + Assert-Git + + $oldVersion = Get-KoreBuildVersion + + & "$RepoRoot/run.ps1" -Update -ToolsSource $ToolsSource -Command noop | Out-Null + + $newVersion = Get-KoreBuildVersion + + if ($oldVersion -eq $newVersion) { + Write-Host -ForegroundColor Magenta 'No changes to build tools' + exit 0 + } + + Invoke-Block { git add "$RepoRoot/global.json" } + Invoke-Block { git add "$RepoRoot/korebuild-lock.txt" } + Invoke-Block { git add "$RepoRoot/build/dependencies.props" } + + $shortMessage = "Updating BuildTools from $oldVersion to $newVersion" + # add this to the commit message to make it possible to filter commit triggers based on message + $message = "$shortMessage`n`n[auto-updated: buildtools]" + + if (-not $NoCommit -and ($Force -or ($PSCmdlet.ShouldContinue($shortMessage, 'Create a new commit with these changes?')))) { + + $gitConfigArgs = @() + if ($GitAuthorName) { + $gitConfigArgs += '-c', "user.name=$GitAuthorName" + } + + if ($GitAuthorEmail) { + $gitConfigArgs += '-c', "user.email=$GitAuthorEmail" + } + + Invoke-Block { git @gitConfigArgs commit -m $message @GitCommitArgs } + } + else { + # If composing this script with others, return the message that would have been used + return @{ + message = $message + } + } +} +finally { + Pop-Location +} diff --git a/scripts/UpdateDependencies.ps1 b/scripts/UpdateDependencies.ps1 new file mode 100755 index 0000000000..7aeb8fd3f8 --- /dev/null +++ b/scripts/UpdateDependencies.ps1 @@ -0,0 +1,81 @@ +#!/usr/bin/env pwsh -c +<# +.PARAMETER BuildXml + The URL or file path to a build.xml file that defines package versions to be used +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + $BuildXml, + [switch]$NoCommit, + [string]$GithubUpstreamBranch, + [string]$GithubEmail, + [string]$GithubUsername, + [string]$GithubToken +) + +$ErrorActionPreference = 'Stop' +Import-Module -Scope Local -Force "$PSScriptRoot/common.psm1" +Set-StrictMode -Version 1 +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +if (-not $NoCommit) { + Set-GitHubInfo $GithubToken $GithubUsername $GithubEmail +} + +$depsPath = Resolve-Path "$PSScriptRoot/../build/dependencies.props" +[xml] $dependencies = LoadXml $depsPath + +if ($BuildXml -like 'http*') { + $url = $BuildXml + New-Item -Type Directory "$PSScriptRoot/../obj/" -ErrorAction Ignore + $BuildXml = "$PSScriptRoot/../obj/build.xml" + Write-Verbose "Downloading from $url to $BuildXml" + Invoke-WebRequest -OutFile $BuildXml $url +} + +[xml] $remoteDeps = LoadXml $BuildXml + +$variables = @{} + +foreach ($package in $remoteDeps.SelectNodes('//Package')) { + $packageId = $package.Id + $packageVersion = $package.Version + $varName = PackageIdVarName $packageId + Write-Verbose "Found {id: $packageId, version: $packageVersion, varName: $varName }" + + if ($variables[$varName]) { + if ($variables[$varName].Where( {$_ -eq $packageVersion}, 'First').Count -eq 0) { + $variables[$varName] += $packageVersion + } + } + else { + $variables[$varName] = @($packageVersion) + } +} + +if (-not $NoCommit) { + $currentBranch = Invoke-Block { & git rev-parse --abbrev-ref HEAD } + + $destinationBranch = "dotnetbot/UpdateDeps" + Invoke-Block { & git checkout -tb $destinationBranch "origin/$GithubUpstreamBranch" } +} + +try { + $updatedVars = UpdateVersions $variables $dependencies $depsPath + + if ($NoCommit) { + exit 0 + } + + $body = CommitUpdatedVersions $updatedVars $dependencies $depsPath + + if ($body) { + CreatePR "aspnet" $GithubUsername $GithubUpstreamBranch $destinationBranch $body $GithubToken + } +} +finally { + if (-not $NoCommit) { + Invoke-Block { & git checkout $currentBranch } + } +} diff --git a/scripts/UpdateDependenciesCoreFx.ps1 b/scripts/UpdateDependenciesCoreFx.ps1 new file mode 100644 index 0000000000..03be551f8a --- /dev/null +++ b/scripts/UpdateDependenciesCoreFx.ps1 @@ -0,0 +1,134 @@ + +[CmdletBinding()] +param( + [switch]$NoCommit, + [string]$GithubEmail, + [string]$GithubUsername, + [string]$GithubToken +) +# This script only works against master at the moment because only master prod-con builds allow you to access their results before the entire chain is finished. + +$ErrorActionPreference = 'Stop' +Import-Module -Scope Local -Force "$PSScriptRoot/common.psm1" +Set-StrictMode -Version 1 +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +$githubRaw = "https://raw.githubusercontent.com" +$versionsRepo = "dotnet/versions" +$versionsBranch = "master" + +$coreSetupRepo = "dotnet/core-setup" +$coreFxRepo = "dotnet/corefx" + +$coreSetupVersions = "$githubRaw/$versionsRepo/$versionsBranch/build-info/$coreSetupRepo/master/Latest_Packages.txt" + +$tempDir = "$PSScriptRoot/../obj" + +mkdir -Path $tempDir -ErrorAction Ignore + +$localCoreSetupVersions = "$tempDir/coresetup.packages" +Write-Host "Downloading $coreSetupVersions to $localCoreSetupVersions" +Invoke-WebRequest -OutFile $localCoreSetupVersions -Uri $coreSetupVersions + +$msNetCoreAppPackageVersion = $null +$msNetCoreAppPackageName = "Microsoft.NETCore.App" + +Set-GitHubInfo $GithubToken $GithubUsername $GithubEmail + +$variables = @{} + +foreach ($line in Get-Content $localCoreSetupVersions) { + if ($line.StartsWith("$msNetCoreAppPackageName ")) { + $msNetCoreAppPackageVersion = $line.Trim("$msNetCoreAppPackageName ") + } + $parts = $line.Split(' ') + $packageName = $parts[0] + + $varName = "$packageName" + "PackageVersion" + $varName = $varName.Replace('.', '') + + $packageVersion = $parts[1] + if ($variables[$varName]) { + if ($variables[$varName].Where( {$_ -eq $packageVersion}, 'First').Count -eq 0) { + $variables[$varName] += $packageVersion + } + } + else { + $variables[$varName] = @($packageVersion) + } +} + +if (!$msNetCoreAppPackageVersion) { + throw "$msNetCoreAppPackageName was not in $coreSetupVersions" +} + +$coreAppDownloadLink = "https://dotnet.myget.org/F/dotnet-core/api/v2/package/$msNetCoreAppPackageName/$msNetCoreAppPackageVersion" +$netCoreAppNupkg = "$tempDir/microsoft.netcore.app.zip" +Invoke-WebRequest -OutFile $netCoreAppNupkg -Uri $coreAppDownloadLink +$expandedNetCoreApp = "$tempDir/microsoft.netcore.app/" +Expand-Archive -Path $netCoreAppNupkg -DestinationPath $expandedNetCoreApp -Force +$versionsTxt = "$expandedNetCoreApp/$msNetCoreAppPackageName.versions.txt" + +$versionsCoreFxCommit = $null +foreach ($line in Get-Content $versionsTxt) { + if ($line.StartsWith("dotnet/versions/corefx")) { + $versionsCoreFxCommit = $line.Split(' ')[1] + break + } +} + +if (!$versionsCoreFxCommit) { + Throw "no 'dotnet/versions/corefx' in versions.txt of Microsoft.NETCore.App" +} + +$coreFxVersionsUrl = "$githubRaw/$versionsRepo/$versionsCoreFxCommit/build-info/$coreFxRepo/$versionsBranch/Latest_Packages.txt" +$localCoreFxVersions = "$tempDir/$corefx.packages" +Invoke-WebRequest -OutFile $localCoreFxVersions -Uri $coreFxVersionsUrl + +foreach ($line in Get-Content $localCoreFxVersions) { + $parts = $line.Split(' ') + + $packageName = $parts[0] + + $varName = "$packageName" + "PackageVersion" + $varName = $varName.Replace('.', '') + $packageVersion = $parts[1] + if ($variables[$varName]) { + if ($variables[$varName].Where( {$_ -eq $packageVersion}, 'First').Count -eq 0) { + $variables[$varName] += $packageVersion + } + } + else { + $variables[$varName] = @($packageVersion) + } +} + +$depsPath = Resolve-Path "$PSScriptRoot/../build/dependencies.props" +Write-Host "Loading deps from $depsPath" +[xml] $dependencies = LoadXml $depsPath + +if (-not $NoCommit) { + $baseBranch = "master" + Invoke-Block { & git fetch origin } + + $currentBranch = Invoke-Block { & git rev-parse --abbrev-ref HEAD } + $destinationBranch = "upgrade-netcore-deps" + + Invoke-Block { & git checkout -tb $destinationBranch "origin/$baseBranch" } +} + +try { + $updatedVars = UpdateVersions $variables $dependencies $depsPath + if (-not $NoCommit) { + $body = CommitUpdatedVersions $updatedVars $dependencies $depsPath "Upgrade to .NET Core $msNetCoreAppPackageVersion" + + if ($body) { + CreatePR "aspnet" $GithubUsername $baseBranch $destinationBranch $body $GithubToken + } + } +} +finally { + if (-not $NoCommit) { + Invoke-Block { & git checkout $currentBranch } + } +} diff --git a/scripts/UpdateRepos.ps1 b/scripts/UpdateRepos.ps1 new file mode 100755 index 0000000000..69d23232d8 --- /dev/null +++ b/scripts/UpdateRepos.ps1 @@ -0,0 +1,148 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Updates each repo Universe builds to new dependencies.props. +.PARAMETER Source + The NuGet package source to find the lineup on. +.PARAMETER LineupID + The ID of the Lineup to determine which versions to use. +.PARAMETER LineupVersion + The version of the Lineup to be used. +.PARAMETER NoPush + Make commits without pusing. +.PARAMETER GitAuthorName + The author name to use in the commit message. (Optional) +.PARAMETER GitAuthorEmail + The author email to use in the commit message. (Optional) +.PARAMETER Force + Specified this to push commits without prompting. +.PARAMETER GitCommitArgs + Any remaining arguments are passed as arguments to 'git commit' actions in each repo. +#> +[cmdletbinding(SupportsShouldProcess = $true)] +param( + [Parameter(Mandatory = $true)] + [string]$Source, + [Parameter(Mandatory = $true)] + [string]$LineupID, + [Parameter(Mandatory = $true)] + [string]$LineupVersion, + [switch]$NoPush, + [string]$GitAuthorName = $null, + [string]$GitAuthorEmail = $null, + [switch]$Force, + [string[]]$GitCommitArgs = @() +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version 2 + +Import-Module "$PSScriptRoot/common.psm1" -Scope Local -Force + +$RepoRoot = Resolve-Path "$PSScriptRoot\.." +$ModuleDirectory = Join-Path $RepoRoot "modules" + +$gitConfigArgs = @() +if ($GitAuthorName) { + $gitConfigArgs += '-c', "user.name=$GitAuthorName" +} + +if ($GitAuthorEmail) { + $gitConfigArgs += '-c', "user.email=$GitAuthorEmail" +} + +Push-Location $ModuleDirectory +try { + + $build_errors = @() + $submodules = Get-Submodules $RepoRoot + foreach ($submodule in $submodules) { + Push-Location $submodule.path + try { + Invoke-Block { & git fetch } + Invoke-Block { & git checkout origin/$($submodule.branch) } + $depsFile = Join-Path (Join-Path $($submodule.path) "build") "dependencies.props" + + if (!(Test-Path $depsFile)) { + Write-Warning "No build\dependencies.props file exists for '$($submodule.module)'." + continue + } + + $koreBuildLock = "korebuild-lock.txt" + + $universeKoreBuildLock = (Join-Path $RepoRoot $koreBuildLock) + $submoduleKoreBuildLock = (Join-Path $submodule.path $koreBuildLock) + + Copy-Item $universeKoreBuildLock $submoduleKoreBuildLock -Force + + Write-Verbose "About to update dependencies.props for $($submodule.module)" + & .\run.ps1 upgrade deps --source $Source --id $LineupID --version $LineupVersion --deps-file $depsFile + + Invoke-Block { & git @gitConfigArgs add $depsFile $koreBuildLock } + + # If there were any changes test and push. + & git diff --cached --quiet ./ + if ($LASTEXITCODE -ne 0) { + Invoke-Block { & git @gitConfigArgs commit --quiet -m "Update dependencies.props`n`n[auto-updated: dependencies]" @GitCommitArgs } + + # Prepare this submodule for push + $sshUrl = "git@github.com:aspnet/$($submodule.module)" + Invoke-Block { & git remote set-url --push origin $sshUrl } + + # Test the submodule + try { + Invoke-Block { & .\run.ps1 default-build /p:SkipTests=true } + } + catch { + Write-Warning "Error in $($submodule.module): $_" + $build_errors += @{ + Repo = $submodule.module + Message = $_ + } + continue + } + + # Push the changes + if (-not $NoPush -and ($Force -or ($PSCmdlet.ShouldContinue("Pushing updates to repos.", 'Push the changes to these repos?')))) { + try { + $newBranch = "maestro/$($submodule.branch)" + Invoke-Block { & git @gitConfigArgs push origin HEAD:refs/heads/$newBranch} + } + catch { + Write-Warning "Error in pushing $($newBranch): $_" + $build_errors += @{ + Repo = $submodule.module + Message = $_ + } + continue + } + } + } + else { + Write-Host "No changes in $($submodule.module)" + } + } + catch { + Write-Warning "Error in $($submodule.module): $_" + $build_errors += @{ + Repo = $submodule.module + Message = $_ + } + } + finally { + Pop-Location + } + } + + if ($build_errors.Count -gt 0 ) { + Write-Warning "The following repos failed:" + foreach ($error in $build_errors) { + Write-Warning " - $($error.Repo)" + } + throw "Failed to build" + } +} +finally { + Pop-Location +} diff --git a/scripts/UpdateSubmodules.ps1 b/scripts/UpdateSubmodules.ps1 new file mode 100755 index 0000000000..11058328f0 --- /dev/null +++ b/scripts/UpdateSubmodules.ps1 @@ -0,0 +1,144 @@ +#!/usr/bin/env pwsh -c + +<# +.SYNOPSIS + Updates git submodules and generates a commit message with the list of changes +.PARAMETER GitAuthorName + The author name to use in the commit message. (Optional) +.PARAMETER GitAuthorEmail + The author email to use in the commit message. (Optional) +.PARAMETER GitCommitArgs + Additional arguments to pass into git-commit +.PARAMETER NoCommit + Make changes without executing git-commit +.PARAMETER Force + Specified this to make a commit with any changes +.PARAMETER IgnoredRepos + Repos to not update (likely because they are temporarily broken). +#> +[cmdletbinding(SupportsShouldProcess = $true)] +param( + [string]$GitAuthorName = $null, + [string]$GitAuthorEmail = $null, + [string[]]$GitCommitArgs = @(), + [switch]$NoCommit, + [switch]$Force, + [string[]]$IgnoredRepos = @() +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version 2 + +$RepoRoot = Resolve-Path "$PSScriptRoot\.." +$ModuleDirectory = Join-Path $RepoRoot "modules" + +Import-Module "$PSScriptRoot/common.psm1" -Scope Local -Force + +function Get-GitChanges([string]$Path) { + Write-Verbose "git diff --cached --quiet $Path" + & git diff --cached --quiet $Path | Out-Null + if ($LastExitCode -ne 0) { + return $true + } + Write-Verbose "git diff --quiet $Path" + & git diff --quiet $Path | Out-Null + return $LastExitCode -ne 0 +} + +Push-Location $RepoRoot | Out-Null +try { + Assert-Git + + Write-Host "Checking that submodules are in a clean state first..." + if (Get-GitChanges $ModuleDirectory) { + Write-Error "$RepoRoot/modules is in an unclean state. Reset submodules first by running ``git submodule update``" + exit 1 + } + + $submodules = Get-Submodules $RepoRoot -Verbose:$VerbosePreference + + foreach ($submodule in $submodules) { + $submoduleName = $submodule.module + if ($IgnoredRepos.Contains($submoduleName)) + { + Write-Host "Skipping $submoduleName due to IgnoredRepos." + continue + } + + $submodulePath = $submodule.path + Write-Host "Updating $submodulePath" + + $vcs_name = "BUILD_VCS_NUMBER_" + ($submodule.module -replace '\.','_') + $newCommit = [environment]::GetEnvironmentVariable($vcs_name) + + if (-not $newCommit) { + if ($env:TEAMCITY_PROJECT_NAME) { + throw "TeamCity env variable '$vcs_name' not found. Make sure to configure a VCS root for $submodulePath" + } + Invoke-Block { & git submodule update --remote $submodulePath } + Push-Location $submodulePath | Out-Null + try { + $newCommit = $(git rev-parse HEAD) + } + finally { + Pop-Location | Out-Null + } + } + else { + Push-Location $submodulePath | Out-Null + try { + Invoke-Block { & git checkout $newCommit } + } + finally { + Pop-Location | Out-Null + } + } + + $submodule.newCommit = $newCommit + if ($newCommit -ne $submodule.commit) { + $submodule.changed = $true + Write-Host -ForegroundColor Cyan "`t=> $($submodule.module) updated to $($submodule.newCommit)" + } + else { + Write-Host -ForegroundColor Magenta "`t$($submodule.module) did not change" + } + } + + $changes = $submodules ` + | ? { $_.changed } ` + | % { + Invoke-Block { & git add $_.path } + "$($_.module) => $($_.newCommit)" + } + + if ($changes) { + $shortMessage = "Updating submodule(s) `n`n$( $changes -join "`n" )" + # add this to the commit message to make it possible to filter commit triggers based on message + $message = "$shortMessage`n`n[auto-updated: submodules]" + if (-not $NoCommit -and ($Force -or ($PSCmdlet.ShouldContinue($shortMessage, 'Create a new commit with these changes?')))) { + + $gitConfigArgs = @() + if ($GitAuthorName) { + $gitConfigArgs += '-c',"user.name=$GitAuthorName" + } + + if ($GitAuthorEmail) { + $gitConfigArgs += '-c',"user.email=$GitAuthorEmail" + } + + Invoke-Block { & git @gitConfigArgs commit -m $message @GitCommitArgs } + } + else { + # If composing this script with others, return the message that would have been used + return @{ + message = $message + } + } + } + else { + Write-Host -ForegroundColor Magenta 'No changes detected in git submodules' + } +} +finally { + Pop-Location +} diff --git a/scripts/common.psm1 b/scripts/common.psm1 new file mode 100644 index 0000000000..5225c6d7b8 --- /dev/null +++ b/scripts/common.psm1 @@ -0,0 +1,314 @@ +$ErrorActionPreference = 'Stop' +# Update the default TLS support to 1.2 +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +function Assert-Git { + if (!(Get-Command git -ErrorAction Ignore)) { + Write-Error 'git is required to execute this script' + exit 1 + } +} + +function Invoke-Block([scriptblock]$cmd, [string]$WorkingDir = $null) { + if ($WorkingDir) { + Push-Location $WorkingDir + } + + try { + + $cmd | Out-String | Write-Verbose + & $cmd + + # Need to check both of these cases for errors as they represent different items + # - $?: did the powershell script block throw an error + # - $lastexitcode: did a windows command executed by the script block end in error + if ((-not $?) -or ($lastexitcode -ne 0)) { + if ($error -ne $null) + { + Write-Warning $error[0] + } + throw "Command failed to execute: $cmd" + } + } + finally { + if ($WorkingDir) { + Pop-Location + } + } +} + +function Get-Submodules { + param( + [Parameter(Mandatory = $true)] + [string]$RepoRoot, + [switch]$Shipping + ) + + $moduleConfigFile = Join-Path $RepoRoot ".gitmodules" + $submodules = @() + + [xml] $submoduleConfig = Get-Content "$RepoRoot/build/submodules.props" + $repos = $submoduleConfig.Project.ItemGroup.Repository | % { $_.Include } + + Get-ChildItem "$RepoRoot/modules/*" -Directory ` + | ? { (-not $Shipping) -or $($repos -contains $($_.Name)) -or $_.Name -eq 'Templating' } ` + | % { + Push-Location $_ | Out-Null + Write-Verbose "Attempting to get submodule info for $_" + + if (Test-Path 'version.props') { + [xml] $versionXml = Get-Content 'version.props' + $versionPrefix = $versionXml.Project.PropertyGroup.VersionPrefix | select-object -first 1 + $versionSuffix = $versionXml.Project.PropertyGroup.VersionSuffix | select-object -first 1 + } + else { + $versionPrefix = '' + $versionSuffix = '' + } + + try { + $data = [PSCustomObject] @{ + path = $_ + module = $_.Name + commit = $(git rev-parse HEAD) + newCommit = $null + changed = $false + remote = $(git config remote.origin.url) + branch = $(git config -f $moduleConfigFile --get submodule.modules/$($_.Name).branch ) + versionPrefix = $versionPrefix + versionSuffix = $versionSuffix + } + + $submodules += $data + } + finally { + Pop-Location | Out-Null + } + } + + return $submodules +} + +function SaveXml([xml]$xml, [string]$path) { + Write-Verbose "Saving to $path" + $ErrorActionPreference = 'stop' + + $settings = New-Object System.XML.XmlWriterSettings + $settings.OmitXmlDeclaration = $true + $settings.Encoding = New-Object System.Text.UTF8Encoding( $true ) + $writer = [System.XML.XMLTextWriter]::Create($path, $settings) + $xml.Save($writer) + $writer.Close() +} + +function LoadXml([string]$path) { + Write-Verbose "Reading from $path" + + $ErrorActionPreference = 'stop' + $obj = new-object xml + $obj.PreserveWhitespace = $true + $obj.Load($path) + return $obj +} + +function PackageIdVarName([string]$packageId) { + $canonicalVarName = '' + $upperCaseNext = $true + for ($i = 0; $i -lt $packageId.Length; $i++) { + $ch = $packageId[$i] + if (-not [System.Char]::IsLetterOrDigit(($ch))) { + $upperCaseNext = $true + continue + } + if ($upperCaseNext) { + $ch = [System.Char]::ToUpperInvariant($ch) + $upperCaseNext = $false + } + $canonicalVarName += $ch + } + $canonicalVarName += "PackageVersion" + return $canonicalVarName +} + +function Ensure-Hub() { + $tmpDir = "$PSScriptRoot\tmp" + $zipDir = "$tmpDir\Hub" + $hubLocation = "$zipDir\bin\hub.exe" + + if (-Not (Test-Path $hubLocation) ) { + $source = "https://github.com/github/hub/releases/download/v2.3.0-pre9/hub-windows-amd64-2.3.0-pre9.zip" + $zipLocation = "$tmpDir\hub.zip" + + mkdir -Path $tmpDir -ErrorAction Ignore | Out-Null + + Invoke-WebRequest -OutFile $zipLocation -Uri $source + + Expand-Archive -Path $zipLocation -DestinationPath $zipDir -Force + if (-Not (Test-Path $hubLocation)) { + throw "Hub couldn't be downloaded" + } + } + + return $hubLocation +} + +function CreatePR( + [string]$baseFork, + [string]$headFork, + [string]$baseBranch, + [string]$destinationBranch, + [string]$body, + [string]$gitHubToken) { + $hubLocation = Ensure-Hub + + Invoke-Block { git push -f https://$gitHubToken@github.com/$headFork/Universe.git $destinationBranch } + & $hubLocation pull-request -f -b "${baseFork}:$baseBranch" -h "${headFork}:$destinationBranch" -m $body +} + +function Set-GithubInfo( + [string]$GitHubPassword, + [string]$GitHubUser, + [string]$GitHubEmail) +{ + $Env:GITHUB_TOKEN = $GitHubPassword + $Env:GITHUB_USER = $GitHubUser + $Env:GITHUB_EMAIL = $GitHubEmail +} +function CommitUpdatedVersions( + [hashtable]$updatedVars, + [xml]$dependencies, + [string]$depsPath, + [string]$subject = 'Updating external dependencies') +{ + $count = $updatedVars.Count + if ($count -gt 0) { + & git add build\dependencies.props + + $gitConfigArgs = @() + if ($env:GITHUB_USER) { + $gitConfigArgs += '-c',"user.name=$env:GITHUB_USER" + } + + if ($env:GITHUB_EMAIL) { + $gitConfigArgs += '-c',"user.email=$env:GITHUB_EMAIL" + } + + Invoke-Block { & git @gitConfigArgs commit -m $subject } | Out-Null + + $body = "$subject`n`n" + + $body += "New versions:`n" + + foreach ($var in $updatedVars.GetEnumerator()) { + $body += " $($var.Name)`n" + } + + return $body + } +} + +function UpdateVersions([hashtable]$variables, [xml]$dependencies, [string]$depsPath) { + $updatedVars = @{} + + foreach ($varName in ($variables.Keys | sort)) { + $packageVersions = $variables[$varName] + if ($packageVersions.Length -gt 1) { + Write-Warning "Skipped $varName. Multiple version found. { $($packageVersions -join ', ') }." + continue + } + + $packageVersion = $packageVersions | Select-Object -First 1 + + $depVarNode = $dependencies.SelectSingleNode("//PropertyGroup[`@Label=`"Package Versions: Auto`"]/$varName") + if ($depVarNode -and $depVarNode.InnerText -ne $packageVersion) { + $depVarNode.InnerText = $packageVersion + Write-Host -f DarkGray " Updating $varName to $packageVersion" + $updatedVars[$varName] = $packageVersion + } + elseif ($depVarNode) { + Write-Host -f DarkBlue " Didn't update $varName to $packageVersion because it was $($depVarNode.InnerText)" + } + else { + # This isn't a dependency we use + } + } + + if ($updatedVars.Count -gt 0) { + Write-Host -f Cyan "Updating version variables in $depsPath" + SaveXml $dependencies $depsPath + } + else { + Write-Host -f Green "No changes found" + } + + return $updatedVars +} + +function Get-MSBuildPath { + param( + [switch]$Prerelease, + [string[]]$Requires + ) + + $vsInstallDir = $null + if ($env:VSINSTALLDIR -and (Test-Path $env:VSINSTALLDIR)) { + $vsInstallDir = $env:VSINSTALLDIR + Write-Verbose "Using VSINSTALLDIR=$vsInstallDir" + } + else { + $vswhere = "${env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe" + Write-Verbose "Using vswhere.exe from $vswhere" + + if (-not (Test-Path $vswhere)) { + Write-Error "Missing prerequisite: could not find vswhere" + } + + [string[]] $vswhereArgs = @() + + if ($Prerelease) { + $vswhereArgs += '-prerelease' + } + + if ($Requires) { + foreach ($r in $Requires) { + $vswhereArgs += '-requires', $r + } + } + + $installs = & $vswhere -format json -version '[15.0, 16.0)' -latest -products * @vswhereArgs | ConvertFrom-Json + if (!$installs) { + Write-Error "Missing prerequisite: could not find any installations of Visual Studio" + } + + $vs = $installs | Select-Object -First 1 + $vsInstallDir = $vs.installationPath + Write-Host "Using $($vs.displayName)" + } + + $msbuild = Join-Path $vsInstallDir 'MSBuild/15.0/bin/msbuild.exe' + if (!(Test-Path $msbuild)) { + Write-Error "Missing prerequisite: could not find msbuild.exe" + } + return $msbuild +} + +function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { + if ($RemotePath -notlike 'http*') { + Copy-Item $RemotePath $LocalPath + return + } + + $retries = 10 + while ($retries -gt 0) { + $retries -= 1 + try { + Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath + return + } + catch { + Write-Verbose "Request failed. $retries retries remaining" + } + } + + Write-Error "Download failed: '$RemotePath'." +} diff --git a/scripts/requirements.txt b/scripts/requirements.txt new file mode 100644 index 0000000000..a550da3e64 --- /dev/null +++ b/scripts/requirements.txt @@ -0,0 +1,2 @@ +PyYAML==3.12 +termcolor==1.1.0 diff --git a/scripts/update_travis_appveyor_yml.py b/scripts/update_travis_appveyor_yml.py new file mode 100755 index 0000000000..07fde1a9bf --- /dev/null +++ b/scripts/update_travis_appveyor_yml.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +import collections +import glob +import yaml +from os import path +from termcolor import colored, cprint +from yaml.constructor import Constructor + +def dump_format(dump, tag, mapping, flow_style=None): + """ + Better output formatting for YAML dictionaries + """ + value = [] + node = yaml.MappingNode(tag, value, flow_style=flow_style) + if dump.alias_key is not None: + dump.represented_objects[dump.alias_key] = node + best_style = True + if hasattr(mapping, 'items'): + mapping = mapping.items() + for item_key, item_value in mapping: + node_key = dump.represent_data(item_key) + node_value = dump.represent_data(item_value) + if not (isinstance(node_key, yaml.ScalarNode) and not node_key.style): + best_style = False + if not (isinstance(node_value, yaml.ScalarNode) and not node_value.style): + best_style = False + value.append((node_key, node_value)) + if flow_style is None: + if dump.default_flow_style is not None: + node.flow_style = dump.default_flow_style + else: + node.flow_style = best_style + return node + + +def add_bool_as_scalar(self, node): + """ + Don't auto-parse boolean values + """ + if node.value == 'true' or node.value == 'false' : + return self.construct_yaml_bool(node) + return self.construct_scalar(node) + +_mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG + +def dict_representer(dumper, data): + return dumper.represent_mapping(_mapping_tag, data.iteritems()) + + +def dict_constructor(loader, node): + return collections.OrderedDict(loader.construct_pairs(node)) + +def update(pattern, updater): + print('\n\n\n') + cprint(pattern, 'magenta') + + for f in glob.glob(path.join(repo_root, "modules", "*", pattern)): + yml = path.join(repo_root, f) + + if not path.exists(yml): + cprint("File does not exist: {}".format(yml), 'red') + continue + + print("Updating {}".format(yml)) + document = yaml.load(open(yml, 'r')) + document = updater(document) + yml_file = open(yml, 'w') + yml_file.write(yaml.safe_dump(document, default_flow_style=False, indent=2)) + yml_file.close() + +# +# Config yaml parser +# + +# Do not reorder keys in yaml file +yaml.add_representer(collections.OrderedDict, dict_representer) +yaml.add_constructor(_mapping_tag, dict_constructor) +# Pretty print dictionaries +yaml.SafeDumper.add_representer(collections.OrderedDict, + lambda dumper, value: dump_format(dumper, u'tag:yaml.org,2002:map', value)) +# Don't parse booleans - treat them as scalars +yaml.Loader.add_constructor(u'tag:yaml.org,2002:bool', add_bool_as_scalar) +yaml.SafeLoader.add_constructor(u'tag:yaml.org,2002:bool', add_bool_as_scalar) + +# +# Main +# + +repo_root = path.dirname(path.dirname(path.abspath(__file__))) + +def transform_yaml_doc(document): + if not 'branches' in document: + document['branches'] = {} + document['branches']['only'] = [ + 'master', '/^release\/.*$/', '/^(.*\/)?ci-.*$/'] + return document + +update(".travis.yml", transform_yaml_doc) +update(".appveyor.yml", transform_yaml_doc) diff --git a/src/DataProtection/DataProtection.sln b/src/DataProtection/DataProtection.sln new file mode 100644 index 0000000000..3e9512f1d9 --- /dev/null +++ b/src/DataProtection/DataProtection.sln @@ -0,0 +1,333 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26814.1 +MinimumVisualStudioVersion = 15.0.26730.03 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5FCB2DA3-5395-47F5-BCEE-E0EA319448EA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{60336AB3-948D-4D15-A5FB-F32A2B91E814}" + ProjectSection(SolutionItems) = preProject + test\CreateTestCert.ps1 = test\CreateTestCert.ps1 + test\Directory.Build.props = test\Directory.Build.props + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{5A3A5DE3-49AD-431C-971D-B01B62D94AE2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E1D86B1B-41D8-43C9-97FD-C2BF65C414E2}" + ProjectSection(SolutionItems) = preProject + .appveyor.yml = .appveyor.yml + .gitattributes = .gitattributes + .gitignore = .gitignore + .travis.yml = .travis.yml + CONTRIBUTING.md = CONTRIBUTING.md + build\dependencies.props = build\dependencies.props + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + korebuild.json = korebuild.json + LICENSE.txt = LICENSE.txt + NuGet.config = NuGet.config + NuGetPackageVerifier.json = NuGetPackageVerifier.json + Provision-AutoGenKeys.ps1 = Provision-AutoGenKeys.ps1 + README.md = README.md + version.props = version.props + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection", "src\Microsoft.AspNetCore.DataProtection\Microsoft.AspNetCore.DataProtection.csproj", "{1E570CD4-6F12-44F4-961E-005EE2002BC2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.Test", "test\Microsoft.AspNetCore.DataProtection.Test\Microsoft.AspNetCore.DataProtection.Test.csproj", "{7A637185-2BA1-437D-9D4C-7CC4F94CF7BF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Cryptography.Internal", "src\Microsoft.AspNetCore.Cryptography.Internal\Microsoft.AspNetCore.Cryptography.Internal.csproj", "{E2779976-A28C-4365-A4BB-4AD854FAF23E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Cryptography.KeyDerivation", "src\Microsoft.AspNetCore.Cryptography.KeyDerivation\Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj", "{421F0383-34B1-402D-807B-A94542513ABA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Cryptography.KeyDerivation.Test", "test\Microsoft.AspNetCore.Cryptography.KeyDerivation.Test\Microsoft.AspNetCore.Cryptography.KeyDerivation.Test.csproj", "{42C97F52-8D56-46BD-A712-4F22BED157A7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Cryptography.Internal.Test", "test\Microsoft.AspNetCore.Cryptography.Internal.Test\Microsoft.AspNetCore.Cryptography.Internal.Test.csproj", "{37053D5F-5B61-47CE-8B72-298CE007FFB0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.Abstractions", "src\Microsoft.AspNetCore.DataProtection.Abstractions\Microsoft.AspNetCore.DataProtection.Abstractions.csproj", "{4B115BDE-B253-46A6-97BF-A8B37B344FF2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.Abstractions.Test", "test\Microsoft.AspNetCore.DataProtection.Abstractions.Test\Microsoft.AspNetCore.DataProtection.Abstractions.Test.csproj", "{FF650A69-DEE4-4B36-9E30-264EE7CFB478}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.SystemWeb", "src\Microsoft.AspNetCore.DataProtection.SystemWeb\Microsoft.AspNetCore.DataProtection.SystemWeb.csproj", "{E3552DEB-4173-43AE-BF69-3C10DFF3BAB6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.Extensions.Test", "test\Microsoft.AspNetCore.DataProtection.Extensions.Test\Microsoft.AspNetCore.DataProtection.Extensions.Test.csproj", "{04AA8E60-A053-4D50-89FE-E76C3DF45200}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.Extensions", "src\Microsoft.AspNetCore.DataProtection.Extensions\Microsoft.AspNetCore.DataProtection.Extensions.csproj", "{BF8681DB-C28B-441F-BD92-0DCFE9537A9F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.AzureStorage", "src\Microsoft.AspNetCore.DataProtection.AzureStorage\Microsoft.AspNetCore.DataProtection.AzureStorage.csproj", "{CC799B57-81E2-4F45-8A32-0D5F49753C3F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzureBlob", "samples\AzureBlob\AzureBlob.csproj", "{B07435B3-CD81-4E3B-88A5-6384821E1C01}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.AzureStorage.Test", "test\Microsoft.AspNetCore.DataProtection.AzureStorage.Test\Microsoft.AspNetCore.DataProtection.AzureStorage.Test.csproj", "{8C41240E-48F8-402F-9388-74CFE27F4D76}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Redis", "samples\Redis\Redis.csproj", "{24AAEC96-DF46-4F61-B2FF-3D5E056685D9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonDISample", "samples\NonDISample\NonDISample.csproj", "{32CF970B-E2F1-4CD9-8DB3-F5715475373A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KeyManagementSample", "samples\KeyManagementSample\KeyManagementSample.csproj", "{6E066F8D-2910-404F-8949-F58125E28495}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomEncryptorSample", "samples\CustomEncryptorSample\CustomEncryptorSample.csproj", "{F4D59BBD-6145-4EE0-BA6E-AD03605BF151}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.AzureKeyVault", "src\Microsoft.AspNetCore.DataProtection.AzureKeyVault\Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj", "{4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzureKeyVault", "samples\AzureKeyVault\AzureKeyVault.csproj", "{295E8539-5450-4764-B3F5-51F968628022}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test", "test\Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test\Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test.csproj", "{C85ED942-8121-453F-8308-9DB730843B63}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test", "test\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test.csproj", "{06728BF2-C5EB-44C7-9F30-14FAA5649E14}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore", "src\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj", "{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCoreSample", "samples\EntityFrameworkCoreSample\EntityFrameworkCoreSample.csproj", "{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.StackExchangeRedis", "src\Microsoft.AspNetCore.DataProtection.StackExchangeRedis\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj", "{57713B23-CCAB-44DB-A08D-55F9D236D05B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test", "test\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test.csproj", "{33BB1B86-64BF-45BB-A334-3E1A4802253C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1E570CD4-6F12-44F4-961E-005EE2002BC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E570CD4-6F12-44F4-961E-005EE2002BC2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E570CD4-6F12-44F4-961E-005EE2002BC2}.Debug|x86.ActiveCfg = Debug|Any CPU + {1E570CD4-6F12-44F4-961E-005EE2002BC2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E570CD4-6F12-44F4-961E-005EE2002BC2}.Release|Any CPU.Build.0 = Release|Any CPU + {1E570CD4-6F12-44F4-961E-005EE2002BC2}.Release|x86.ActiveCfg = Release|Any CPU + {7A637185-2BA1-437D-9D4C-7CC4F94CF7BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A637185-2BA1-437D-9D4C-7CC4F94CF7BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A637185-2BA1-437D-9D4C-7CC4F94CF7BF}.Debug|x86.ActiveCfg = Debug|Any CPU + {7A637185-2BA1-437D-9D4C-7CC4F94CF7BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A637185-2BA1-437D-9D4C-7CC4F94CF7BF}.Release|Any CPU.Build.0 = Release|Any CPU + {7A637185-2BA1-437D-9D4C-7CC4F94CF7BF}.Release|x86.ActiveCfg = Release|Any CPU + {E2779976-A28C-4365-A4BB-4AD854FAF23E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2779976-A28C-4365-A4BB-4AD854FAF23E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2779976-A28C-4365-A4BB-4AD854FAF23E}.Debug|x86.ActiveCfg = Debug|Any CPU + {E2779976-A28C-4365-A4BB-4AD854FAF23E}.Debug|x86.Build.0 = Debug|Any CPU + {E2779976-A28C-4365-A4BB-4AD854FAF23E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2779976-A28C-4365-A4BB-4AD854FAF23E}.Release|Any CPU.Build.0 = Release|Any CPU + {E2779976-A28C-4365-A4BB-4AD854FAF23E}.Release|x86.ActiveCfg = Release|Any CPU + {E2779976-A28C-4365-A4BB-4AD854FAF23E}.Release|x86.Build.0 = Release|Any CPU + {421F0383-34B1-402D-807B-A94542513ABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {421F0383-34B1-402D-807B-A94542513ABA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {421F0383-34B1-402D-807B-A94542513ABA}.Debug|x86.ActiveCfg = Debug|Any CPU + {421F0383-34B1-402D-807B-A94542513ABA}.Debug|x86.Build.0 = Debug|Any CPU + {421F0383-34B1-402D-807B-A94542513ABA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {421F0383-34B1-402D-807B-A94542513ABA}.Release|Any CPU.Build.0 = Release|Any CPU + {421F0383-34B1-402D-807B-A94542513ABA}.Release|x86.ActiveCfg = Release|Any CPU + {421F0383-34B1-402D-807B-A94542513ABA}.Release|x86.Build.0 = Release|Any CPU + {42C97F52-8D56-46BD-A712-4F22BED157A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42C97F52-8D56-46BD-A712-4F22BED157A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42C97F52-8D56-46BD-A712-4F22BED157A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {42C97F52-8D56-46BD-A712-4F22BED157A7}.Debug|x86.Build.0 = Debug|Any CPU + {42C97F52-8D56-46BD-A712-4F22BED157A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42C97F52-8D56-46BD-A712-4F22BED157A7}.Release|Any CPU.Build.0 = Release|Any CPU + {42C97F52-8D56-46BD-A712-4F22BED157A7}.Release|x86.ActiveCfg = Release|Any CPU + {42C97F52-8D56-46BD-A712-4F22BED157A7}.Release|x86.Build.0 = Release|Any CPU + {37053D5F-5B61-47CE-8B72-298CE007FFB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {37053D5F-5B61-47CE-8B72-298CE007FFB0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {37053D5F-5B61-47CE-8B72-298CE007FFB0}.Debug|x86.ActiveCfg = Debug|Any CPU + {37053D5F-5B61-47CE-8B72-298CE007FFB0}.Debug|x86.Build.0 = Debug|Any CPU + {37053D5F-5B61-47CE-8B72-298CE007FFB0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {37053D5F-5B61-47CE-8B72-298CE007FFB0}.Release|Any CPU.Build.0 = Release|Any CPU + {37053D5F-5B61-47CE-8B72-298CE007FFB0}.Release|x86.ActiveCfg = Release|Any CPU + {37053D5F-5B61-47CE-8B72-298CE007FFB0}.Release|x86.Build.0 = Release|Any CPU + {4B115BDE-B253-46A6-97BF-A8B37B344FF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B115BDE-B253-46A6-97BF-A8B37B344FF2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B115BDE-B253-46A6-97BF-A8B37B344FF2}.Debug|x86.ActiveCfg = Debug|Any CPU + {4B115BDE-B253-46A6-97BF-A8B37B344FF2}.Debug|x86.Build.0 = Debug|Any CPU + {4B115BDE-B253-46A6-97BF-A8B37B344FF2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B115BDE-B253-46A6-97BF-A8B37B344FF2}.Release|Any CPU.Build.0 = Release|Any CPU + {4B115BDE-B253-46A6-97BF-A8B37B344FF2}.Release|x86.ActiveCfg = Release|Any CPU + {4B115BDE-B253-46A6-97BF-A8B37B344FF2}.Release|x86.Build.0 = Release|Any CPU + {FF650A69-DEE4-4B36-9E30-264EE7CFB478}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF650A69-DEE4-4B36-9E30-264EE7CFB478}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF650A69-DEE4-4B36-9E30-264EE7CFB478}.Debug|x86.ActiveCfg = Debug|Any CPU + {FF650A69-DEE4-4B36-9E30-264EE7CFB478}.Debug|x86.Build.0 = Debug|Any CPU + {FF650A69-DEE4-4B36-9E30-264EE7CFB478}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF650A69-DEE4-4B36-9E30-264EE7CFB478}.Release|Any CPU.Build.0 = Release|Any CPU + {FF650A69-DEE4-4B36-9E30-264EE7CFB478}.Release|x86.ActiveCfg = Release|Any CPU + {FF650A69-DEE4-4B36-9E30-264EE7CFB478}.Release|x86.Build.0 = Release|Any CPU + {E3552DEB-4173-43AE-BF69-3C10DFF3BAB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3552DEB-4173-43AE-BF69-3C10DFF3BAB6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3552DEB-4173-43AE-BF69-3C10DFF3BAB6}.Debug|x86.ActiveCfg = Debug|Any CPU + {E3552DEB-4173-43AE-BF69-3C10DFF3BAB6}.Debug|x86.Build.0 = Debug|Any CPU + {E3552DEB-4173-43AE-BF69-3C10DFF3BAB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3552DEB-4173-43AE-BF69-3C10DFF3BAB6}.Release|Any CPU.Build.0 = Release|Any CPU + {E3552DEB-4173-43AE-BF69-3C10DFF3BAB6}.Release|x86.ActiveCfg = Release|Any CPU + {E3552DEB-4173-43AE-BF69-3C10DFF3BAB6}.Release|x86.Build.0 = Release|Any CPU + {04AA8E60-A053-4D50-89FE-E76C3DF45200}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04AA8E60-A053-4D50-89FE-E76C3DF45200}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04AA8E60-A053-4D50-89FE-E76C3DF45200}.Debug|x86.ActiveCfg = Debug|Any CPU + {04AA8E60-A053-4D50-89FE-E76C3DF45200}.Debug|x86.Build.0 = Debug|Any CPU + {04AA8E60-A053-4D50-89FE-E76C3DF45200}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04AA8E60-A053-4D50-89FE-E76C3DF45200}.Release|Any CPU.Build.0 = Release|Any CPU + {04AA8E60-A053-4D50-89FE-E76C3DF45200}.Release|x86.ActiveCfg = Release|Any CPU + {04AA8E60-A053-4D50-89FE-E76C3DF45200}.Release|x86.Build.0 = Release|Any CPU + {BF8681DB-C28B-441F-BD92-0DCFE9537A9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF8681DB-C28B-441F-BD92-0DCFE9537A9F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF8681DB-C28B-441F-BD92-0DCFE9537A9F}.Debug|x86.ActiveCfg = Debug|Any CPU + {BF8681DB-C28B-441F-BD92-0DCFE9537A9F}.Debug|x86.Build.0 = Debug|Any CPU + {BF8681DB-C28B-441F-BD92-0DCFE9537A9F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF8681DB-C28B-441F-BD92-0DCFE9537A9F}.Release|Any CPU.Build.0 = Release|Any CPU + {BF8681DB-C28B-441F-BD92-0DCFE9537A9F}.Release|x86.ActiveCfg = Release|Any CPU + {BF8681DB-C28B-441F-BD92-0DCFE9537A9F}.Release|x86.Build.0 = Release|Any CPU + {CC799B57-81E2-4F45-8A32-0D5F49753C3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC799B57-81E2-4F45-8A32-0D5F49753C3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC799B57-81E2-4F45-8A32-0D5F49753C3F}.Debug|x86.ActiveCfg = Debug|Any CPU + {CC799B57-81E2-4F45-8A32-0D5F49753C3F}.Debug|x86.Build.0 = Debug|Any CPU + {CC799B57-81E2-4F45-8A32-0D5F49753C3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC799B57-81E2-4F45-8A32-0D5F49753C3F}.Release|Any CPU.Build.0 = Release|Any CPU + {CC799B57-81E2-4F45-8A32-0D5F49753C3F}.Release|x86.ActiveCfg = Release|Any CPU + {CC799B57-81E2-4F45-8A32-0D5F49753C3F}.Release|x86.Build.0 = Release|Any CPU + {B07435B3-CD81-4E3B-88A5-6384821E1C01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B07435B3-CD81-4E3B-88A5-6384821E1C01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B07435B3-CD81-4E3B-88A5-6384821E1C01}.Debug|x86.ActiveCfg = Debug|Any CPU + {B07435B3-CD81-4E3B-88A5-6384821E1C01}.Debug|x86.Build.0 = Debug|Any CPU + {B07435B3-CD81-4E3B-88A5-6384821E1C01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B07435B3-CD81-4E3B-88A5-6384821E1C01}.Release|Any CPU.Build.0 = Release|Any CPU + {B07435B3-CD81-4E3B-88A5-6384821E1C01}.Release|x86.ActiveCfg = Release|Any CPU + {B07435B3-CD81-4E3B-88A5-6384821E1C01}.Release|x86.Build.0 = Release|Any CPU + {8C41240E-48F8-402F-9388-74CFE27F4D76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C41240E-48F8-402F-9388-74CFE27F4D76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C41240E-48F8-402F-9388-74CFE27F4D76}.Debug|x86.ActiveCfg = Debug|Any CPU + {8C41240E-48F8-402F-9388-74CFE27F4D76}.Debug|x86.Build.0 = Debug|Any CPU + {8C41240E-48F8-402F-9388-74CFE27F4D76}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C41240E-48F8-402F-9388-74CFE27F4D76}.Release|Any CPU.Build.0 = Release|Any CPU + {8C41240E-48F8-402F-9388-74CFE27F4D76}.Release|x86.ActiveCfg = Release|Any CPU + {8C41240E-48F8-402F-9388-74CFE27F4D76}.Release|x86.Build.0 = Release|Any CPU + {24AAEC96-DF46-4F61-B2FF-3D5E056685D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24AAEC96-DF46-4F61-B2FF-3D5E056685D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24AAEC96-DF46-4F61-B2FF-3D5E056685D9}.Debug|x86.ActiveCfg = Debug|Any CPU + {24AAEC96-DF46-4F61-B2FF-3D5E056685D9}.Debug|x86.Build.0 = Debug|Any CPU + {24AAEC96-DF46-4F61-B2FF-3D5E056685D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24AAEC96-DF46-4F61-B2FF-3D5E056685D9}.Release|Any CPU.Build.0 = Release|Any CPU + {24AAEC96-DF46-4F61-B2FF-3D5E056685D9}.Release|x86.ActiveCfg = Release|Any CPU + {24AAEC96-DF46-4F61-B2FF-3D5E056685D9}.Release|x86.Build.0 = Release|Any CPU + {32CF970B-E2F1-4CD9-8DB3-F5715475373A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32CF970B-E2F1-4CD9-8DB3-F5715475373A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32CF970B-E2F1-4CD9-8DB3-F5715475373A}.Debug|x86.ActiveCfg = Debug|Any CPU + {32CF970B-E2F1-4CD9-8DB3-F5715475373A}.Debug|x86.Build.0 = Debug|Any CPU + {32CF970B-E2F1-4CD9-8DB3-F5715475373A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32CF970B-E2F1-4CD9-8DB3-F5715475373A}.Release|Any CPU.Build.0 = Release|Any CPU + {32CF970B-E2F1-4CD9-8DB3-F5715475373A}.Release|x86.ActiveCfg = Release|Any CPU + {32CF970B-E2F1-4CD9-8DB3-F5715475373A}.Release|x86.Build.0 = Release|Any CPU + {6E066F8D-2910-404F-8949-F58125E28495}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6E066F8D-2910-404F-8949-F58125E28495}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6E066F8D-2910-404F-8949-F58125E28495}.Debug|x86.ActiveCfg = Debug|Any CPU + {6E066F8D-2910-404F-8949-F58125E28495}.Debug|x86.Build.0 = Debug|Any CPU + {6E066F8D-2910-404F-8949-F58125E28495}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6E066F8D-2910-404F-8949-F58125E28495}.Release|Any CPU.Build.0 = Release|Any CPU + {6E066F8D-2910-404F-8949-F58125E28495}.Release|x86.ActiveCfg = Release|Any CPU + {6E066F8D-2910-404F-8949-F58125E28495}.Release|x86.Build.0 = Release|Any CPU + {F4D59BBD-6145-4EE0-BA6E-AD03605BF151}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F4D59BBD-6145-4EE0-BA6E-AD03605BF151}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F4D59BBD-6145-4EE0-BA6E-AD03605BF151}.Debug|x86.ActiveCfg = Debug|Any CPU + {F4D59BBD-6145-4EE0-BA6E-AD03605BF151}.Debug|x86.Build.0 = Debug|Any CPU + {F4D59BBD-6145-4EE0-BA6E-AD03605BF151}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F4D59BBD-6145-4EE0-BA6E-AD03605BF151}.Release|Any CPU.Build.0 = Release|Any CPU + {F4D59BBD-6145-4EE0-BA6E-AD03605BF151}.Release|x86.ActiveCfg = Release|Any CPU + {F4D59BBD-6145-4EE0-BA6E-AD03605BF151}.Release|x86.Build.0 = Release|Any CPU + {4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9}.Debug|x86.ActiveCfg = Debug|Any CPU + {4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9}.Debug|x86.Build.0 = Debug|Any CPU + {4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9}.Release|Any CPU.Build.0 = Release|Any CPU + {4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9}.Release|x86.ActiveCfg = Release|Any CPU + {4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9}.Release|x86.Build.0 = Release|Any CPU + {295E8539-5450-4764-B3F5-51F968628022}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {295E8539-5450-4764-B3F5-51F968628022}.Debug|Any CPU.Build.0 = Debug|Any CPU + {295E8539-5450-4764-B3F5-51F968628022}.Debug|x86.ActiveCfg = Debug|Any CPU + {295E8539-5450-4764-B3F5-51F968628022}.Debug|x86.Build.0 = Debug|Any CPU + {295E8539-5450-4764-B3F5-51F968628022}.Release|Any CPU.ActiveCfg = Release|Any CPU + {295E8539-5450-4764-B3F5-51F968628022}.Release|Any CPU.Build.0 = Release|Any CPU + {295E8539-5450-4764-B3F5-51F968628022}.Release|x86.ActiveCfg = Release|Any CPU + {295E8539-5450-4764-B3F5-51F968628022}.Release|x86.Build.0 = Release|Any CPU + {C85ED942-8121-453F-8308-9DB730843B63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C85ED942-8121-453F-8308-9DB730843B63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C85ED942-8121-453F-8308-9DB730843B63}.Debug|x86.ActiveCfg = Debug|Any CPU + {C85ED942-8121-453F-8308-9DB730843B63}.Debug|x86.Build.0 = Debug|Any CPU + {C85ED942-8121-453F-8308-9DB730843B63}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C85ED942-8121-453F-8308-9DB730843B63}.Release|Any CPU.Build.0 = Release|Any CPU + {C85ED942-8121-453F-8308-9DB730843B63}.Release|x86.ActiveCfg = Release|Any CPU + {C85ED942-8121-453F-8308-9DB730843B63}.Release|x86.Build.0 = Release|Any CPU + {06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Debug|x86.ActiveCfg = Debug|Any CPU + {06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Debug|x86.Build.0 = Debug|Any CPU + {06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|Any CPU.ActiveCfg = Release|Any CPU + {06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|Any CPU.Build.0 = Release|Any CPU + {06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|x86.ActiveCfg = Release|Any CPU + {06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|x86.Build.0 = Release|Any CPU + {3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|x86.ActiveCfg = Debug|Any CPU + {3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|x86.Build.0 = Debug|Any CPU + {3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|Any CPU.Build.0 = Release|Any CPU + {3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|x86.ActiveCfg = Release|Any CPU + {3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|x86.Build.0 = Release|Any CPU + {22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Debug|x86.ActiveCfg = Debug|Any CPU + {22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Debug|x86.Build.0 = Debug|Any CPU + {22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Release|Any CPU.Build.0 = Release|Any CPU + {22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Release|x86.ActiveCfg = Release|Any CPU + {22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Release|x86.Build.0 = Release|Any CPU + {57713B23-CCAB-44DB-A08D-55F9D236D05B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {57713B23-CCAB-44DB-A08D-55F9D236D05B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {57713B23-CCAB-44DB-A08D-55F9D236D05B}.Debug|x86.ActiveCfg = Debug|Any CPU + {57713B23-CCAB-44DB-A08D-55F9D236D05B}.Debug|x86.Build.0 = Debug|Any CPU + {57713B23-CCAB-44DB-A08D-55F9D236D05B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {57713B23-CCAB-44DB-A08D-55F9D236D05B}.Release|Any CPU.Build.0 = Release|Any CPU + {57713B23-CCAB-44DB-A08D-55F9D236D05B}.Release|x86.ActiveCfg = Release|Any CPU + {57713B23-CCAB-44DB-A08D-55F9D236D05B}.Release|x86.Build.0 = Release|Any CPU + {33BB1B86-64BF-45BB-A334-3E1A4802253C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {33BB1B86-64BF-45BB-A334-3E1A4802253C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {33BB1B86-64BF-45BB-A334-3E1A4802253C}.Debug|x86.ActiveCfg = Debug|Any CPU + {33BB1B86-64BF-45BB-A334-3E1A4802253C}.Debug|x86.Build.0 = Debug|Any CPU + {33BB1B86-64BF-45BB-A334-3E1A4802253C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33BB1B86-64BF-45BB-A334-3E1A4802253C}.Release|Any CPU.Build.0 = Release|Any CPU + {33BB1B86-64BF-45BB-A334-3E1A4802253C}.Release|x86.ActiveCfg = Release|Any CPU + {33BB1B86-64BF-45BB-A334-3E1A4802253C}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1E570CD4-6F12-44F4-961E-005EE2002BC2} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {7A637185-2BA1-437D-9D4C-7CC4F94CF7BF} = {60336AB3-948D-4D15-A5FB-F32A2B91E814} + {E2779976-A28C-4365-A4BB-4AD854FAF23E} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {421F0383-34B1-402D-807B-A94542513ABA} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {42C97F52-8D56-46BD-A712-4F22BED157A7} = {60336AB3-948D-4D15-A5FB-F32A2B91E814} + {37053D5F-5B61-47CE-8B72-298CE007FFB0} = {60336AB3-948D-4D15-A5FB-F32A2B91E814} + {4B115BDE-B253-46A6-97BF-A8B37B344FF2} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {FF650A69-DEE4-4B36-9E30-264EE7CFB478} = {60336AB3-948D-4D15-A5FB-F32A2B91E814} + {E3552DEB-4173-43AE-BF69-3C10DFF3BAB6} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {04AA8E60-A053-4D50-89FE-E76C3DF45200} = {60336AB3-948D-4D15-A5FB-F32A2B91E814} + {BF8681DB-C28B-441F-BD92-0DCFE9537A9F} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {CC799B57-81E2-4F45-8A32-0D5F49753C3F} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {B07435B3-CD81-4E3B-88A5-6384821E1C01} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2} + {8C41240E-48F8-402F-9388-74CFE27F4D76} = {60336AB3-948D-4D15-A5FB-F32A2B91E814} + {24AAEC96-DF46-4F61-B2FF-3D5E056685D9} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2} + {32CF970B-E2F1-4CD9-8DB3-F5715475373A} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2} + {6E066F8D-2910-404F-8949-F58125E28495} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2} + {F4D59BBD-6145-4EE0-BA6E-AD03605BF151} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2} + {4E76B2A8-9DC3-46E6-B5FC-097A1D1DFBE9} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {295E8539-5450-4764-B3F5-51F968628022} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2} + {C85ED942-8121-453F-8308-9DB730843B63} = {60336AB3-948D-4D15-A5FB-F32A2B91E814} + {06728BF2-C5EB-44C7-9F30-14FAA5649E14} = {60336AB3-948D-4D15-A5FB-F32A2B91E814} + {3E4CA7FE-741B-4C78-A775-220E0E3C1B03} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {22BA4EAB-641E-42B2-BB37-9C3BCFD99F76} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2} + {57713B23-CCAB-44DB-A08D-55F9D236D05B} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA} + {33BB1B86-64BF-45BB-A334-3E1A4802253C} = {60336AB3-948D-4D15-A5FB-F32A2B91E814} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DD305D75-BD1B-43AE-BF04-869DA6A0858F} + EndGlobalSection +EndGlobal diff --git a/src/DataProtection/Directory.Build.props b/src/DataProtection/Directory.Build.props new file mode 100644 index 0000000000..deb7bb4ee6 --- /dev/null +++ b/src/DataProtection/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/DataProtection/NuGetPackageVerifier.json b/src/DataProtection/NuGetPackageVerifier.json new file mode 100644 index 0000000000..22ef3c09c0 --- /dev/null +++ b/src/DataProtection/NuGetPackageVerifier.json @@ -0,0 +1,7 @@ +{ + "Default": { + "rules": [ + "DefaultCompositeRule" + ] + } +} diff --git a/src/DataProtection/Provision-AutoGenKeys.ps1 b/src/DataProtection/Provision-AutoGenKeys.ps1 new file mode 100644 index 0000000000..9be7e1601d --- /dev/null +++ b/src/DataProtection/Provision-AutoGenKeys.ps1 @@ -0,0 +1,117 @@ +param ( + [Parameter(Mandatory = $True)] + [string] $appPoolName + ) + +# Provisions the HKLM registry so that the specified user account can persist auto-generated machine keys. +function Provision-AutoGenKeys { + [CmdletBinding()] + param ( + [ValidateSet("2.0", "4.0")] + [Parameter(Mandatory = $True)] + [string] $frameworkVersion, + [ValidateSet("32", "64")] + [Parameter(Mandatory = $True)] + [string] $architecture, + [Parameter(Mandatory = $True)] + [string] $sid + ) + process { + # We require administrative permissions to continue. + if (-Not (new-object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) { + Write-Error "This cmdlet requires Administrator permissions." + return + } + # Open HKLM with an appropriate view into the registry + if ($architecture -eq "32") { + $regView = [Microsoft.Win32.RegistryView]::Registry32; + } else { + $regView = [Microsoft.Win32.RegistryView]::Registry64; + } + $baseRegKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $regView) + # Open ASP.NET base key + if ($frameworkVersion -eq "2.0") { + $expandedVersion = "2.0.50727.0" + } else { + $expandedVersion = "4.0.30319.0" + } + $softwareMicrosoftKey = $baseRegKey.OpenSubKey("SOFTWARE\Microsoft\", $True); + + $aspNetKey = $softwareMicrosoftKey.OpenSubKey("ASP.NET", $True); + if ($aspNetKey -eq $null) + { + $aspNetKey = $softwareMicrosoftKey.CreateSubKey("ASP.NET") + } + + $aspNetBaseKey = $aspNetKey.OpenSubKey("$expandedVersion", $True); + if ($aspNetBaseKey -eq $null) + { + $aspNetBaseKey = $aspNetKey.CreateSubKey("$expandedVersion") + } + + # Create AutoGenKeys subkey if it doesn't already exist + $autoGenBaseKey = $aspNetBaseKey.OpenSubKey("AutoGenKeys", $True) + if ($autoGenBaseKey -eq $null) { + $autoGenBaseKey = $aspNetBaseKey.CreateSubKey("AutoGenKeys") + } + # SYSTEM, ADMINISTRATORS, and the target SID get full access + $regSec = New-Object System.Security.AccessControl.RegistrySecurity + $regSec.SetSecurityDescriptorSddlForm("D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GA;;;$sid)") + $userAutoGenKey = $autoGenBaseKey.OpenSubKey($sid, $True) + if ($userAutoGenKey -eq $null) { + # Subkey didn't exist; create and ACL appropriately + $userAutoGenKey = $autoGenBaseKey.CreateSubKey($sid, [Microsoft.Win32.RegistryKeyPermissionCheck]::Default, $regSec) + } else { + # Subkey existed; make sure ACLs are correct + $userAutoGenKey.SetAccessControl($regSec) + } + } +} + +$ErrorActionPreference = "Stop" +if (Get-Command Get-IISAppPool -errorAction SilentlyContinue) +{ + $processModel = (Get-IISAppPool $appPoolName).processModel +} +else +{ + Import-Module WebAdministration + $processModel = Get-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name "processModel" +} + +$identityType = $processModel.identityType +Write-Output "Pool process model: '$identityType'" + +Switch ($identityType) +{ + "LocalService" { + $userName = "LocalService"; + } + "LocalSystem" { + $userName = "System"; + } + "NetworkService" { + $userName = "NetworkService"; + } + "ApplicationPoolIdentity" { + $userName = "IIS APPPOOL\$appPoolName"; + } + "SpecificUser" { + $userName = $processModel.userName; + } +} +Write-Output "Pool user name: '$userName'" + +Try +{ + $poolSid = (New-Object System.Security.Principal.NTAccount($userName)).Translate([System.Security.Principal.SecurityIdentifier]).Value +} +Catch [System.Security.Principal.IdentityNotMappedException] +{ + Write-Error "Application pool '$appPoolName' account cannot be resolved." +} + +Write-Output "Pool SID: '$poolSid'" + +Provision-AutoGenKeys "4.0" "32" $poolSid +Provision-AutoGenKeys "4.0" "64" $poolSid diff --git a/src/DataProtection/README.md b/src/DataProtection/README.md new file mode 100644 index 0000000000..cd58074d9e --- /dev/null +++ b/src/DataProtection/README.md @@ -0,0 +1,8 @@ +DataProtection +============== + +Data Protection APIs for protecting and unprotecting data. You can find documentation for Data Protection in the [ASP.NET Core Documentation](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/). + +## Community Maintained Data Protection Providers & Projects + + - [ASP.NET Core DataProtection for Service Fabric](https://github.com/MedAnd/AspNetCore.DataProtection.ServiceFabric) diff --git a/src/DataProtection/build.cmd b/src/DataProtection/build.cmd new file mode 100644 index 0000000000..f4169ea5e4 --- /dev/null +++ b/src/DataProtection/build.cmd @@ -0,0 +1,3 @@ +@ECHO OFF +SET RepoRoot="%~dp0..\.." +%RepoRoot%\build.cmd -LockFile %RepoRoot%\korebuild-lock.txt -Path %~dp0 %* diff --git a/src/DataProtection/build.sh b/src/DataProtection/build.sh new file mode 100755 index 0000000000..d5bb0cf631 --- /dev/null +++ b/src/DataProtection/build.sh @@ -0,0 +1,7 @@ +#!/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" "$@" diff --git a/src/DataProtection/build/repo.props b/src/DataProtection/build/repo.props new file mode 100644 index 0000000000..3fa98a9b36 --- /dev/null +++ b/src/DataProtection/build/repo.props @@ -0,0 +1,10 @@ + + + + + true + + + + + diff --git a/src/DataProtection/dependencies.props b/src/DataProtection/dependencies.props new file mode 100644 index 0000000000..6633853e15 --- /dev/null +++ b/src/DataProtection/dependencies.props @@ -0,0 +1,33 @@ + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + + 2.2.0-preview2-20181004.6 + 3.0.0-alpha1-10584 + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + $(LastGoodAspBuildVersion) + + + + + + diff --git a/src/DataProtection/samples/AzureBlob/AzureBlob.csproj b/src/DataProtection/samples/AzureBlob/AzureBlob.csproj new file mode 100644 index 0000000000..72bce10880 --- /dev/null +++ b/src/DataProtection/samples/AzureBlob/AzureBlob.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp3.0 + exe + + + + + + + + + + + + + + diff --git a/src/DataProtection/samples/AzureBlob/Program.cs b/src/DataProtection/samples/AzureBlob/Program.cs new file mode 100644 index 0000000000..cce8604648 --- /dev/null +++ b/src/DataProtection/samples/AzureBlob/Program.cs @@ -0,0 +1,43 @@ +// 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 Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.WindowsAzure.Storage; +using LogLevel = Microsoft.Extensions.Logging.LogLevel; + +namespace AzureBlob +{ + public class Program + { + public static void Main(string[] args) + { + var storageAccount = CloudStorageAccount.DevelopmentStorageAccount; + var client = storageAccount.CreateCloudBlobClient(); + var container = client.GetContainerReference("key-container"); + + // The container must exist before calling the DataProtection APIs. + // The specific file within the container does not have to exist, + // as it will be created on-demand. + + container.CreateIfNotExistsAsync().GetAwaiter().GetResult(); + + // Configure + using (var services = new ServiceCollection() + .AddLogging(o => o.AddConsole().SetMinimumLevel(LogLevel.Debug)) + .AddDataProtection() + .PersistKeysToAzureBlobStorage(container, "keys.xml") + .Services + .BuildServiceProvider()) + { + // Run a sample payload + + var protector = services.GetDataProtector("sample-purpose"); + var protectedData = protector.Protect("Hello world!"); + Console.WriteLine(protectedData); + } + } + } +} diff --git a/src/DataProtection/samples/AzureKeyVault/AzureKeyVault.csproj b/src/DataProtection/samples/AzureKeyVault/AzureKeyVault.csproj new file mode 100644 index 0000000000..faa7d75be0 --- /dev/null +++ b/src/DataProtection/samples/AzureKeyVault/AzureKeyVault.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp3.0 + exe + + + + + + + + + + + + + + + diff --git a/src/DataProtection/samples/AzureKeyVault/Program.cs b/src/DataProtection/samples/AzureKeyVault/Program.cs new file mode 100644 index 0000000000..7d6299f3e5 --- /dev/null +++ b/src/DataProtection/samples/AzureKeyVault/Program.cs @@ -0,0 +1,44 @@ +// 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.IO; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main(string[] args) + { + var builder = new ConfigurationBuilder(); + builder.SetBasePath(Directory.GetCurrentDirectory()); + builder.AddJsonFile("settings.json"); + var config = builder.Build(); + + var store = new X509Store(StoreLocation.CurrentUser); + store.Open(OpenFlags.ReadOnly); + var cert = store.Certificates.Find(X509FindType.FindByThumbprint, config["CertificateThumbprint"], false); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(); + serviceCollection.AddDataProtection() + .PersistKeysToFileSystem(new DirectoryInfo(".")) + .ProtectKeysWithAzureKeyVault(config["KeyId"], config["ClientId"], cert.OfType().Single()); + + var serviceProvider = serviceCollection.BuildServiceProvider(); + + var loggerFactory = serviceProvider.GetService(); + loggerFactory.AddConsole(); + + var protector = serviceProvider.GetDataProtector("Test"); + + Console.WriteLine(protector.Protect("Hello world")); + } + } +} diff --git a/src/DataProtection/samples/AzureKeyVault/settings.json b/src/DataProtection/samples/AzureKeyVault/settings.json new file mode 100644 index 0000000000..ef7d4d81b8 --- /dev/null +++ b/src/DataProtection/samples/AzureKeyVault/settings.json @@ -0,0 +1,5 @@ +{ + "CertificateThumbprint": "", + "KeyId": "", + "ClientId": "" +} \ No newline at end of file diff --git a/src/DataProtection/samples/CustomEncryptorSample/CustomBuilderExtensions.cs b/src/DataProtection/samples/CustomEncryptorSample/CustomBuilderExtensions.cs new file mode 100644 index 0000000000..faa99a4a5d --- /dev/null +++ b/src/DataProtection/samples/CustomEncryptorSample/CustomBuilderExtensions.cs @@ -0,0 +1,31 @@ +// 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 Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace CustomEncryptorSample +{ + public static class CustomBuilderExtensions + { + public static IDataProtectionBuilder UseXmlEncryptor( + this IDataProtectionBuilder builder, + Func factory) + { + builder.Services.AddSingleton>(serviceProvider => + { + var instance = factory(serviceProvider); + return new ConfigureOptions(options => + { + options.XmlEncryptor = instance; + }); + }); + + return builder; + } + } +} diff --git a/src/DataProtection/samples/CustomEncryptorSample/CustomEncryptorSample.csproj b/src/DataProtection/samples/CustomEncryptorSample/CustomEncryptorSample.csproj new file mode 100644 index 0000000000..f55e580fed --- /dev/null +++ b/src/DataProtection/samples/CustomEncryptorSample/CustomEncryptorSample.csproj @@ -0,0 +1,18 @@ + + + + net461;netcoreapp3.0 + exe + + + + + + + + + + + + + diff --git a/src/DataProtection/samples/CustomEncryptorSample/CustomXmlDecryptor.cs b/src/DataProtection/samples/CustomEncryptorSample/CustomXmlDecryptor.cs new file mode 100644 index 0000000000..a8925f12f6 --- /dev/null +++ b/src/DataProtection/samples/CustomEncryptorSample/CustomXmlDecryptor.cs @@ -0,0 +1,32 @@ +// 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 System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace CustomEncryptorSample +{ + public class CustomXmlDecryptor : IXmlDecryptor + { + private readonly ILogger _logger; + + public CustomXmlDecryptor(IServiceProvider services) + { + _logger = services.GetRequiredService().CreateLogger(); + } + + public XElement Decrypt(XElement encryptedElement) + { + if (encryptedElement == null) + { + throw new ArgumentNullException(nameof(encryptedElement)); + } + + return new XElement(encryptedElement.Elements().Single()); + } + } +} diff --git a/src/DataProtection/samples/CustomEncryptorSample/CustomXmlEncryptor.cs b/src/DataProtection/samples/CustomEncryptorSample/CustomXmlEncryptor.cs new file mode 100644 index 0000000000..f6653f776a --- /dev/null +++ b/src/DataProtection/samples/CustomEncryptorSample/CustomXmlEncryptor.cs @@ -0,0 +1,38 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace CustomEncryptorSample +{ + public class CustomXmlEncryptor : IXmlEncryptor + { + private readonly ILogger _logger; + + public CustomXmlEncryptor(IServiceProvider services) + { + _logger = services.GetRequiredService().CreateLogger(); + } + + public EncryptedXmlInfo Encrypt(XElement plaintextElement) + { + if (plaintextElement == null) + { + throw new ArgumentNullException(nameof(plaintextElement)); + } + + _logger.LogInformation("Not encrypting key"); + + var newElement = new XElement("unencryptedKey", + new XComment(" This key is not encrypted. "), + new XElement(plaintextElement)); + var encryptedTextElement = new EncryptedXmlInfo(newElement, typeof(CustomXmlDecryptor)); + + return encryptedTextElement; + } + } +} diff --git a/src/DataProtection/samples/CustomEncryptorSample/Program.cs b/src/DataProtection/samples/CustomEncryptorSample/Program.cs new file mode 100644 index 0000000000..9079aeee3f --- /dev/null +++ b/src/DataProtection/samples/CustomEncryptorSample/Program.cs @@ -0,0 +1,36 @@ +// 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.IO; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace CustomEncryptorSample +{ + public class Program + { + public static void Main(string[] args) + { + var keysFolder = Path.Combine(Directory.GetCurrentDirectory(), "temp-keys"); + using (var services = new ServiceCollection() + .AddLogging(o => o.AddConsole().SetMinimumLevel(LogLevel.Debug)) + .AddDataProtection() + .PersistKeysToFileSystem(new DirectoryInfo(keysFolder)) + .UseXmlEncryptor(s => new CustomXmlEncryptor(s)) + .Services.BuildServiceProvider()) + { + var protector = services.GetDataProtector("SamplePurpose"); + + // protect the payload + var protectedPayload = protector.Protect("Hello World!"); + Console.WriteLine($"Protect returned: {protectedPayload}"); + + // unprotect the payload + var unprotectedPayload = protector.Unprotect(protectedPayload); + Console.WriteLine($"Unprotect returned: {unprotectedPayload}"); + } + } + } +} diff --git a/src/DataProtection/samples/EntityFrameworkCoreSample/EntityFrameworkCoreSample.csproj b/src/DataProtection/samples/EntityFrameworkCoreSample/EntityFrameworkCoreSample.csproj new file mode 100644 index 0000000000..4b8bf7da45 --- /dev/null +++ b/src/DataProtection/samples/EntityFrameworkCoreSample/EntityFrameworkCoreSample.csproj @@ -0,0 +1,18 @@ + + + + exe + net461;netcoreapp3.0 + + + + + + + + + + + + + diff --git a/src/DataProtection/samples/EntityFrameworkCoreSample/Program.cs b/src/DataProtection/samples/EntityFrameworkCoreSample/Program.cs new file mode 100644 index 0000000000..d4e978a7b8 --- /dev/null +++ b/src/DataProtection/samples/EntityFrameworkCoreSample/Program.cs @@ -0,0 +1,48 @@ +// 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 Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace EntityFrameworkCoreSample +{ + class Program + { + static void Main(string[] args) + { + // Configure + var services = new ServiceCollection() + .AddLogging(o => o.AddConsole().SetMinimumLevel(LogLevel.Debug)) + .AddDbContext(o => + { + o.UseInMemoryDatabase("DataProtection_EntityFrameworkCore"); + o.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); + o.EnableSensitiveDataLogging(); + }) + .AddDataProtection() + .PersistKeysToDbContext() + .SetDefaultKeyLifetime(TimeSpan.FromDays(7)) + .Services + .BuildServiceProvider(validateScopes: true); + + using(services) + { + // Run a sample payload + var protector = services.GetDataProtector("sample-purpose"); + var protectedData = protector.Protect("Hello world!"); + Console.WriteLine(protectedData); + } + } + } + + class DataProtectionKeyContext : DbContext, IDataProtectionKeyContext + { + public DataProtectionKeyContext(DbContextOptions options) : base(options) { } + + public DbSet DataProtectionKeys { get; set; } + } +} diff --git a/src/DataProtection/samples/KeyManagementSample/KeyManagementSample.csproj b/src/DataProtection/samples/KeyManagementSample/KeyManagementSample.csproj new file mode 100644 index 0000000000..d97d58f988 --- /dev/null +++ b/src/DataProtection/samples/KeyManagementSample/KeyManagementSample.csproj @@ -0,0 +1,13 @@ + + + + net461;netcoreapp3.0 + exe + + + + + + + + diff --git a/src/DataProtection/samples/KeyManagementSample/Program.cs b/src/DataProtection/samples/KeyManagementSample/Program.cs new file mode 100644 index 0000000000..be128aa11c --- /dev/null +++ b/src/DataProtection/samples/KeyManagementSample/Program.cs @@ -0,0 +1,66 @@ +// 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.IO; +using System.Runtime.InteropServices; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.DependencyInjection; + +namespace KeyManagementSample +{ + public class Program + { + public static void Main(string[] args) + { + var keysFolder = Path.Combine(Directory.GetCurrentDirectory(), "temp-keys"); + var serviceCollection = new ServiceCollection(); + var builder = serviceCollection + .AddDataProtection() + // point at a specific folder and use DPAPI to encrypt keys + .PersistKeysToFileSystem(new DirectoryInfo(keysFolder)); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + builder.ProtectKeysWithDpapi(); + } + + using (var services = serviceCollection.BuildServiceProvider()) + { + // perform a protect operation to force the system to put at least + // one key in the key ring + services.GetDataProtector("Sample.KeyManager.v1").Protect("payload"); + Console.WriteLine("Performed a protect operation."); + + // get a reference to the key manager + var keyManager = services.GetService(); + + // list all keys in the key ring + var allKeys = keyManager.GetAllKeys(); + Console.WriteLine($"The key ring contains {allKeys.Count} key(s)."); + foreach (var key in allKeys) + { + Console.WriteLine($"Key {key.KeyId:B}: Created = {key.CreationDate:u}, IsRevoked = {key.IsRevoked}"); + } + + // revoke all keys in the key ring + keyManager.RevokeAllKeys(DateTimeOffset.Now, reason: "Revocation reason here."); + Console.WriteLine("Revoked all existing keys."); + + // add a new key to the key ring with immediate activation and a 1-month expiration + keyManager.CreateNewKey( + activationDate: DateTimeOffset.Now, + expirationDate: DateTimeOffset.Now.AddMonths(1)); + Console.WriteLine("Added a new key."); + + // list all keys in the key ring + allKeys = keyManager.GetAllKeys(); + Console.WriteLine($"The key ring contains {allKeys.Count} key(s)."); + foreach (var key in allKeys) + { + Console.WriteLine($"Key {key.KeyId:B}: Created = {key.CreationDate:u}, IsRevoked = {key.IsRevoked}"); + } + } + } + } +} diff --git a/src/DataProtection/samples/NonDISample/NonDISample.csproj b/src/DataProtection/samples/NonDISample/NonDISample.csproj new file mode 100644 index 0000000000..6371351b01 --- /dev/null +++ b/src/DataProtection/samples/NonDISample/NonDISample.csproj @@ -0,0 +1,12 @@ + + + + net461;netcoreapp3.0 + exe + + + + + + + diff --git a/src/DataProtection/samples/NonDISample/Program.cs b/src/DataProtection/samples/NonDISample/Program.cs new file mode 100644 index 0000000000..f9ccd92603 --- /dev/null +++ b/src/DataProtection/samples/NonDISample/Program.cs @@ -0,0 +1,41 @@ +// 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.IO; +using System.Runtime.InteropServices; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; + +namespace NonDISample +{ + public class Program + { + public static void Main(string[] args) + { + var keysFolder = Path.Combine(Directory.GetCurrentDirectory(), "temp-keys"); + + // instantiate the data protection system at this folder + var dataProtectionProvider = DataProtectionProvider.Create( + new DirectoryInfo(keysFolder), + configuration => + { + configuration.SetApplicationName("my app name"); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + configuration.ProtectKeysWithDpapi(); + } + }); + + var protector = dataProtectionProvider.CreateProtector("Program.No-DI"); + + // protect the payload + var protectedPayload = protector.Protect("Hello World!"); + Console.WriteLine($"Protect returned: {protectedPayload}"); + + // unprotect the payload + var unprotectedPayload = protector.Unprotect(protectedPayload); + Console.WriteLine($"Unprotect returned: {unprotectedPayload}"); + } + } +} diff --git a/src/DataProtection/samples/Redis/Program.cs b/src/DataProtection/samples/Redis/Program.cs new file mode 100644 index 0000000000..57d910ae8f --- /dev/null +++ b/src/DataProtection/samples/Redis/Program.cs @@ -0,0 +1,35 @@ +// 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 Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection.StackExchangeRedis; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using StackExchange.Redis; + +namespace RedisSample +{ + public class Program + { + public static void Main(string[] args) + { + // Connect + var redis = ConnectionMultiplexer.Connect("localhost:6379"); + + // Configure + using (var services = new ServiceCollection() + .AddLogging(o => o.AddConsole().SetMinimumLevel(LogLevel.Debug)) + .AddDataProtection() + .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys") + .Services + .BuildServiceProvider()) + { + // Run a sample payload + var protector = services.GetDataProtector("sample-purpose"); + var protectedData = protector.Protect("Hello world!"); + Console.WriteLine(protectedData); + } + } + } +} diff --git a/src/DataProtection/samples/Redis/Redis.csproj b/src/DataProtection/samples/Redis/Redis.csproj new file mode 100644 index 0000000000..7b1433e9fe --- /dev/null +++ b/src/DataProtection/samples/Redis/Redis.csproj @@ -0,0 +1,18 @@ + + + + net461;netcoreapp3.0 + exe + + + + + + + + + + + + + diff --git a/src/DataProtection/shared/EncodingUtil.cs b/src/DataProtection/shared/EncodingUtil.cs new file mode 100644 index 0000000000..67b99eac3b --- /dev/null +++ b/src/DataProtection/shared/EncodingUtil.cs @@ -0,0 +1,14 @@ +// 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.Text; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal static class EncodingUtil + { + // UTF8 encoding that fails on invalid chars + public static readonly UTF8Encoding SecureUtf8Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); + } +} diff --git a/src/DataProtection/shared/ExceptionExtensions.cs b/src/DataProtection/shared/ExceptionExtensions.cs new file mode 100644 index 0000000000..f441935d13 --- /dev/null +++ b/src/DataProtection/shared/ExceptionExtensions.cs @@ -0,0 +1,20 @@ +// 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.Security.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal static class ExceptionExtensions + { + /// + /// Determines whether an exception must be homogenized by being wrapped inside a + /// CryptographicException before being rethrown. + /// + public static bool RequiresHomogenization(this Exception ex) + { + return !(ex is CryptographicException); + } + } +} diff --git a/src/DataProtection/src/Directory.Build.props b/src/DataProtection/src/Directory.Build.props new file mode 100644 index 0000000000..4b89a431e7 --- /dev/null +++ b/src/DataProtection/src/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.cs new file mode 100644 index 0000000000..0c074b8280 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.cs @@ -0,0 +1,38 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/cc562981(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO + { + public uint cbSize; + public uint dwInfoVersion; + public byte* pbNonce; + public uint cbNonce; + public byte* pbAuthData; + public uint cbAuthData; + public byte* pbTag; + public uint cbTag; + public byte* pbMacContext; + public uint cbMacContext; + public uint cbAAD; + public ulong cbData; + public uint dwFlags; + + // corresponds to the BCRYPT_INIT_AUTH_MODE_INFO macro in bcrypt.h + public static void Init(out BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO info) + { + const uint BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION = 1; + info = new BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO + { + cbSize = (uint)sizeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO), + dwInfoVersion = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION + }; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCRYPT_KEY_LENGTHS_STRUCT.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCRYPT_KEY_LENGTHS_STRUCT.cs new file mode 100644 index 0000000000..0d4139018f --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCRYPT_KEY_LENGTHS_STRUCT.cs @@ -0,0 +1,46 @@ +// 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.Runtime.InteropServices; +using Microsoft.AspNetCore.Cryptography.Internal; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375525(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + internal struct BCRYPT_KEY_LENGTHS_STRUCT + { + // MSDN says these fields represent the key length in bytes. + // It's wrong: these key lengths are all actually in bits. + internal uint dwMinLength; + internal uint dwMaxLength; + internal uint dwIncrement; + + public void EnsureValidKeyLength(uint keyLengthInBits) + { + if (!IsValidKeyLength(keyLengthInBits)) + { + string message = Resources.FormatBCRYPT_KEY_LENGTHS_STRUCT_InvalidKeyLength(keyLengthInBits, dwMinLength, dwMaxLength, dwIncrement); + throw new ArgumentOutOfRangeException(nameof(keyLengthInBits), message); + } + CryptoUtil.Assert(keyLengthInBits % 8 == 0, "keyLengthInBits % 8 == 0"); + } + + private bool IsValidKeyLength(uint keyLengthInBits) + { + // If the step size is zero, then the key length must be exactly the min or the max. Otherwise, + // key length must be between min and max (inclusive) and a whole number of increments away from min. + if (dwIncrement == 0) + { + return (keyLengthInBits == dwMinLength || keyLengthInBits == dwMaxLength); + } + else + { + return (dwMinLength <= keyLengthInBits) + && (keyLengthInBits <= dwMaxLength) + && ((keyLengthInBits - dwMinLength) % dwIncrement == 0); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptBuffer.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptBuffer.cs new file mode 100644 index 0000000000..c091859729 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptBuffer.cs @@ -0,0 +1,17 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375368(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + internal struct BCryptBuffer + { + public uint cbBuffer; // Length of buffer, in bytes + public BCryptKeyDerivationBufferType BufferType; // Buffer type + public IntPtr pvBuffer; // Pointer to buffer + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptBufferDesc.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptBufferDesc.cs new file mode 100644 index 0000000000..8fd699643e --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptBufferDesc.cs @@ -0,0 +1,26 @@ +// 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.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375370(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct BCryptBufferDesc + { + private const int BCRYPTBUFFER_VERSION = 0; + + public uint ulVersion; // Version number + public uint cBuffers; // Number of buffers + public BCryptBuffer* pBuffers; // Pointer to array of buffers + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Initialize(ref BCryptBufferDesc bufferDesc) + { + bufferDesc.ulVersion = BCRYPTBUFFER_VERSION; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptEncryptFlags.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptEncryptFlags.cs new file mode 100644 index 0000000000..81ae0105cc --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptEncryptFlags.cs @@ -0,0 +1,13 @@ +// 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; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + [Flags] + internal enum BCryptEncryptFlags + { + BCRYPT_BLOCK_PADDING = 0x00000001, + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptGenRandomFlags.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptGenRandomFlags.cs new file mode 100644 index 0000000000..ed20fec309 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptGenRandomFlags.cs @@ -0,0 +1,15 @@ +// 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; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + // from bcrypt.h + [Flags] + internal enum BCryptGenRandomFlags + { + BCRYPT_RNG_USE_ENTROPY_IN_BUFFER = 0x00000001, + BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002, + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptKeyDerivationBufferType.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptKeyDerivationBufferType.cs new file mode 100644 index 0000000000..a68569e799 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptKeyDerivationBufferType.cs @@ -0,0 +1,29 @@ +// 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; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + // from bcrypt.h + internal enum BCryptKeyDerivationBufferType + { + KDF_HASH_ALGORITHM = 0x0, + KDF_SECRET_PREPEND = 0x1, + KDF_SECRET_APPEND = 0x2, + KDF_HMAC_KEY = 0x3, + KDF_TLS_PRF_LABEL = 0x4, + KDF_TLS_PRF_SEED = 0x5, + KDF_SECRET_HANDLE = 0x6, + KDF_TLS_PRF_PROTOCOL = 0x7, + KDF_ALGORITHMID = 0x8, + KDF_PARTYUINFO = 0x9, + KDF_PARTYVINFO = 0xA, + KDF_SUPPPUBINFO = 0xB, + KDF_SUPPPRIVINFO = 0xC, + KDF_LABEL = 0xD, + KDF_CONTEXT = 0xE, + KDF_SALT = 0xF, + KDF_ITERATION_COUNT = 0x10, + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptUtil.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptUtil.cs new file mode 100644 index 0000000000..86c86c64a8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/BCryptUtil.cs @@ -0,0 +1,29 @@ +// 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; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + /// + /// Wraps utility BCRYPT APIs that don't work directly with handles. + /// + internal unsafe static class BCryptUtil + { + /// + /// Fills a buffer with cryptographically secure random data. + /// + public static void GenRandom(byte* pbBuffer, uint cbBuffer) + { + if (cbBuffer != 0) + { + int ntstatus = UnsafeNativeMethods.BCryptGenRandom( + hAlgorithm: IntPtr.Zero, + pbBuffer: pbBuffer, + cbBuffer: cbBuffer, + dwFlags: BCryptGenRandomFlags.BCRYPT_USE_SYSTEM_PREFERRED_RNG); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/CachedAlgorithmHandles.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/CachedAlgorithmHandles.cs new file mode 100644 index 0000000000..48e63685fd --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/CachedAlgorithmHandles.cs @@ -0,0 +1,93 @@ +// 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 Microsoft.AspNetCore.Cryptography.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + /// + /// Provides cached CNG algorithm provider instances, as calling BCryptOpenAlgorithmProvider is expensive. + /// Callers should use caution never to dispose of the algorithm provider instances returned by this type. + /// + internal static class CachedAlgorithmHandles + { + private static CachedAlgorithmInfo _aesCbc = new CachedAlgorithmInfo(() => GetAesAlgorithm(chainingMode: Constants.BCRYPT_CHAIN_MODE_CBC)); + private static CachedAlgorithmInfo _aesGcm = new CachedAlgorithmInfo(() => GetAesAlgorithm(chainingMode: Constants.BCRYPT_CHAIN_MODE_GCM)); + private static CachedAlgorithmInfo _hmacSha1 = new CachedAlgorithmInfo(() => GetHmacAlgorithm(algorithm: Constants.BCRYPT_SHA1_ALGORITHM)); + private static CachedAlgorithmInfo _hmacSha256 = new CachedAlgorithmInfo(() => GetHmacAlgorithm(algorithm: Constants.BCRYPT_SHA256_ALGORITHM)); + private static CachedAlgorithmInfo _hmacSha512 = new CachedAlgorithmInfo(() => GetHmacAlgorithm(algorithm: Constants.BCRYPT_SHA512_ALGORITHM)); + private static CachedAlgorithmInfo _pbkdf2 = new CachedAlgorithmInfo(GetPbkdf2Algorithm); + private static CachedAlgorithmInfo _sha1 = new CachedAlgorithmInfo(() => GetHashAlgorithm(algorithm: Constants.BCRYPT_SHA1_ALGORITHM)); + private static CachedAlgorithmInfo _sha256 = new CachedAlgorithmInfo(() => GetHashAlgorithm(algorithm: Constants.BCRYPT_SHA256_ALGORITHM)); + private static CachedAlgorithmInfo _sha512 = new CachedAlgorithmInfo(() => GetHashAlgorithm(algorithm: Constants.BCRYPT_SHA512_ALGORITHM)); + private static CachedAlgorithmInfo _sp800_108_ctr_hmac = new CachedAlgorithmInfo(GetSP800_108_CTR_HMACAlgorithm); + + public static BCryptAlgorithmHandle AES_CBC => CachedAlgorithmInfo.GetAlgorithmHandle(ref _aesCbc); + + public static BCryptAlgorithmHandle AES_GCM => CachedAlgorithmInfo.GetAlgorithmHandle(ref _aesGcm); + + public static BCryptAlgorithmHandle HMAC_SHA1 => CachedAlgorithmInfo.GetAlgorithmHandle(ref _hmacSha1); + + public static BCryptAlgorithmHandle HMAC_SHA256 => CachedAlgorithmInfo.GetAlgorithmHandle(ref _hmacSha256); + + public static BCryptAlgorithmHandle HMAC_SHA512 => CachedAlgorithmInfo.GetAlgorithmHandle(ref _hmacSha512); + + // Only available on Win8+. + public static BCryptAlgorithmHandle PBKDF2 => CachedAlgorithmInfo.GetAlgorithmHandle(ref _pbkdf2); + + public static BCryptAlgorithmHandle SHA1 => CachedAlgorithmInfo.GetAlgorithmHandle(ref _sha1); + + public static BCryptAlgorithmHandle SHA256 => CachedAlgorithmInfo.GetAlgorithmHandle(ref _sha256); + + public static BCryptAlgorithmHandle SHA512 => CachedAlgorithmInfo.GetAlgorithmHandle(ref _sha512); + + // Only available on Win8+. + public static BCryptAlgorithmHandle SP800_108_CTR_HMAC => CachedAlgorithmInfo.GetAlgorithmHandle(ref _sp800_108_ctr_hmac); + + private static BCryptAlgorithmHandle GetAesAlgorithm(string chainingMode) + { + var algHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(Constants.BCRYPT_AES_ALGORITHM); + algHandle.SetChainingMode(chainingMode); + return algHandle; + } + + private static BCryptAlgorithmHandle GetHashAlgorithm(string algorithm) + { + return BCryptAlgorithmHandle.OpenAlgorithmHandle(algorithm, hmac: false); + } + + private static BCryptAlgorithmHandle GetHmacAlgorithm(string algorithm) + { + return BCryptAlgorithmHandle.OpenAlgorithmHandle(algorithm, hmac: true); + } + + private static BCryptAlgorithmHandle GetPbkdf2Algorithm() + { + return BCryptAlgorithmHandle.OpenAlgorithmHandle(Constants.BCRYPT_PBKDF2_ALGORITHM, implementation: Constants.MS_PRIMITIVE_PROVIDER); + } + + private static BCryptAlgorithmHandle GetSP800_108_CTR_HMACAlgorithm() + { + return BCryptAlgorithmHandle.OpenAlgorithmHandle(Constants.BCRYPT_SP800108_CTR_HMAC_ALGORITHM, implementation: Constants.MS_PRIMITIVE_PROVIDER); + } + + // Warning: mutable struct! + private struct CachedAlgorithmInfo + { + private WeakReference _algorithmHandle; + private readonly Func _factory; + + public CachedAlgorithmInfo(Func factory) + { + _algorithmHandle = null; + _factory = factory; + } + + public static BCryptAlgorithmHandle GetAlgorithmHandle(ref CachedAlgorithmInfo cachedAlgorithmInfo) + { + return WeakReferenceHelpers.GetSharedInstance(ref cachedAlgorithmInfo._algorithmHandle, cachedAlgorithmInfo._factory); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/NCryptEncryptFlags.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/NCryptEncryptFlags.cs new file mode 100644 index 0000000000..a0c1bc0fc4 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/NCryptEncryptFlags.cs @@ -0,0 +1,17 @@ +// 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; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + [Flags] + internal enum NCryptEncryptFlags + { + NCRYPT_NO_PADDING_FLAG = 0x00000001, + NCRYPT_PAD_PKCS1_FLAG = 0x00000002, + NCRYPT_PAD_OAEP_FLAG = 0x00000004, + NCRYPT_PAD_PSS_FLAG = 0x00000008, + NCRYPT_SILENT_FLAG = 0x00000040, + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/OSVersionUtil.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/OSVersionUtil.cs new file mode 100644 index 0000000000..0d09a0b6f8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Cng/OSVersionUtil.cs @@ -0,0 +1,66 @@ +// 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 Microsoft.AspNetCore.Cryptography.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + internal static class OSVersionUtil + { + private static readonly OSVersion _osVersion = GetOSVersion(); + + private static OSVersion GetOSVersion() + { + const string BCRYPT_LIB = "bcrypt.dll"; + SafeLibraryHandle bcryptLibHandle = null; + try + { + bcryptLibHandle = SafeLibraryHandle.Open(BCRYPT_LIB); + } + catch + { + // we'll handle the exceptional case later + } + + if (bcryptLibHandle != null) + { + using (bcryptLibHandle) + { + if (bcryptLibHandle.DoesProcExist("BCryptKeyDerivation")) + { + // We're running on Win8+. + return OSVersion.Win8OrLater; + } + else + { + // We're running on Win7+. + return OSVersion.Win7OrLater; + } + } + } + else + { + // Not running on Win7+. + return OSVersion.NotWindows; + } + } + + public static bool IsWindows() + { + return (_osVersion >= OSVersion.Win7OrLater); + } + + public static bool IsWindows8OrLater() + { + return (_osVersion >= OSVersion.Win8OrLater); + } + + private enum OSVersion + { + NotWindows = 0, + Win7OrLater = 1, + Win8OrLater = 2 + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Constants.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Constants.cs new file mode 100644 index 0000000000..44b0568aa8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Constants.cs @@ -0,0 +1,88 @@ +// 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; + +namespace Microsoft.AspNetCore.Cryptography +{ + // The majority of these are from bcrypt.h + internal static class Constants + { + internal const int MAX_STACKALLOC_BYTES = 256; // greatest number of bytes that we'll ever allow to stackalloc in a single frame + + // BCrypt(Import/Export)Key BLOB types + internal const string BCRYPT_OPAQUE_KEY_BLOB = "OpaqueKeyBlob"; + internal const string BCRYPT_KEY_DATA_BLOB = "KeyDataBlob"; + internal const string BCRYPT_AES_WRAP_KEY_BLOB = "Rfc3565KeyWrapBlob"; + + // Microsoft built-in providers + internal const string MS_PRIMITIVE_PROVIDER = "Microsoft Primitive Provider"; + internal const string MS_PLATFORM_CRYPTO_PROVIDER = "Microsoft Platform Crypto Provider"; + + // Common algorithm identifiers + internal const string BCRYPT_RSA_ALGORITHM = "RSA"; + internal const string BCRYPT_RSA_SIGN_ALGORITHM = "RSA_SIGN"; + internal const string BCRYPT_DH_ALGORITHM = "DH"; + internal const string BCRYPT_DSA_ALGORITHM = "DSA"; + internal const string BCRYPT_RC2_ALGORITHM = "RC2"; + internal const string BCRYPT_RC4_ALGORITHM = "RC4"; + internal const string BCRYPT_AES_ALGORITHM = "AES"; + internal const string BCRYPT_DES_ALGORITHM = "DES"; + internal const string BCRYPT_DESX_ALGORITHM = "DESX"; + internal const string BCRYPT_3DES_ALGORITHM = "3DES"; + internal const string BCRYPT_3DES_112_ALGORITHM = "3DES_112"; + internal const string BCRYPT_MD2_ALGORITHM = "MD2"; + internal const string BCRYPT_MD4_ALGORITHM = "MD4"; + internal const string BCRYPT_MD5_ALGORITHM = "MD5"; + internal const string BCRYPT_SHA1_ALGORITHM = "SHA1"; + internal const string BCRYPT_SHA256_ALGORITHM = "SHA256"; + internal const string BCRYPT_SHA384_ALGORITHM = "SHA384"; + internal const string BCRYPT_SHA512_ALGORITHM = "SHA512"; + internal const string BCRYPT_AES_GMAC_ALGORITHM = "AES-GMAC"; + internal const string BCRYPT_AES_CMAC_ALGORITHM = "AES-CMAC"; + internal const string BCRYPT_ECDSA_P256_ALGORITHM = "ECDSA_P256"; + internal const string BCRYPT_ECDSA_P384_ALGORITHM = "ECDSA_P384"; + internal const string BCRYPT_ECDSA_P521_ALGORITHM = "ECDSA_P521"; + internal const string BCRYPT_ECDH_P256_ALGORITHM = "ECDH_P256"; + internal const string BCRYPT_ECDH_P384_ALGORITHM = "ECDH_P384"; + internal const string BCRYPT_ECDH_P521_ALGORITHM = "ECDH_P521"; + internal const string BCRYPT_RNG_ALGORITHM = "RNG"; + internal const string BCRYPT_RNG_FIPS186_DSA_ALGORITHM = "FIPS186DSARNG"; + internal const string BCRYPT_RNG_DUAL_EC_ALGORITHM = "DUALECRNG"; + internal const string BCRYPT_SP800108_CTR_HMAC_ALGORITHM = "SP800_108_CTR_HMAC"; + internal const string BCRYPT_SP80056A_CONCAT_ALGORITHM = "SP800_56A_CONCAT"; + internal const string BCRYPT_PBKDF2_ALGORITHM = "PBKDF2"; + internal const string BCRYPT_CAPI_KDF_ALGORITHM = "CAPI_KDF"; + + // BCryptGetProperty strings + internal const string BCRYPT_OBJECT_LENGTH = "ObjectLength"; + internal const string BCRYPT_ALGORITHM_NAME = "AlgorithmName"; + internal const string BCRYPT_PROVIDER_HANDLE = "ProviderHandle"; + internal const string BCRYPT_CHAINING_MODE = "ChainingMode"; + internal const string BCRYPT_BLOCK_LENGTH = "BlockLength"; + internal const string BCRYPT_KEY_LENGTH = "KeyLength"; + internal const string BCRYPT_KEY_OBJECT_LENGTH = "KeyObjectLength"; + internal const string BCRYPT_KEY_STRENGTH = "KeyStrength"; + internal const string BCRYPT_KEY_LENGTHS = "KeyLengths"; + internal const string BCRYPT_BLOCK_SIZE_LIST = "BlockSizeList"; + internal const string BCRYPT_EFFECTIVE_KEY_LENGTH = "EffectiveKeyLength"; + internal const string BCRYPT_HASH_LENGTH = "HashDigestLength"; + internal const string BCRYPT_HASH_OID_LIST = "HashOIDList"; + internal const string BCRYPT_PADDING_SCHEMES = "PaddingSchemes"; + internal const string BCRYPT_SIGNATURE_LENGTH = "SignatureLength"; + internal const string BCRYPT_HASH_BLOCK_LENGTH = "HashBlockLength"; + internal const string BCRYPT_AUTH_TAG_LENGTH = "AuthTagLength"; + internal const string BCRYPT_PRIMITIVE_TYPE = "PrimitiveType"; + internal const string BCRYPT_IS_KEYED_HASH = "IsKeyedHash"; + internal const string BCRYPT_IS_REUSABLE_HASH = "IsReusableHash"; + internal const string BCRYPT_MESSAGE_BLOCK_LENGTH = "MessageBlockLength"; + + // Property Strings + internal const string BCRYPT_CHAIN_MODE_NA = "ChainingModeN/A"; + internal const string BCRYPT_CHAIN_MODE_CBC = "ChainingModeCBC"; + internal const string BCRYPT_CHAIN_MODE_ECB = "ChainingModeECB"; + internal const string BCRYPT_CHAIN_MODE_CFB = "ChainingModeCFB"; + internal const string BCRYPT_CHAIN_MODE_CCM = "ChainingModeCCM"; + internal const string BCRYPT_CHAIN_MODE_GCM = "ChainingModeGCM"; + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/CryptoUtil.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/CryptoUtil.cs new file mode 100644 index 0000000000..e60673634d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/CryptoUtil.cs @@ -0,0 +1,99 @@ +// 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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.Internal; + +namespace Microsoft.AspNetCore.Cryptography +{ + internal unsafe static class CryptoUtil + { + // This isn't a typical Debug.Assert; the check is always performed, even in retail builds. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Assert(bool condition, string message) + { + if (!condition) + { + Fail(message); + } + } + + // This isn't a typical Debug.Assert; the check is always performed, even in retail builds. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AssertSafeHandleIsValid(SafeHandle safeHandle) + { + Assert(safeHandle != null && !safeHandle.IsInvalid, "Safe handle is invalid."); + } + + // Asserts that the current platform is Windows; throws PlatformNotSupportedException otherwise. + public static void AssertPlatformIsWindows() + { + if (!OSVersionUtil.IsWindows()) + { + throw new PlatformNotSupportedException(Resources.Platform_Windows7Required); + } + } + + // Asserts that the current platform is Windows 8 or above; throws PlatformNotSupportedException otherwise. + public static void AssertPlatformIsWindows8OrLater() + { + if (!OSVersionUtil.IsWindows8OrLater()) + { + throw new PlatformNotSupportedException(Resources.Platform_Windows8Required); + } + } + + // This isn't a typical Debug.Fail; an error always occurs, even in retail builds. + // This method doesn't return, but since the CLR doesn't allow specifying a 'never' + // return type, we mimic it by specifying our return type as Exception. That way + // callers can write 'throw Fail(...);' to make the C# compiler happy, as the + // throw keyword is implicitly of type O. + [MethodImpl(MethodImplOptions.NoInlining)] + public static Exception Fail(string message) + { + Debug.Fail(message); + throw new CryptographicException("Assertion failed: " + message); + } + + // Allows callers to write "var x = Method() ?? Fail(message);" as a convenience to guard + // against a method returning null unexpectedly. + [MethodImpl(MethodImplOptions.NoInlining)] + public static T Fail(string message) where T : class + { + throw Fail(message); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static bool TimeConstantBuffersAreEqual(byte* bufA, byte* bufB, uint count) + { + bool areEqual = true; + for (uint i = 0; i < count; i++) + { + areEqual &= (bufA[i] == bufB[i]); + } + return areEqual; + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] + public static bool TimeConstantBuffersAreEqual(byte[] bufA, int offsetA, int countA, byte[] bufB, int offsetB, int countB) + { + // Technically this is an early exit scenario, but it means that the caller did something bizarre. + // An error at the call site isn't usable for timing attacks. + Assert(countA == countB, "countA == countB"); + + bool areEqual = true; + for (int i = 0; i < countA; i++) + { + areEqual &= (bufA[offsetA + i] == bufB[offsetB + i]); + } + return areEqual; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/DATA_BLOB.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/DATA_BLOB.cs new file mode 100644 index 0000000000..3c307bebce --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/DATA_BLOB.cs @@ -0,0 +1,16 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.AspNetCore.Cryptography +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa381414(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct DATA_BLOB + { + public uint cbData; + public byte* pbData; + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Microsoft.AspNetCore.Cryptography.Internal.csproj b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Microsoft.AspNetCore.Cryptography.Internal.csproj new file mode 100644 index 0000000000..ff4ef3babe --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Microsoft.AspNetCore.Cryptography.Internal.csproj @@ -0,0 +1,12 @@ + + + + Infrastructure for ASP.NET Core cryptographic packages. Applications and libraries should not reference this package directly. + netstandard2.0 + $(NoWarn);CS1591 + true + true + aspnetcore;dataprotection + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Properties/AssemblyInfo.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..62865ae945 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +// 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.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// we only ever p/invoke into DLLs known to be in the System32 folder +[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Cryptography.Internal.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Cryptography.KeyDerivation, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Cryptography.KeyDerivation.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.DataProtection, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.DataProtection.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.DataProtection.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.DataProtection.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Properties/Resources.Designer.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..df010bc683 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Properties/Resources.Designer.cs @@ -0,0 +1,86 @@ +// +namespace Microsoft.AspNetCore.Cryptography.Internal +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.AspNetCore.Cryptography.Internal.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// A provider could not be found for algorithm '{0}'. + /// + internal static string BCryptAlgorithmHandle_ProviderNotFound + { + get => GetString("BCryptAlgorithmHandle_ProviderNotFound"); + } + + /// + /// A provider could not be found for algorithm '{0}'. + /// + internal static string FormatBCryptAlgorithmHandle_ProviderNotFound(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("BCryptAlgorithmHandle_ProviderNotFound"), p0); + + /// + /// The key length {0} is invalid. Valid key lengths are {1} to {2} bits (step size {3}). + /// + internal static string BCRYPT_KEY_LENGTHS_STRUCT_InvalidKeyLength + { + get => GetString("BCRYPT_KEY_LENGTHS_STRUCT_InvalidKeyLength"); + } + + /// + /// The key length {0} is invalid. Valid key lengths are {1} to {2} bits (step size {3}). + /// + internal static string FormatBCRYPT_KEY_LENGTHS_STRUCT_InvalidKeyLength(object p0, object p1, object p2, object p3) + => string.Format(CultureInfo.CurrentCulture, GetString("BCRYPT_KEY_LENGTHS_STRUCT_InvalidKeyLength"), p0, p1, p2, p3); + + /// + /// This operation requires Windows 7 / Windows Server 2008 R2 or later. + /// + internal static string Platform_Windows7Required + { + get => GetString("Platform_Windows7Required"); + } + + /// + /// This operation requires Windows 7 / Windows Server 2008 R2 or later. + /// + internal static string FormatPlatform_Windows7Required() + => GetString("Platform_Windows7Required"); + + /// + /// This operation requires Windows 8 / Windows Server 2012 or later. + /// + internal static string Platform_Windows8Required + { + get => GetString("Platform_Windows8Required"); + } + + /// + /// This operation requires Windows 8 / Windows Server 2012 or later. + /// + internal static string FormatPlatform_Windows8Required() + => GetString("Platform_Windows8Required"); + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Resources.resx b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Resources.resx new file mode 100644 index 0000000000..125f619abb --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/Resources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + A provider could not be found for algorithm '{0}'. + + + The key length {0} is invalid. Valid key lengths are {1} to {2} bits (step size {3}). + + + This operation requires Windows 7 / Windows Server 2008 R2 or later. + + + This operation requires Windows 8 / Windows Server 2012 or later. + + \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptAlgorithmHandle.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptAlgorithmHandle.cs new file mode 100644 index 0000000000..45f4c4e041 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptAlgorithmHandle.cs @@ -0,0 +1,170 @@ +// 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.Diagnostics; +using System.Globalization; +using System.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.Internal; + +namespace Microsoft.AspNetCore.Cryptography.SafeHandles +{ + /// + /// Represents a handle to a BCrypt algorithm provider from which keys and hashes can be created. + /// + internal unsafe sealed class BCryptAlgorithmHandle : BCryptHandle + { + // Called by P/Invoke when returning SafeHandles + private BCryptAlgorithmHandle() { } + + /// + /// Creates an unkeyed hash handle from this hash algorithm. + /// + public BCryptHashHandle CreateHash() + { + return CreateHashCore(null, 0); + } + + private BCryptHashHandle CreateHashCore(byte* pbKey, uint cbKey) + { + BCryptHashHandle retVal; + int ntstatus = UnsafeNativeMethods.BCryptCreateHash(this, out retVal, IntPtr.Zero, 0, pbKey, cbKey, dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + CryptoUtil.AssertSafeHandleIsValid(retVal); + + retVal.SetAlgorithmProviderHandle(this); + return retVal; + } + + /// + /// Creates an HMAC hash handle from this hash algorithm. + /// + public BCryptHashHandle CreateHmac(byte* pbKey, uint cbKey) + { + Debug.Assert(pbKey != null); + return CreateHashCore(pbKey, cbKey); + } + + /// + /// Imports a key into a symmetric encryption or KDF algorithm. + /// + public BCryptKeyHandle GenerateSymmetricKey(byte* pbSecret, uint cbSecret) + { + BCryptKeyHandle retVal; + int ntstatus = UnsafeNativeMethods.BCryptGenerateSymmetricKey(this, out retVal, IntPtr.Zero, 0, pbSecret, cbSecret, 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + CryptoUtil.AssertSafeHandleIsValid(retVal); + + retVal.SetAlgorithmProviderHandle(this); + return retVal; + } + + /// + /// Gets the name of this BCrypt algorithm. + /// + public string GetAlgorithmName() + { + // First, calculate how many characters are in the name. + uint byteLengthOfNameWithTerminatingNull = GetProperty(Constants.BCRYPT_ALGORITHM_NAME, null, 0); + CryptoUtil.Assert(byteLengthOfNameWithTerminatingNull % sizeof(char) == 0 && byteLengthOfNameWithTerminatingNull > sizeof(char), "byteLengthOfNameWithTerminatingNull % sizeof(char) == 0 && byteLengthOfNameWithTerminatingNull > sizeof(char)"); + uint numCharsWithoutNull = (byteLengthOfNameWithTerminatingNull - 1) / sizeof(char); + + if (numCharsWithoutNull == 0) + { + return String.Empty; // degenerate case + } + + // Allocate a string object and write directly into it (CLR team approves of this mechanism). + string retVal = new String((char)0, checked((int)numCharsWithoutNull)); + uint numBytesCopied; + fixed (char* pRetVal = retVal) + { + numBytesCopied = GetProperty(Constants.BCRYPT_ALGORITHM_NAME, pRetVal, byteLengthOfNameWithTerminatingNull); + } + CryptoUtil.Assert(numBytesCopied == byteLengthOfNameWithTerminatingNull, "numBytesCopied == byteLengthOfNameWithTerminatingNull"); + return retVal; + } + + /// + /// Gets the cipher block length (in bytes) of this block cipher algorithm. + /// + public uint GetCipherBlockLength() + { + uint cipherBlockLength; + uint numBytesCopied = GetProperty(Constants.BCRYPT_BLOCK_LENGTH, &cipherBlockLength, sizeof(uint)); + CryptoUtil.Assert(numBytesCopied == sizeof(uint), "numBytesCopied == sizeof(uint)"); + return cipherBlockLength; + } + + /// + /// Gets the hash block length (in bytes) of this hash algorithm. + /// + public uint GetHashBlockLength() + { + uint hashBlockLength; + uint numBytesCopied = GetProperty(Constants.BCRYPT_HASH_BLOCK_LENGTH, &hashBlockLength, sizeof(uint)); + CryptoUtil.Assert(numBytesCopied == sizeof(uint), "numBytesCopied == sizeof(uint)"); + return hashBlockLength; + } + + /// + /// Gets the key lengths (in bits) supported by this algorithm. + /// + public BCRYPT_KEY_LENGTHS_STRUCT GetSupportedKeyLengths() + { + BCRYPT_KEY_LENGTHS_STRUCT supportedKeyLengths; + uint numBytesCopied = GetProperty(Constants.BCRYPT_KEY_LENGTHS, &supportedKeyLengths, (uint)sizeof(BCRYPT_KEY_LENGTHS_STRUCT)); + CryptoUtil.Assert(numBytesCopied == sizeof(BCRYPT_KEY_LENGTHS_STRUCT), "numBytesCopied == sizeof(BCRYPT_KEY_LENGTHS_STRUCT)"); + return supportedKeyLengths; + } + + /// + /// Gets the digest length (in bytes) of this hash algorithm provider. + /// + public uint GetHashDigestLength() + { + uint digestLength; + uint numBytesCopied = GetProperty(Constants.BCRYPT_HASH_LENGTH, &digestLength, sizeof(uint)); + CryptoUtil.Assert(numBytesCopied == sizeof(uint), "numBytesCopied == sizeof(uint)"); + return digestLength; + } + + public static BCryptAlgorithmHandle OpenAlgorithmHandle(string algorithmId, string implementation = null, bool hmac = false) + { + // from bcrypt.h + const uint BCRYPT_ALG_HANDLE_HMAC_FLAG = 0x00000008; + + // from ntstatus.h + const int STATUS_NOT_FOUND = unchecked((int)0xC0000225); + + BCryptAlgorithmHandle algHandle; + int ntstatus = UnsafeNativeMethods.BCryptOpenAlgorithmProvider(out algHandle, algorithmId, implementation, dwFlags: (hmac) ? BCRYPT_ALG_HANDLE_HMAC_FLAG : 0); + + // error checking + if (ntstatus == STATUS_NOT_FOUND) + { + string message = String.Format(CultureInfo.CurrentCulture, Resources.BCryptAlgorithmHandle_ProviderNotFound, algorithmId); + throw new CryptographicException(message); + } + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + CryptoUtil.AssertSafeHandleIsValid(algHandle); + + return algHandle; + } + + // Do not provide a finalizer - SafeHandle's critical finalizer will call ReleaseHandle for you. + protected override bool ReleaseHandle() + { + return (UnsafeNativeMethods.BCryptCloseAlgorithmProvider(handle, dwFlags: 0) == 0); + } + + public void SetChainingMode(string chainingMode) + { + fixed (char* pszChainingMode = chainingMode ?? String.Empty) + { + SetProperty(Constants.BCRYPT_CHAINING_MODE, pszChainingMode, checked((uint)(chainingMode.Length + 1 /* null terminator */) * sizeof(char))); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptHandle.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptHandle.cs new file mode 100644 index 0000000000..66b2c1dbd4 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptHandle.cs @@ -0,0 +1,30 @@ +// 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 Microsoft.Win32.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography.SafeHandles +{ + internal unsafe abstract class BCryptHandle : SafeHandleZeroOrMinusOneIsInvalid + { + protected BCryptHandle() + : base(ownsHandle: true) + { + } + + protected uint GetProperty(string pszProperty, void* pbOutput, uint cbOutput) + { + uint retVal; + int ntstatus = UnsafeNativeMethods.BCryptGetProperty(this, pszProperty, pbOutput, cbOutput, out retVal, dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + return retVal; + } + + protected void SetProperty(string pszProperty, void* pbInput, uint cbInput) + { + int ntstatus = UnsafeNativeMethods.BCryptSetProperty(this, pszProperty, pbInput, cbInput, dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptHashHandle.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptHashHandle.cs new file mode 100644 index 0000000000..dace0f23ae --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptHashHandle.cs @@ -0,0 +1,71 @@ +// 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 Microsoft.Win32.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography.SafeHandles +{ + internal unsafe sealed class BCryptHashHandle : BCryptHandle + { + private BCryptAlgorithmHandle _algProviderHandle; + + // Called by P/Invoke when returning SafeHandles + private BCryptHashHandle() { } + + /// + /// Duplicates this hash handle, including any existing hashed state. + /// + public BCryptHashHandle DuplicateHash() + { + BCryptHashHandle duplicateHandle; + int ntstatus = UnsafeNativeMethods.BCryptDuplicateHash(this, out duplicateHandle, IntPtr.Zero, 0, 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + CryptoUtil.AssertSafeHandleIsValid(duplicateHandle); + + duplicateHandle._algProviderHandle = this._algProviderHandle; + return duplicateHandle; + } + + /// + /// Calculates the cryptographic hash over a set of input data. + /// + public void HashData(byte* pbInput, uint cbInput, byte* pbHashDigest, uint cbHashDigest) + { + int ntstatus; + if (cbInput > 0) + { + ntstatus = UnsafeNativeMethods.BCryptHashData( + hHash: this, + pbInput: pbInput, + cbInput: cbInput, + dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + } + + ntstatus = UnsafeNativeMethods.BCryptFinishHash( + hHash: this, + pbOutput: pbHashDigest, + cbOutput: cbHashDigest, + dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + } + + // Do not provide a finalizer - SafeHandle's critical finalizer will call ReleaseHandle for you. + protected override bool ReleaseHandle() + { + return (UnsafeNativeMethods.BCryptDestroyHash(handle) == 0); + } + + // We don't actually need to hold a reference to the algorithm handle, as the native CNG library + // already holds the reference for us. But once we create a hash from an algorithm provider, odds + // are good that we'll create another hash from the same algorithm provider at some point in the + // future. And since algorithm providers are expensive to create, we'll hold a strong reference + // to all known in-use providers. This way the cached algorithm provider handles utility class + // doesn't keep creating providers over and over. + internal void SetAlgorithmProviderHandle(BCryptAlgorithmHandle algProviderHandle) + { + _algProviderHandle = algProviderHandle; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptKeyHandle.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptKeyHandle.cs new file mode 100644 index 0000000000..cd7d05f8e3 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/BCryptKeyHandle.cs @@ -0,0 +1,33 @@ +// 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; + +namespace Microsoft.AspNetCore.Cryptography.SafeHandles +{ + internal sealed class BCryptKeyHandle : BCryptHandle + { + private BCryptAlgorithmHandle _algProviderHandle; + + // Called by P/Invoke when returning SafeHandles + private BCryptKeyHandle() { } + + // Do not provide a finalizer - SafeHandle's critical finalizer will call ReleaseHandle for you. + protected override bool ReleaseHandle() + { + _algProviderHandle = null; + return (UnsafeNativeMethods.BCryptDestroyKey(handle) == 0); + } + + // We don't actually need to hold a reference to the algorithm handle, as the native CNG library + // already holds the reference for us. But once we create a key from an algorithm provider, odds + // are good that we'll create another key from the same algorithm provider at some point in the + // future. And since algorithm providers are expensive to create, we'll hold a strong reference + // to all known in-use providers. This way the cached algorithm provider handles utility class + // doesn't keep creating providers over and over. + internal void SetAlgorithmProviderHandle(BCryptAlgorithmHandle algProviderHandle) + { + _algProviderHandle = algProviderHandle; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/LocalAllocHandle.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/LocalAllocHandle.cs new file mode 100644 index 0000000000..852c5d1594 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/LocalAllocHandle.cs @@ -0,0 +1,26 @@ +// 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.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography.SafeHandles +{ + /// + /// Represents a handle returned by LocalAlloc. + /// + internal class LocalAllocHandle : SafeHandleZeroOrMinusOneIsInvalid + { + // Called by P/Invoke when returning SafeHandles + protected LocalAllocHandle() + : base(ownsHandle: true) { } + + // Do not provide a finalizer - SafeHandle's critical finalizer will call ReleaseHandle for you. + protected override bool ReleaseHandle() + { + Marshal.FreeHGlobal(handle); // actually calls LocalFree + return true; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/NCryptDescriptorHandle.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/NCryptDescriptorHandle.cs new file mode 100644 index 0000000000..3a181cf06b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/NCryptDescriptorHandle.cs @@ -0,0 +1,42 @@ +// 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 Microsoft.Win32.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography.SafeHandles +{ + internal unsafe sealed class NCryptDescriptorHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private NCryptDescriptorHandle() + : base(ownsHandle: true) + { + } + + public string GetProtectionDescriptorRuleString() + { + // from ncryptprotect.h + const int NCRYPT_PROTECTION_INFO_TYPE_DESCRIPTOR_STRING = 0x00000001; + + LocalAllocHandle ruleStringHandle; + int ntstatus = UnsafeNativeMethods.NCryptGetProtectionDescriptorInfo( + hDescriptor: this, + pMemPara: IntPtr.Zero, + dwInfoType: NCRYPT_PROTECTION_INFO_TYPE_DESCRIPTOR_STRING, + ppvInfo: out ruleStringHandle); + UnsafeNativeMethods.ThrowExceptionForNCryptStatus(ntstatus); + CryptoUtil.AssertSafeHandleIsValid(ruleStringHandle); + + using (ruleStringHandle) + { + return new String((char*)ruleStringHandle.DangerousGetHandle()); + } + } + + // Do not provide a finalizer - SafeHandle's critical finalizer will call ReleaseHandle for you. + protected override bool ReleaseHandle() + { + return (UnsafeNativeMethods.NCryptCloseProtectionDescriptor(handle) == 0); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/SafeLibraryHandle.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/SafeLibraryHandle.cs new file mode 100644 index 0000000000..ccd0b99c79 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/SafeLibraryHandle.cs @@ -0,0 +1,176 @@ +// 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.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security; +using Microsoft.Win32.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography.SafeHandles +{ + /// + /// Represents a handle to a Windows module (DLL). + /// + internal unsafe sealed class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid + { + // Called by P/Invoke when returning SafeHandles + private SafeLibraryHandle() + : base(ownsHandle: true) + { } + + /// + /// Returns a value stating whether the library exports a given proc. + /// + public bool DoesProcExist(string lpProcName) + { + IntPtr pfnProc = UnsafeNativeMethods.GetProcAddress(this, lpProcName); + return (pfnProc != IntPtr.Zero); + } + + /// + /// Forbids this library from being unloaded. The library will remain loaded until process termination, + /// regardless of how many times FreeLibrary is called. + /// + public void ForbidUnload() + { + // from winbase.h + const uint GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 0x00000004U; + const uint GET_MODULE_HANDLE_EX_FLAG_PIN = 0x00000001U; + + IntPtr unused; + bool retVal = UnsafeNativeMethods.GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, this, out unused); + if (!retVal) + { + UnsafeNativeMethods.ThrowExceptionForLastWin32Error(); + } + } + + /// + /// Formats a message string using the resource table in the specified library. + /// + public string FormatMessage(int messageId) + { + // from winbase.h + const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; + const uint FORMAT_MESSAGE_FROM_HMODULE = 0x00000800; + const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; + const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; + + LocalAllocHandle messageHandle; + int numCharsOutput = UnsafeNativeMethods.FormatMessage( + dwFlags: FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + lpSource: this, + dwMessageId: (uint)messageId, + dwLanguageId: 0 /* ignore current culture */, + lpBuffer: out messageHandle, + nSize: 0 /* unused */, + Arguments: IntPtr.Zero /* unused */); + + if (numCharsOutput != 0 && messageHandle != null && !messageHandle.IsInvalid) + { + // Successfully retrieved the message. + using (messageHandle) + { + return new String((char*)messageHandle.DangerousGetHandle(), 0, numCharsOutput).Trim(); + } + } + else + { + // Message not found - that's fine. + return null; + } + } + + /// + /// Gets a delegate pointing to a given export from this library. + /// + public TDelegate GetProcAddress(string lpProcName, bool throwIfNotFound = true) where TDelegate : class + { + IntPtr pfnProc = UnsafeNativeMethods.GetProcAddress(this, lpProcName); + if (pfnProc == IntPtr.Zero) + { + if (throwIfNotFound) + { + UnsafeNativeMethods.ThrowExceptionForLastWin32Error(); + } + else + { + return null; + } + } + + return Marshal.GetDelegateForFunctionPointer(pfnProc); + } + + /// + /// Opens a library. If 'filename' is not a fully-qualified path, the default search path is used. + /// + public static SafeLibraryHandle Open(string filename) + { + const uint LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800U; // from libloaderapi.h + + SafeLibraryHandle handle = UnsafeNativeMethods.LoadLibraryEx(filename, IntPtr.Zero, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (handle == null || handle.IsInvalid) + { + UnsafeNativeMethods.ThrowExceptionForLastWin32Error(); + } + return handle; + } + + // Do not provide a finalizer - SafeHandle's critical finalizer will call ReleaseHandle for you. + protected override bool ReleaseHandle() + { + return UnsafeNativeMethods.FreeLibrary(handle); + } + + [SuppressUnmanagedCodeSecurity] + private static class UnsafeNativeMethods + { + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx + [DllImport("kernel32.dll", EntryPoint = "FormatMessageW", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, SetLastError = true)] + public static extern int FormatMessage( + [In] uint dwFlags, + [In] SafeLibraryHandle lpSource, + [In] uint dwMessageId, + [In] uint dwLanguageId, + [Out] out LocalAllocHandle lpBuffer, + [In] uint nSize, + [In] IntPtr Arguments + ); + + // http://msdn.microsoft.com/en-us/library/ms683152(v=vs.85).aspx + [return: MarshalAs(UnmanagedType.Bool)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)] + internal static extern bool FreeLibrary(IntPtr hModule); + + // http://msdn.microsoft.com/en-us/library/ms683200(v=vs.85).aspx + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll", EntryPoint = "GetModuleHandleExW", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + internal static extern bool GetModuleHandleEx( + [In] uint dwFlags, + [In] SafeLibraryHandle lpModuleName, // can point to a location within the module if GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS is set + [Out] out IntPtr phModule); + + // http://msdn.microsoft.com/en-us/library/ms683212(v=vs.85).aspx + [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + internal static extern IntPtr GetProcAddress( + [In] SafeLibraryHandle hModule, + [In, MarshalAs(UnmanagedType.LPStr)] string lpProcName); + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx + [DllImport("kernel32.dll", EntryPoint = "LoadLibraryExW", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + internal static extern SafeLibraryHandle LoadLibraryEx( + [In, MarshalAs(UnmanagedType.LPWStr)] string lpFileName, + [In] IntPtr hFile, + [In] uint dwFlags); + + internal static void ThrowExceptionForLastWin32Error() + { + int hr = Marshal.GetHRForLastWin32Error(); + Marshal.ThrowExceptionForHR(hr); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/SecureLocalAllocHandle.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/SecureLocalAllocHandle.cs new file mode 100644 index 0000000000..ac1f3c6172 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/SafeHandles/SecureLocalAllocHandle.cs @@ -0,0 +1,61 @@ +// 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.Runtime.InteropServices; +using System.Runtime.ConstrainedExecution; + +namespace Microsoft.AspNetCore.Cryptography.SafeHandles +{ + /// + /// Represents a handle returned by LocalAlloc. + /// The memory will be zeroed out before it's freed. + /// + internal unsafe sealed class SecureLocalAllocHandle : LocalAllocHandle + { + private readonly IntPtr _cb; + + private SecureLocalAllocHandle(IntPtr cb) + { + _cb = cb; + } + + public IntPtr Length + { + get + { + return _cb; + } + } + + /// + /// Allocates some amount of memory using LocalAlloc. + /// + public static SecureLocalAllocHandle Allocate(IntPtr cb) + { + SecureLocalAllocHandle newHandle = new SecureLocalAllocHandle(cb); + newHandle.AllocateImpl(cb); + return newHandle; + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + private void AllocateImpl(IntPtr cb) + { + handle = Marshal.AllocHGlobal(cb); // actually calls LocalAlloc + } + + public SecureLocalAllocHandle Duplicate() + { + SecureLocalAllocHandle duplicateHandle = Allocate(_cb); + UnsafeBufferUtil.BlockCopy(from: this, to: duplicateHandle, length: _cb); + return duplicateHandle; + } + + // Do not provide a finalizer - SafeHandle's critical finalizer will call ReleaseHandle for you. + protected override bool ReleaseHandle() + { + UnsafeBufferUtil.SecureZeroMemory((byte*)handle, _cb); // compiler won't optimize this away + return base.ReleaseHandle(); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/UnsafeBufferUtil.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/UnsafeBufferUtil.cs new file mode 100644 index 0000000000..681adb8bc3 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/UnsafeBufferUtil.cs @@ -0,0 +1,179 @@ +// 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.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; +using System.Threading; +using Microsoft.AspNetCore.Cryptography.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography +{ + internal unsafe static class UnsafeBufferUtil + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static void BlockCopy(void* from, void* to, int byteCount) + { + BlockCopy(from, to, checked((uint)byteCount)); // will be checked before invoking the delegate + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static void BlockCopy(void* from, void* to, uint byteCount) + { + if (byteCount != 0) + { + BlockCopyCore((byte*)from, (byte*)to, byteCount); + } + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + public static void BlockCopy(LocalAllocHandle from, void* to, uint byteCount) + { + bool refAdded = false; + try + { + from.DangerousAddRef(ref refAdded); + BlockCopy((void*)from.DangerousGetHandle(), to, byteCount); + } + finally + { + if (refAdded) + { + from.DangerousRelease(); + } + } + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + public static void BlockCopy(void* from, LocalAllocHandle to, uint byteCount) + { + bool refAdded = false; + try + { + to.DangerousAddRef(ref refAdded); + BlockCopy(from, (void*)to.DangerousGetHandle(), byteCount); + } + finally + { + if (refAdded) + { + to.DangerousRelease(); + } + } + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + public static void BlockCopy(LocalAllocHandle from, LocalAllocHandle to, IntPtr length) + { + if (length == IntPtr.Zero) + { + return; + } + + bool fromRefAdded = false; + bool toRefAdded = false; + try + { + from.DangerousAddRef(ref fromRefAdded); + to.DangerousAddRef(ref toRefAdded); + if (sizeof(IntPtr) == 4) + { + BlockCopyCore(from: (byte*)from.DangerousGetHandle(), to: (byte*)to.DangerousGetHandle(), byteCount: (uint)length.ToInt32()); + } + else + { + BlockCopyCore(from: (byte*)from.DangerousGetHandle(), to: (byte*)to.DangerousGetHandle(), byteCount: (ulong)length.ToInt64()); + } + } + finally + { + if (fromRefAdded) + { + from.DangerousRelease(); + } + if (toRefAdded) + { + to.DangerousRelease(); + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void BlockCopyCore(byte* from, byte* to, uint byteCount) + { + Buffer.MemoryCopy(from, to, (ulong)byteCount, (ulong)byteCount); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void BlockCopyCore(byte* from, byte* to, ulong byteCount) + { + Buffer.MemoryCopy(from, to, byteCount, byteCount); + } + + /// + /// Securely clears a memory buffer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static void SecureZeroMemory(byte* buffer, int byteCount) + { + SecureZeroMemory(buffer, checked((uint)byteCount)); + } + + /// + /// Securely clears a memory buffer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static void SecureZeroMemory(byte* buffer, uint byteCount) + { + if (byteCount != 0) + { + do + { + buffer[--byteCount] = 0; + } while (byteCount != 0); + + // Volatile to make sure the zero-writes don't get optimized away + Volatile.Write(ref *buffer, 0); + } + } + + /// + /// Securely clears a memory buffer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static void SecureZeroMemory(byte* buffer, ulong byteCount) + { + if (byteCount != 0) + { + do + { + buffer[--byteCount] = 0; + } while (byteCount != 0); + + // Volatile to make sure the zero-writes don't get optimized away + Volatile.Write(ref *buffer, 0); + } + } + + /// + /// Securely clears a memory buffer. + /// + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static void SecureZeroMemory(byte* buffer, IntPtr length) + { + if (sizeof(IntPtr) == 4) + { + SecureZeroMemory(buffer, (uint)length.ToInt32()); + } + else + { + SecureZeroMemory(buffer, (ulong)length.ToInt64()); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/UnsafeNativeMethods.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/UnsafeNativeMethods.cs new file mode 100644 index 0000000000..3a5a4d8db3 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/UnsafeNativeMethods.cs @@ -0,0 +1,346 @@ +// 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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Cryptography; +using System.Threading; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Microsoft.Win32.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography +{ + [SuppressUnmanagedCodeSecurity] + internal unsafe static class UnsafeNativeMethods + { + private const string BCRYPT_LIB = "bcrypt.dll"; + private static readonly Lazy _lazyBCryptLibHandle = GetLazyLibraryHandle(BCRYPT_LIB); + + private const string CRYPT32_LIB = "crypt32.dll"; + private static readonly Lazy _lazyCrypt32LibHandle = GetLazyLibraryHandle(CRYPT32_LIB); + + private const string NCRYPT_LIB = "ncrypt.dll"; + private static readonly Lazy _lazyNCryptLibHandle = GetLazyLibraryHandle(NCRYPT_LIB); + + private static Lazy GetLazyLibraryHandle(string libraryName) + { + // We don't need to worry about race conditions: SafeLibraryHandle will clean up after itself + return new Lazy(() => SafeLibraryHandle.Open(libraryName), LazyThreadSafetyMode.PublicationOnly); + } + + /* + * BCRYPT.DLL + */ + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375377(v=vs.85).aspx + internal static extern int BCryptCloseAlgorithmProvider( + [In] IntPtr hAlgorithm, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375383(v=vs.85).aspx + internal static extern int BCryptCreateHash( + [In] BCryptAlgorithmHandle hAlgorithm, + [Out] out BCryptHashHandle phHash, + [In] IntPtr pbHashObject, + [In] uint cbHashObject, + [In] byte* pbSecret, + [In] uint cbSecret, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375391(v=vs.85).aspx + internal static extern int BCryptDecrypt( + [In] BCryptKeyHandle hKey, + [In] byte* pbInput, + [In] uint cbInput, + [In] void* pPaddingInfo, + [In] byte* pbIV, + [In] uint cbIV, + [In] byte* pbOutput, + [In] uint cbOutput, + [Out] out uint pcbResult, + [In] BCryptEncryptFlags dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/dd433795(v=vs.85).aspx + internal static extern int BCryptDeriveKeyPBKDF2( + [In] BCryptAlgorithmHandle hPrf, + [In] byte* pbPassword, + [In] uint cbPassword, + [In] byte* pbSalt, + [In] uint cbSalt, + [In] ulong cIterations, + [In] byte* pbDerivedKey, + [In] uint cbDerivedKey, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375399(v=vs.85).aspx + internal static extern int BCryptDestroyHash( + [In] IntPtr hHash); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375404(v=vs.85).aspx + internal static extern int BCryptDestroyKey( + [In] IntPtr hKey); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375413(v=vs.85).aspx + internal static extern int BCryptDuplicateHash( + [In] BCryptHashHandle hHash, + [Out] out BCryptHashHandle phNewHash, + [In] IntPtr pbHashObject, + [In] uint cbHashObject, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375421(v=vs.85).aspx + internal static extern int BCryptEncrypt( + [In] BCryptKeyHandle hKey, + [In] byte* pbInput, + [In] uint cbInput, + [In] void* pPaddingInfo, + [In] byte* pbIV, + [In] uint cbIV, + [In] byte* pbOutput, + [In] uint cbOutput, + [Out] out uint pcbResult, + [In] BCryptEncryptFlags dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375443(v=vs.85).aspx + internal static extern int BCryptFinishHash( + [In] BCryptHashHandle hHash, + [In] byte* pbOutput, + [In] uint cbOutput, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375453(v=vs.85).aspx + internal static extern int BCryptGenerateSymmetricKey( + [In] BCryptAlgorithmHandle hAlgorithm, + [Out] out BCryptKeyHandle phKey, + [In] IntPtr pbKeyObject, + [In] uint cbKeyObject, + [In] byte* pbSecret, + [In] uint cbSecret, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375458(v=vs.85).aspx + internal static extern int BCryptGenRandom( + [In] IntPtr hAlgorithm, + [In] byte* pbBuffer, + [In] uint cbBuffer, + [In] BCryptGenRandomFlags dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375464(v=vs.85).aspx + internal static extern int BCryptGetProperty( + [In] BCryptHandle hObject, + [In, MarshalAs(UnmanagedType.LPWStr)] string pszProperty, + [In] void* pbOutput, + [In] uint cbOutput, + [Out] out uint pcbResult, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375468(v=vs.85).aspx + internal static extern int BCryptHashData( + [In] BCryptHashHandle hHash, + [In] byte* pbInput, + [In] uint cbInput, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/hh448506(v=vs.85).aspx + internal static extern int BCryptKeyDerivation( + [In] BCryptKeyHandle hKey, + [In] BCryptBufferDesc* pParameterList, + [In] byte* pbDerivedKey, + [In] uint cbDerivedKey, + [Out] out uint pcbResult, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375479(v=vs.85).aspx + internal static extern int BCryptOpenAlgorithmProvider( + [Out] out BCryptAlgorithmHandle phAlgorithm, + [In, MarshalAs(UnmanagedType.LPWStr)] string pszAlgId, + [In, MarshalAs(UnmanagedType.LPWStr)] string pszImplementation, + [In] uint dwFlags); + + [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375504(v=vs.85).aspx + internal static extern int BCryptSetProperty( + [In] BCryptHandle hObject, + [In, MarshalAs(UnmanagedType.LPWStr)] string pszProperty, + [In] void* pbInput, + [In] uint cbInput, + [In] uint dwFlags); + + /* + * CRYPT32.DLL + */ + + [DllImport(CRYPT32_LIB, CallingConvention = CallingConvention.Winapi, SetLastError = true)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380261(v=vs.85).aspx + internal static extern bool CryptProtectData( + [In] DATA_BLOB* pDataIn, + [In] IntPtr szDataDescr, + [In] DATA_BLOB* pOptionalEntropy, + [In] IntPtr pvReserved, + [In] IntPtr pPromptStruct, + [In] uint dwFlags, + [Out] out DATA_BLOB pDataOut); + + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380262(v=vs.85).aspx + [DllImport(CRYPT32_LIB, CallingConvention = CallingConvention.Winapi, SetLastError = true)] + public static extern bool CryptProtectMemory( + [In] SafeHandle pData, + [In] uint cbData, + [In] uint dwFlags); + + [DllImport(CRYPT32_LIB, CallingConvention = CallingConvention.Winapi, SetLastError = true)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380882(v=vs.85).aspx + internal static extern bool CryptUnprotectData( + [In] DATA_BLOB* pDataIn, + [In] IntPtr ppszDataDescr, + [In] DATA_BLOB* pOptionalEntropy, + [In] IntPtr pvReserved, + [In] IntPtr pPromptStruct, + [In] uint dwFlags, + [Out] out DATA_BLOB pDataOut); + + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380890(v=vs.85).aspx + [DllImport(CRYPT32_LIB, CallingConvention = CallingConvention.Winapi, SetLastError = true)] + public static extern bool CryptUnprotectMemory( + [In] byte* pData, + [In] uint cbData, + [In] uint dwFlags); + + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380890(v=vs.85).aspx + [DllImport(CRYPT32_LIB, CallingConvention = CallingConvention.Winapi, SetLastError = true)] + public static extern bool CryptUnprotectMemory( + [In] SafeHandle pData, + [In] uint cbData, + [In] uint dwFlags); + + /* + * NCRYPT.DLL + */ + + [DllImport(NCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/hh706799(v=vs.85).aspx + internal static extern int NCryptCloseProtectionDescriptor( + [In] IntPtr hDescriptor); + + [DllImport(NCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/hh706800(v=vs.85).aspx + internal static extern int NCryptCreateProtectionDescriptor( + [In, MarshalAs(UnmanagedType.LPWStr)] string pwszDescriptorString, + [In] uint dwFlags, + [Out] out NCryptDescriptorHandle phDescriptor); + + [DllImport(NCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh706801(v=vs.85).aspx + internal static extern int NCryptGetProtectionDescriptorInfo( + [In] NCryptDescriptorHandle hDescriptor, + [In] IntPtr pMemPara, + [In] uint dwInfoType, + [Out] out LocalAllocHandle ppvInfo); + + [DllImport(NCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/hh706802(v=vs.85).aspx + internal static extern int NCryptProtectSecret( + [In] NCryptDescriptorHandle hDescriptor, + [In] uint dwFlags, + [In] byte* pbData, + [In] uint cbData, + [In] IntPtr pMemPara, + [In] IntPtr hWnd, + [Out] out LocalAllocHandle ppbProtectedBlob, + [Out] out uint pcbProtectedBlob); + + [DllImport(NCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/hh706811(v=vs.85).aspx + internal static extern int NCryptUnprotectSecret( + [In] IntPtr phDescriptor, + [In] uint dwFlags, + [In] byte* pbProtectedBlob, + [In] uint cbProtectedBlob, + [In] IntPtr pMemPara, + [In] IntPtr hWnd, + [Out] out LocalAllocHandle ppbData, + [Out] out uint pcbData); + + [DllImport(NCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] + // http://msdn.microsoft.com/en-us/library/windows/desktop/hh706811(v=vs.85).aspx + internal static extern int NCryptUnprotectSecret( + [Out] out NCryptDescriptorHandle phDescriptor, + [In] uint dwFlags, + [In] byte* pbProtectedBlob, + [In] uint cbProtectedBlob, + [In] IntPtr pMemPara, + [In] IntPtr hWnd, + [Out] out LocalAllocHandle ppbData, + [Out] out uint pcbData); + + /* + * HELPER FUNCTIONS + */ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ThrowExceptionForBCryptStatus(int ntstatus) + { + // This wrapper method exists because 'throw' statements won't always be inlined. + if (ntstatus != 0) + { + ThrowExceptionForBCryptStatusImpl(ntstatus); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void ThrowExceptionForBCryptStatusImpl(int ntstatus) + { + string message = _lazyBCryptLibHandle.Value.FormatMessage(ntstatus); + throw new CryptographicException(message); + } + + public static void ThrowExceptionForLastCrypt32Error() + { + int lastError = Marshal.GetLastWin32Error(); + Debug.Assert(lastError != 0, "This method should only be called if there was an error."); + + string message = _lazyCrypt32LibHandle.Value.FormatMessage(lastError); + throw new CryptographicException(message); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ThrowExceptionForNCryptStatus(int ntstatus) + { + // This wrapper method exists because 'throw' statements won't always be inlined. + if (ntstatus != 0) + { + ThrowExceptionForNCryptStatusImpl(ntstatus); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void ThrowExceptionForNCryptStatusImpl(int ntstatus) + { + string message = _lazyNCryptLibHandle.Value.FormatMessage(ntstatus); + throw new CryptographicException(message); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/WeakReferenceHelpers.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/WeakReferenceHelpers.cs new file mode 100644 index 0000000000..71b77a58e5 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/WeakReferenceHelpers.cs @@ -0,0 +1,59 @@ +// 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.Diagnostics; +using System.Threading; + +namespace Microsoft.AspNetCore.Cryptography +{ + internal static class WeakReferenceHelpers + { + public static T GetSharedInstance(ref WeakReference weakReference, Func factory) + where T : class, IDisposable + { + // First, see if the WR already exists and points to a live object. + WeakReference existingWeakRef = Volatile.Read(ref weakReference); + T newTarget = null; + WeakReference newWeakRef = null; + + while (true) + { + if (existingWeakRef != null) + { + T existingTarget; + if (weakReference.TryGetTarget(out existingTarget)) + { + // If we created a new target on a previous iteration of the loop but we + // weren't able to store the target into the desired location, dispose of it now. + newTarget?.Dispose(); + return existingTarget; + } + } + + // If the existing WR didn't point anywhere useful and this is our + // first iteration through the loop, create the new target and WR now. + if (newTarget == null) + { + newTarget = factory(); + Debug.Assert(newTarget != null); + newWeakRef = new WeakReference(newTarget); + } + Debug.Assert(newWeakRef != null); + + // Try replacing the existing WR with our newly-created one. + WeakReference currentWeakRef = Interlocked.CompareExchange(ref weakReference, newWeakRef, existingWeakRef); + if (ReferenceEquals(currentWeakRef, existingWeakRef)) + { + // success, 'weakReference' now points to our newly-created WR + return newTarget; + } + + // If we got to this point, somebody beat us to creating a new WR. + // We'll loop around and check it for validity. + Debug.Assert(currentWeakRef != null); + existingWeakRef = currentWeakRef; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/baseline.netcore.json b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/baseline.netcore.json new file mode 100644 index 0000000000..01daa339ee --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.Internal/baseline.netcore.json @@ -0,0 +1,4 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.Cryptography.Internal, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [] +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/KeyDerivation.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/KeyDerivation.cs new file mode 100644 index 0000000000..67ff1ca420 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/KeyDerivation.cs @@ -0,0 +1,56 @@ +// 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 Microsoft.AspNetCore.Cryptography.KeyDerivation.PBKDF2; + +namespace Microsoft.AspNetCore.Cryptography.KeyDerivation +{ + /// + /// Provides algorithms for performing key derivation. + /// + public static class KeyDerivation + { + /// + /// Performs key derivation using the PBKDF2 algorithm. + /// + /// The password from which to derive the key. + /// The salt to be used during the key derivation process. + /// The pseudo-random function to be used in the key derivation process. + /// The number of iterations of the pseudo-random function to apply + /// during the key derivation process. + /// The desired length (in bytes) of the derived key. + /// The derived key. + /// + /// The PBKDF2 algorithm is specified in RFC 2898. + /// + public static byte[] Pbkdf2(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested) + { + if (password == null) + { + throw new ArgumentNullException(nameof(password)); + } + + if (salt == null) + { + throw new ArgumentNullException(nameof(salt)); + } + + // parameter checking + if (prf < KeyDerivationPrf.HMACSHA1 || prf > KeyDerivationPrf.HMACSHA512) + { + throw new ArgumentOutOfRangeException(nameof(prf)); + } + if (iterationCount <= 0) + { + throw new ArgumentOutOfRangeException(nameof(iterationCount)); + } + if (numBytesRequested <= 0) + { + throw new ArgumentOutOfRangeException(nameof(numBytesRequested)); + } + + return Pbkdf2Util.Pbkdf2Provider.DeriveKey(password, salt, prf, iterationCount, numBytesRequested); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/KeyDerivationPrf.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/KeyDerivationPrf.cs new file mode 100644 index 0000000000..57e740f04b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/KeyDerivationPrf.cs @@ -0,0 +1,26 @@ +// 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. + +namespace Microsoft.AspNetCore.Cryptography.KeyDerivation +{ + /// + /// Specifies the PRF which should be used for the key derivation algorithm. + /// + public enum KeyDerivationPrf + { + /// + /// The HMAC algorithm (RFC 2104) using the SHA-1 hash function (FIPS 180-4). + /// + HMACSHA1, + + /// + /// The HMAC algorithm (RFC 2104) using the SHA-256 hash function (FIPS 180-4). + /// + HMACSHA256, + + /// + /// The HMAC algorithm (RFC 2104) using the SHA-512 hash function (FIPS 180-4). + /// + HMACSHA512, + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj new file mode 100644 index 0000000000..04dec66482 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj @@ -0,0 +1,15 @@ + + + + ASP.NET Core utilities for key derivation. + netstandard2.0;netcoreapp3.0 + true + true + aspnetcore;dataprotection + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/IPbkdf2Provider.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/IPbkdf2Provider.cs new file mode 100644 index 0000000000..8be8a5e809 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/IPbkdf2Provider.cs @@ -0,0 +1,15 @@ +// 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; + +namespace Microsoft.AspNetCore.Cryptography.KeyDerivation.PBKDF2 +{ + /// + /// Internal interface used for abstracting away the PBKDF2 implementation since the implementation is OS-specific. + /// + internal interface IPbkdf2Provider + { + byte[] DeriveKey(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/ManagedPbkdf2Provider.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/ManagedPbkdf2Provider.cs new file mode 100644 index 0000000000..bf81ae65c5 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/ManagedPbkdf2Provider.cs @@ -0,0 +1,103 @@ +// 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.Diagnostics; +using System.Security.Cryptography; +using System.Text; + +namespace Microsoft.AspNetCore.Cryptography.KeyDerivation.PBKDF2 +{ + /// + /// A PBKDF2 provider which utilizes the managed hash algorithm classes as PRFs. + /// This isn't the preferred provider since the implementation is slow, but it is provided as a fallback. + /// + internal sealed class ManagedPbkdf2Provider : IPbkdf2Provider + { + public byte[] DeriveKey(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested) + { + Debug.Assert(password != null); + Debug.Assert(salt != null); + Debug.Assert(iterationCount > 0); + Debug.Assert(numBytesRequested > 0); + + // PBKDF2 is defined in NIST SP800-132, Sec. 5.3. + // http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf + + byte[] retVal = new byte[numBytesRequested]; + int numBytesWritten = 0; + int numBytesRemaining = numBytesRequested; + + // For each block index, U_0 := Salt || block_index + byte[] saltWithBlockIndex = new byte[checked(salt.Length + sizeof(uint))]; + Buffer.BlockCopy(salt, 0, saltWithBlockIndex, 0, salt.Length); + + using (var hashAlgorithm = PrfToManagedHmacAlgorithm(prf, password)) + { + for (uint blockIndex = 1; numBytesRemaining > 0; blockIndex++) + { + // write the block index out as big-endian + saltWithBlockIndex[saltWithBlockIndex.Length - 4] = (byte)(blockIndex >> 24); + saltWithBlockIndex[saltWithBlockIndex.Length - 3] = (byte)(blockIndex >> 16); + saltWithBlockIndex[saltWithBlockIndex.Length - 2] = (byte)(blockIndex >> 8); + saltWithBlockIndex[saltWithBlockIndex.Length - 1] = (byte)blockIndex; + + // U_1 = PRF(U_0) = PRF(Salt || block_index) + // T_blockIndex = U_1 + byte[] U_iter = hashAlgorithm.ComputeHash(saltWithBlockIndex); // this is U_1 + byte[] T_blockIndex = U_iter; + + for (int iter = 1; iter < iterationCount; iter++) + { + U_iter = hashAlgorithm.ComputeHash(U_iter); + XorBuffers(src: U_iter, dest: T_blockIndex); + // At this point, the 'U_iter' variable actually contains U_{iter+1} (due to indexing differences). + } + + // At this point, we're done iterating on this block, so copy the transformed block into retVal. + int numBytesToCopy = Math.Min(numBytesRemaining, T_blockIndex.Length); + Buffer.BlockCopy(T_blockIndex, 0, retVal, numBytesWritten, numBytesToCopy); + numBytesWritten += numBytesToCopy; + numBytesRemaining -= numBytesToCopy; + } + } + + // retVal := T_1 || T_2 || ... || T_n, where T_n may be truncated to meet the desired output length + return retVal; + } + + private static KeyedHashAlgorithm PrfToManagedHmacAlgorithm(KeyDerivationPrf prf, string password) + { + byte[] passwordBytes = Encoding.UTF8.GetBytes(password); + try + { + switch (prf) + { + case KeyDerivationPrf.HMACSHA1: + return new HMACSHA1(passwordBytes); + case KeyDerivationPrf.HMACSHA256: + return new HMACSHA256(passwordBytes); + case KeyDerivationPrf.HMACSHA512: + return new HMACSHA512(passwordBytes); + default: + throw CryptoUtil.Fail("Unrecognized PRF."); + } + } + finally + { + // The HMAC ctor makes a duplicate of this key; we clear original buffer to limit exposure to the GC. + Array.Clear(passwordBytes, 0, passwordBytes.Length); + } + } + + private static void XorBuffers(byte[] src, byte[] dest) + { + // Note: dest buffer is mutated. + Debug.Assert(src.Length == dest.Length); + for (int i = 0; i < src.Length; i++) + { + dest[i] ^= src[i]; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/NetCorePbkdf2Provider.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/NetCorePbkdf2Provider.cs new file mode 100644 index 0000000000..a8ce1772eb --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/NetCorePbkdf2Provider.cs @@ -0,0 +1,71 @@ +// 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. + +#if NETCOREAPP3_0 +// Rfc2898DeriveBytes in .NET Standard 2.0 only supports SHA1 + +using System; +using System.Diagnostics; +using System.Security.Cryptography; +using System.Text; + +namespace Microsoft.AspNetCore.Cryptography.KeyDerivation.PBKDF2 +{ + /// + /// Implements Pbkdf2 using . + /// + internal sealed class NetCorePbkdf2Provider : IPbkdf2Provider + { + private static readonly ManagedPbkdf2Provider _fallbackProvider = new ManagedPbkdf2Provider(); + + public byte[] DeriveKey(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested) + { + Debug.Assert(password != null); + Debug.Assert(salt != null); + Debug.Assert(iterationCount > 0); + Debug.Assert(numBytesRequested > 0); + + if (salt.Length < 8) + { + // Rfc2898DeriveBytes enforces the 8 byte recommendation. + // To maintain compatibility, we call into ManagedPbkdf2Provider for salts shorter than 8 bytes + // because we can't use Rfc2898DeriveBytes with this salt. + return _fallbackProvider.DeriveKey(password, salt, prf, iterationCount, numBytesRequested); + } + else + { + return DeriveKeyImpl(password, salt, prf, iterationCount, numBytesRequested); + } + } + + private static byte[] DeriveKeyImpl(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested) + { + HashAlgorithmName algorithmName; + switch (prf) + { + case KeyDerivationPrf.HMACSHA1: + algorithmName = HashAlgorithmName.SHA1; + break; + case KeyDerivationPrf.HMACSHA256: + algorithmName = HashAlgorithmName.SHA256; + break; + case KeyDerivationPrf.HMACSHA512: + algorithmName = HashAlgorithmName.SHA512; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + var passwordBytes = Encoding.UTF8.GetBytes(password); + using (var rfc = new Rfc2898DeriveBytes(passwordBytes, salt, iterationCount, algorithmName)) + { + return rfc.GetBytes(numBytesRequested); + } + } + } +} + +#elif NETSTANDARD2_0 +#else +#error Update target frameworks +#endif diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/Pbkdf2Util.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/Pbkdf2Util.cs new file mode 100644 index 0000000000..d8139c92f7 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/Pbkdf2Util.cs @@ -0,0 +1,46 @@ +// 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 Microsoft.AspNetCore.Cryptography.Cng; + +namespace Microsoft.AspNetCore.Cryptography.KeyDerivation.PBKDF2 +{ + /// + /// Internal base class used for abstracting away the PBKDF2 implementation since the implementation is OS-specific. + /// + internal static class Pbkdf2Util + { + public static readonly IPbkdf2Provider Pbkdf2Provider = GetPbkdf2Provider(); + + private static IPbkdf2Provider GetPbkdf2Provider() + { + // In priority order, our three implementations are Win8, Win7, and "other". + if (OSVersionUtil.IsWindows8OrLater()) + { + // fastest implementation + return new Win8Pbkdf2Provider(); + } + else if (OSVersionUtil.IsWindows()) + { + // acceptable implementation + return new Win7Pbkdf2Provider(); + } +#if NETCOREAPP3_0 + else + { + // fastest implementation on .NET Core for Linux/macOS. + // Not supported on .NET Framework + return new NetCorePbkdf2Provider(); + } +#elif NETSTANDARD2_0 + else + { + // slowest implementation + return new ManagedPbkdf2Provider(); + } +#else +#error Update target frameworks +#endif + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/Win7Pbkdf2Provider.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/Win7Pbkdf2Provider.cs new file mode 100644 index 0000000000..4c359b80f4 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/Win7Pbkdf2Provider.cs @@ -0,0 +1,100 @@ +// 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.Diagnostics; +using System.Text; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography.KeyDerivation.PBKDF2 +{ + /// + /// A PBKDF2 provider which utilizes the Win7 API BCryptDeriveKeyPBKDF2. + /// + internal unsafe sealed class Win7Pbkdf2Provider : IPbkdf2Provider + { + public byte[] DeriveKey(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested) + { + Debug.Assert(password != null); + Debug.Assert(salt != null); + Debug.Assert(iterationCount > 0); + Debug.Assert(numBytesRequested > 0); + + byte dummy; // CLR doesn't like pinning zero-length buffers, so this provides a valid memory address when working with zero-length buffers + + // Don't dispose of this algorithm instance; it is cached and reused! + var algHandle = PrfToCachedCngAlgorithmInstance(prf); + + // Convert password string to bytes. + // Allocate on the stack whenever we can to save allocations. + int cbPasswordBuffer = Encoding.UTF8.GetMaxByteCount(password.Length); + fixed (byte* pbHeapAllocatedPasswordBuffer = (cbPasswordBuffer > Constants.MAX_STACKALLOC_BYTES) ? new byte[cbPasswordBuffer] : null) + { + byte* pbPasswordBuffer = pbHeapAllocatedPasswordBuffer; + if (pbPasswordBuffer == null) + { + if (cbPasswordBuffer == 0) + { + pbPasswordBuffer = &dummy; + } + else + { + byte* pbStackAllocPasswordBuffer = stackalloc byte[cbPasswordBuffer]; // will be released when the frame unwinds + pbPasswordBuffer = pbStackAllocPasswordBuffer; + } + } + + try + { + int cbPasswordBufferUsed; // we're not filling the entire buffer, just a partial buffer + fixed (char* pszPassword = password) + { + cbPasswordBufferUsed = Encoding.UTF8.GetBytes(pszPassword, password.Length, pbPasswordBuffer, cbPasswordBuffer); + } + + fixed (byte* pbHeapAllocatedSalt = salt) + { + byte* pbSalt = (pbHeapAllocatedSalt != null) ? pbHeapAllocatedSalt : &dummy; + + byte[] retVal = new byte[numBytesRequested]; + fixed (byte* pbRetVal = retVal) + { + int ntstatus = UnsafeNativeMethods.BCryptDeriveKeyPBKDF2( + hPrf: algHandle, + pbPassword: pbPasswordBuffer, + cbPassword: (uint)cbPasswordBufferUsed, + pbSalt: pbSalt, + cbSalt: (uint)salt.Length, + cIterations: (ulong)iterationCount, + pbDerivedKey: pbRetVal, + cbDerivedKey: (uint)retVal.Length, + dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + } + return retVal; + } + } + finally + { + UnsafeBufferUtil.SecureZeroMemory(pbPasswordBuffer, cbPasswordBuffer); + } + } + } + + private static BCryptAlgorithmHandle PrfToCachedCngAlgorithmInstance(KeyDerivationPrf prf) + { + switch (prf) + { + case KeyDerivationPrf.HMACSHA1: + return CachedAlgorithmHandles.HMAC_SHA1; + case KeyDerivationPrf.HMACSHA256: + return CachedAlgorithmHandles.HMAC_SHA256; + case KeyDerivationPrf.HMACSHA512: + return CachedAlgorithmHandles.HMAC_SHA512; + default: + throw CryptoUtil.Fail("Unrecognized PRF."); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/Win8Pbkdf2Provider.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/Win8Pbkdf2Provider.cs new file mode 100644 index 0000000000..296e85b7dd --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/PBKDF2/Win8Pbkdf2Provider.cs @@ -0,0 +1,211 @@ +// 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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Text; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; + +namespace Microsoft.AspNetCore.Cryptography.KeyDerivation.PBKDF2 +{ + /// + /// A PBKDF2 provider which utilizes the Win8 API BCryptKeyDerivation. + /// + internal unsafe sealed class Win8Pbkdf2Provider : IPbkdf2Provider + { + public byte[] DeriveKey(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested) + { + Debug.Assert(password != null); + Debug.Assert(salt != null); + Debug.Assert(iterationCount > 0); + Debug.Assert(numBytesRequested > 0); + + string algorithmName = PrfToCngAlgorithmId(prf); + fixed (byte* pbHeapAllocatedSalt = salt) + { + byte dummy; // CLR doesn't like pinning zero-length buffers, so this provides a valid memory address when working with zero-length buffers + byte* pbSalt = (pbHeapAllocatedSalt != null) ? pbHeapAllocatedSalt : &dummy; + + byte[] retVal = new byte[numBytesRequested]; + using (BCryptKeyHandle keyHandle = PasswordToPbkdfKeyHandle(password, CachedAlgorithmHandles.PBKDF2, prf)) + { + fixed (byte* pbRetVal = retVal) + { + DeriveKeyCore(keyHandle, algorithmName, pbSalt, (uint)salt.Length, (ulong)iterationCount, pbRetVal, (uint)retVal.Length); + } + return retVal; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint GetTotalByteLengthIncludingNullTerminator(string input) + { + if (input == null) + { + // degenerate case + return 0; + } + else + { + uint numChars = (uint)input.Length + 1U; // no overflow check necessary since Length is signed + return checked(numChars * sizeof(char)); + } + } + + private static BCryptKeyHandle PasswordToPbkdfKeyHandle(string password, BCryptAlgorithmHandle pbkdf2AlgHandle, KeyDerivationPrf prf) + { + byte dummy; // CLR doesn't like pinning zero-length buffers, so this provides a valid memory address when working with zero-length buffers + + // Convert password string to bytes. + // Allocate on the stack whenever we can to save allocations. + int cbPasswordBuffer = Encoding.UTF8.GetMaxByteCount(password.Length); + fixed (byte* pbHeapAllocatedPasswordBuffer = (cbPasswordBuffer > Constants.MAX_STACKALLOC_BYTES) ? new byte[cbPasswordBuffer] : null) + { + byte* pbPasswordBuffer = pbHeapAllocatedPasswordBuffer; + if (pbPasswordBuffer == null) + { + if (cbPasswordBuffer == 0) + { + pbPasswordBuffer = &dummy; + } + else + { + byte* pbStackAllocPasswordBuffer = stackalloc byte[cbPasswordBuffer]; // will be released when the frame unwinds + pbPasswordBuffer = pbStackAllocPasswordBuffer; + } + } + + try + { + int cbPasswordBufferUsed; // we're not filling the entire buffer, just a partial buffer + fixed (char* pszPassword = password) + { + cbPasswordBufferUsed = Encoding.UTF8.GetBytes(pszPassword, password.Length, pbPasswordBuffer, cbPasswordBuffer); + } + + return PasswordToPbkdfKeyHandleStep2(pbkdf2AlgHandle, pbPasswordBuffer, (uint)cbPasswordBufferUsed, prf); + } + finally + { + UnsafeBufferUtil.SecureZeroMemory(pbPasswordBuffer, cbPasswordBuffer); + } + } + } + + private static BCryptKeyHandle PasswordToPbkdfKeyHandleStep2(BCryptAlgorithmHandle pbkdf2AlgHandle, byte* pbPassword, uint cbPassword, KeyDerivationPrf prf) + { + const uint PBKDF2_MAX_KEYLENGTH_IN_BYTES = 2048; // GetSupportedKeyLengths() on a Win8 box; value should never be lowered in any future version of Windows + if (cbPassword <= PBKDF2_MAX_KEYLENGTH_IN_BYTES) + { + // Common case: the password is small enough to be consumed directly by the PBKDF2 algorithm. + return pbkdf2AlgHandle.GenerateSymmetricKey(pbPassword, cbPassword); + } + else + { + // Rare case: password is very long; we must hash manually. + // PBKDF2 uses the PRFs in HMAC mode, and when the HMAC input key exceeds the hash function's + // block length the key is hashed and run back through the key initialization function. + + BCryptAlgorithmHandle prfAlgorithmHandle; // cached; don't dispose + switch (prf) + { + case KeyDerivationPrf.HMACSHA1: + prfAlgorithmHandle = CachedAlgorithmHandles.SHA1; + break; + case KeyDerivationPrf.HMACSHA256: + prfAlgorithmHandle = CachedAlgorithmHandles.SHA256; + break; + case KeyDerivationPrf.HMACSHA512: + prfAlgorithmHandle = CachedAlgorithmHandles.SHA512; + break; + default: + throw CryptoUtil.Fail("Unrecognized PRF."); + } + + // Final sanity check: don't hash the password if the HMAC key initialization function wouldn't have done it for us. + if (cbPassword <= prfAlgorithmHandle.GetHashBlockLength() /* in bytes */) + { + return pbkdf2AlgHandle.GenerateSymmetricKey(pbPassword, cbPassword); + } + + // Hash the password and use the hash as input to PBKDF2. + uint cbPasswordDigest = prfAlgorithmHandle.GetHashDigestLength(); + CryptoUtil.Assert(cbPasswordDigest > 0, "cbPasswordDigest > 0"); + fixed (byte* pbPasswordDigest = new byte[cbPasswordDigest]) + { + try + { + using (var hashHandle = prfAlgorithmHandle.CreateHash()) + { + hashHandle.HashData(pbPassword, cbPassword, pbPasswordDigest, cbPasswordDigest); + } + return pbkdf2AlgHandle.GenerateSymmetricKey(pbPasswordDigest, cbPasswordDigest); + } + finally + { + UnsafeBufferUtil.SecureZeroMemory(pbPasswordDigest, cbPasswordDigest); + } + } + } + } + + private static void DeriveKeyCore(BCryptKeyHandle pbkdf2KeyHandle, string hashAlgorithm, byte* pbSalt, uint cbSalt, ulong iterCount, byte* pbDerivedBytes, uint cbDerivedBytes) + { + // First, build the buffers necessary to pass (hash alg, salt, iter count) into the KDF + BCryptBuffer* pBuffers = stackalloc BCryptBuffer[3]; + + pBuffers[0].BufferType = BCryptKeyDerivationBufferType.KDF_ITERATION_COUNT; + pBuffers[0].pvBuffer = (IntPtr)(&iterCount); + pBuffers[0].cbBuffer = sizeof(ulong); + + pBuffers[1].BufferType = BCryptKeyDerivationBufferType.KDF_SALT; + pBuffers[1].pvBuffer = (IntPtr)pbSalt; + pBuffers[1].cbBuffer = cbSalt; + + fixed (char* pszHashAlgorithm = hashAlgorithm) + { + pBuffers[2].BufferType = BCryptKeyDerivationBufferType.KDF_HASH_ALGORITHM; + pBuffers[2].pvBuffer = (IntPtr)pszHashAlgorithm; + pBuffers[2].cbBuffer = GetTotalByteLengthIncludingNullTerminator(hashAlgorithm); + + // Add the header which points to the buffers + BCryptBufferDesc bufferDesc = default(BCryptBufferDesc); + BCryptBufferDesc.Initialize(ref bufferDesc); + bufferDesc.cBuffers = 3; + bufferDesc.pBuffers = pBuffers; + + // Finally, import the KDK into the KDF algorithm, then invoke the KDF + uint numBytesDerived; + int ntstatus = UnsafeNativeMethods.BCryptKeyDerivation( + hKey: pbkdf2KeyHandle, + pParameterList: &bufferDesc, + pbDerivedKey: pbDerivedBytes, + cbDerivedKey: cbDerivedBytes, + pcbResult: out numBytesDerived, + dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + + // Final sanity checks before returning control to caller. + CryptoUtil.Assert(numBytesDerived == cbDerivedBytes, "numBytesDerived == cbDerivedBytes"); + } + } + + private static string PrfToCngAlgorithmId(KeyDerivationPrf prf) + { + switch (prf) + { + case KeyDerivationPrf.HMACSHA1: + return Constants.BCRYPT_SHA1_ALGORITHM; + case KeyDerivationPrf.HMACSHA256: + return Constants.BCRYPT_SHA256_ALGORITHM; + case KeyDerivationPrf.HMACSHA512: + return Constants.BCRYPT_SHA512_ALGORITHM; + default: + throw CryptoUtil.Fail("Unrecognized PRF."); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/Properties/AssemblyInfo.cs b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..2ca6553c5d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// 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.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Cryptography.KeyDerivation.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/baseline.netcore.json b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/baseline.netcore.json new file mode 100644 index 0000000000..ceddb40cc2 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.Cryptography.KeyDerivation/baseline.netcore.json @@ -0,0 +1,78 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.Cryptography.KeyDerivation, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.AspNetCore.Cryptography.KeyDerivation.KeyDerivation", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Pbkdf2", + "Parameters": [ + { + "Name": "password", + "Type": "System.String" + }, + { + "Name": "salt", + "Type": "System.Byte[]" + }, + { + "Name": "prf", + "Type": "Microsoft.AspNetCore.Cryptography.KeyDerivation.KeyDerivationPrf" + }, + { + "Name": "iterationCount", + "Type": "System.Int32" + }, + { + "Name": "numBytesRequested", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Byte[]", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Cryptography.KeyDerivation.KeyDerivationPrf", + "Visibility": "Public", + "Kind": "Enumeration", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Field", + "Name": "HMACSHA1", + "Parameters": [], + "GenericParameter": [], + "Literal": "0" + }, + { + "Kind": "Field", + "Name": "HMACSHA256", + "Parameters": [], + "GenericParameter": [], + "Literal": "1" + }, + { + "Kind": "Field", + "Name": "HMACSHA512", + "Parameters": [], + "GenericParameter": [], + "Literal": "2" + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/CryptoUtil.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/CryptoUtil.cs new file mode 100644 index 0000000000..e3e361a3a8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/CryptoUtil.cs @@ -0,0 +1,33 @@ +// 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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Security.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal static class CryptoUtil + { + // This isn't a typical Debug.Fail; an error always occurs, even in retail builds. + // This method doesn't return, but since the CLR doesn't allow specifying a 'never' + // return type, we mimic it by specifying our return type as Exception. That way + // callers can write 'throw Fail(...);' to make the C# compiler happy, as the + // throw keyword is implicitly of type O. + [MethodImpl(MethodImplOptions.NoInlining)] + public static Exception Fail(string message) + { + Debug.Fail(message); + throw new CryptographicException("Assertion failed: " + message); + } + + // Allows callers to write "var x = Method() ?? Fail(message);" as a convenience to guard + // against a method returning null unexpectedly. + [MethodImpl(MethodImplOptions.NoInlining)] + public static T Fail(string message) where T : class + { + throw Fail(message); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/DataProtectionCommonExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/DataProtectionCommonExtensions.cs new file mode 100644 index 0000000000..f4fd8801ae --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/DataProtectionCommonExtensions.cs @@ -0,0 +1,244 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using Microsoft.AspNetCore.DataProtection.Abstractions; +using Microsoft.Extensions.Internal; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Helpful extension methods for data protection APIs. + /// + public static class DataProtectionCommonExtensions + { + /// + /// Creates an given a list of purposes. + /// + /// The from which to generate the purpose chain. + /// The list of purposes which contribute to the purpose chain. This list must + /// contain at least one element, and it may not contain null elements. + /// An tied to the provided purpose chain. + /// + /// This is a convenience method which chains together several calls to + /// . See that method's + /// documentation for more information. + /// + public static IDataProtector CreateProtector(this IDataProtectionProvider provider, IEnumerable purposes) + { + if (provider == null) + { + throw new ArgumentNullException(nameof(provider)); + } + + if (purposes == null) + { + throw new ArgumentNullException(nameof(purposes)); + } + + bool collectionIsEmpty = true; + IDataProtectionProvider retVal = provider; + foreach (string purpose in purposes) + { + if (purpose == null) + { + throw new ArgumentException(Resources.DataProtectionExtensions_NullPurposesCollection, nameof(purposes)); + } + retVal = retVal.CreateProtector(purpose) ?? CryptoUtil.Fail("CreateProtector returned null."); + collectionIsEmpty = false; + } + + if (collectionIsEmpty) + { + throw new ArgumentException(Resources.DataProtectionExtensions_NullPurposesCollection, nameof(purposes)); + } + + Debug.Assert(retVal is IDataProtector); // CreateProtector is supposed to return an instance of this interface + return (IDataProtector)retVal; + } + + /// + /// Creates an given a list of purposes. + /// + /// The from which to generate the purpose chain. + /// The primary purpose used to create the . + /// An optional list of secondary purposes which contribute to the purpose chain. + /// If this list is provided it cannot contain null elements. + /// An tied to the provided purpose chain. + /// + /// This is a convenience method which chains together several calls to + /// . See that method's + /// documentation for more information. + /// + public static IDataProtector CreateProtector(this IDataProtectionProvider provider, string purpose, params string[] subPurposes) + { + if (provider == null) + { + throw new ArgumentNullException(nameof(provider)); + } + + if (purpose == null) + { + throw new ArgumentNullException(nameof(purpose)); + } + + // The method signature isn't simply CreateProtector(this IDataProtectionProvider, params string[] purposes) + // because we don't want the code provider.CreateProtector() [parameterless] to inadvertently compile. + // The actual signature for this method forces at least one purpose to be provided at the call site. + + IDataProtector protector = provider.CreateProtector(purpose); + if (subPurposes != null && subPurposes.Length > 0) + { + protector = protector?.CreateProtector((IEnumerable)subPurposes); + } + return protector ?? CryptoUtil.Fail("CreateProtector returned null."); + } + + /// + /// Retrieves an from an . + /// + /// The service provider from which to retrieve the . + /// An . This method is guaranteed never to return null. + /// If no service exists in . + public static IDataProtectionProvider GetDataProtectionProvider(this IServiceProvider services) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + // We have our own implementation of GetRequiredService since we don't want to + // take a dependency on DependencyInjection.Interfaces. + IDataProtectionProvider provider = (IDataProtectionProvider)services.GetService(typeof(IDataProtectionProvider)); + if (provider == null) + { + throw new InvalidOperationException(Resources.FormatDataProtectionExtensions_NoService(typeof(IDataProtectionProvider).FullName)); + } + return provider; + } + + /// + /// Retrieves an from an given a list of purposes. + /// + /// An which contains the + /// from which to generate the purpose chain. + /// The list of purposes which contribute to the purpose chain. This list must + /// contain at least one element, and it may not contain null elements. + /// An tied to the provided purpose chain. + /// + /// This is a convenience method which calls + /// then . See those methods' + /// documentation for more information. + /// + public static IDataProtector GetDataProtector(this IServiceProvider services, IEnumerable purposes) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + if (purposes == null) + { + throw new ArgumentNullException(nameof(purposes)); + } + + return services.GetDataProtectionProvider().CreateProtector(purposes); + } + + /// + /// Retrieves an from an given a list of purposes. + /// + /// An which contains the + /// from which to generate the purpose chain. + /// The primary purpose used to create the . + /// An optional list of secondary purposes which contribute to the purpose chain. + /// If this list is provided it cannot contain null elements. + /// An tied to the provided purpose chain. + /// + /// This is a convenience method which calls + /// then . See those methods' + /// documentation for more information. + /// + public static IDataProtector GetDataProtector(this IServiceProvider services, string purpose, params string[] subPurposes) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + if (purpose == null) + { + throw new ArgumentNullException(nameof(purpose)); + } + + return services.GetDataProtectionProvider().CreateProtector(purpose, subPurposes); + } + + /// + /// Cryptographically protects a piece of plaintext data. + /// + /// The data protector to use for this operation. + /// The plaintext data to protect. + /// The protected form of the plaintext data. + public static string Protect(this IDataProtector protector, string plaintext) + { + if (protector == null) + { + throw new ArgumentNullException(nameof(protector)); + } + + if (plaintext == null) + { + throw new ArgumentNullException(nameof(plaintext)); + } + + try + { + byte[] plaintextAsBytes = EncodingUtil.SecureUtf8Encoding.GetBytes(plaintext); + byte[] protectedDataAsBytes = protector.Protect(plaintextAsBytes); + return WebEncoders.Base64UrlEncode(protectedDataAsBytes); + } + catch (Exception ex) when (ex.RequiresHomogenization()) + { + // Homogenize exceptions to CryptographicException + throw Error.CryptCommon_GenericError(ex); + } + } + + /// + /// Cryptographically unprotects a piece of protected data. + /// + /// The data protector to use for this operation. + /// The protected data to unprotect. + /// The plaintext form of the protected data. + /// + /// Thrown if is invalid or malformed. + /// + public static string Unprotect(this IDataProtector protector, string protectedData) + { + if (protector == null) + { + throw new ArgumentNullException(nameof(protector)); + } + + if (protectedData == null) + { + throw new ArgumentNullException(nameof(protectedData)); + } + + try + { + byte[] protectedDataAsBytes = WebEncoders.Base64UrlDecode(protectedData); + byte[] plaintextAsBytes = protector.Unprotect(protectedDataAsBytes); + return EncodingUtil.SecureUtf8Encoding.GetString(plaintextAsBytes); + } + catch (Exception ex) when (ex.RequiresHomogenization()) + { + // Homogenize exceptions to CryptographicException + throw Error.CryptCommon_GenericError(ex); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Error.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Error.cs new file mode 100644 index 0000000000..18b93c0ac7 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Error.cs @@ -0,0 +1,23 @@ +// 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.Security.Cryptography; +using Microsoft.AspNetCore.DataProtection.Abstractions; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal static class Error + { + public static CryptographicException CryptCommon_GenericError(Exception inner = null) + { + return new CryptographicException(Resources.CryptCommon_GenericError, inner); + } + + public static CryptographicException CryptCommon_PayloadInvalid() + { + string message = Resources.CryptCommon_PayloadInvalid; + return new CryptographicException(message); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/IDataProtectionProvider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/IDataProtectionProvider.cs new file mode 100644 index 0000000000..02f772724b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/IDataProtectionProvider.cs @@ -0,0 +1,26 @@ +// 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. + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// An interface that can be used to create instances. + /// + public interface IDataProtectionProvider + { + /// + /// Creates an given a purpose. + /// + /// + /// The purpose to be assigned to the newly-created . + /// + /// An IDataProtector tied to the provided purpose. + /// + /// The parameter must be unique for the intended use case; two + /// different instances created with two different + /// values will not be able to decipher each other's payloads. The parameter + /// value is not intended to be kept secret. + /// + IDataProtector CreateProtector(string purpose); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/IDataProtector.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/IDataProtector.cs new file mode 100644 index 0000000000..1d9c8c3946 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/IDataProtector.cs @@ -0,0 +1,28 @@ +// 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. + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// An interface that can provide data protection services. + /// + public interface IDataProtector : IDataProtectionProvider + { + /// + /// Cryptographically protects a piece of plaintext data. + /// + /// The plaintext data to protect. + /// The protected form of the plaintext data. + byte[] Protect(byte[] plaintext); + + /// + /// Cryptographically unprotects a piece of protected data. + /// + /// The protected data to unprotect. + /// The plaintext form of the protected data. + /// + /// Thrown if the protected data is invalid or malformed. + /// + byte[] Unprotect(byte[] protectedData); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Infrastructure/IApplicationDiscriminator.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Infrastructure/IApplicationDiscriminator.cs new file mode 100644 index 0000000000..d8c3af376f --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Infrastructure/IApplicationDiscriminator.cs @@ -0,0 +1,25 @@ +// 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.ComponentModel; + +namespace Microsoft.AspNetCore.DataProtection.Infrastructure +{ + /// + /// Provides information used to discriminate applications. + /// + /// + /// This type supports the data protection system and is not intended to be used + /// by consumers. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public interface IApplicationDiscriminator + { + /// + /// An identifier that uniquely discriminates this application from all other + /// applications on the machine. + /// + string Discriminator { get; } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Microsoft.AspNetCore.DataProtection.Abstractions.csproj b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Microsoft.AspNetCore.DataProtection.Abstractions.csproj new file mode 100644 index 0000000000..24bd9f5fb6 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Microsoft.AspNetCore.DataProtection.Abstractions.csproj @@ -0,0 +1,21 @@ + + + + ASP.NET Core data protection abstractions. +Commonly used types: +Microsoft.AspNetCore.DataProtection.IDataProtectionProvider +Microsoft.AspNetCore.DataProtection.IDataProtector + netstandard2.0 + true + aspnetcore;dataprotection + + + + + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Properties/AssemblyInfo.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..838462a81d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// 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.Runtime.CompilerServices; + +// for unit testing +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.DataProtection.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Properties/Resources.Designer.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7f8422cf6b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Properties/Resources.Designer.cs @@ -0,0 +1,86 @@ +// +namespace Microsoft.AspNetCore.DataProtection.Abstractions +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.AspNetCore.DataProtection.Abstractions.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// The payload was invalid. + /// + internal static string CryptCommon_PayloadInvalid + { + get => GetString("CryptCommon_PayloadInvalid"); + } + + /// + /// The payload was invalid. + /// + internal static string FormatCryptCommon_PayloadInvalid() + => GetString("CryptCommon_PayloadInvalid"); + + /// + /// The purposes collection cannot be null or empty and cannot contain null elements. + /// + internal static string DataProtectionExtensions_NullPurposesCollection + { + get => GetString("DataProtectionExtensions_NullPurposesCollection"); + } + + /// + /// The purposes collection cannot be null or empty and cannot contain null elements. + /// + internal static string FormatDataProtectionExtensions_NullPurposesCollection() + => GetString("DataProtectionExtensions_NullPurposesCollection"); + + /// + /// An error occurred during a cryptographic operation. + /// + internal static string CryptCommon_GenericError + { + get => GetString("CryptCommon_GenericError"); + } + + /// + /// An error occurred during a cryptographic operation. + /// + internal static string FormatCryptCommon_GenericError() + => GetString("CryptCommon_GenericError"); + + /// + /// No service for type '{0}' has been registered. + /// + internal static string DataProtectionExtensions_NoService + { + get => GetString("DataProtectionExtensions_NoService"); + } + + /// + /// No service for type '{0}' has been registered. + /// + internal static string FormatDataProtectionExtensions_NoService(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("DataProtectionExtensions_NoService"), p0); + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Resources.resx b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Resources.resx new file mode 100644 index 0000000000..daa9e2cbd9 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/Resources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The payload was invalid. + + + The purposes collection cannot be null or empty and cannot contain null elements. + + + An error occurred during a cryptographic operation. + + + No service for type '{0}' has been registered. + + \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/baseline.netcore.json b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/baseline.netcore.json new file mode 100644 index 0000000000..eb6e5030fe --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Abstractions/baseline.netcore.json @@ -0,0 +1,231 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.DataProtection.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CreateProtector", + "Parameters": [ + { + "Name": "provider", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider" + }, + { + "Name": "purposes", + "Type": "System.Collections.Generic.IEnumerable" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtector", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CreateProtector", + "Parameters": [ + { + "Name": "provider", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider" + }, + { + "Name": "purpose", + "Type": "System.String" + }, + { + "Name": "subPurposes", + "Type": "System.String[]", + "IsParams": true + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtector", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetDataProtectionProvider", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetDataProtector", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + }, + { + "Name": "purposes", + "Type": "System.Collections.Generic.IEnumerable" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtector", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetDataProtector", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + }, + { + "Name": "purpose", + "Type": "System.String" + }, + { + "Name": "subPurposes", + "Type": "System.String[]", + "IsParams": true + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtector", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Protect", + "Parameters": [ + { + "Name": "protector", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtector" + }, + { + "Name": "plaintext", + "Type": "System.String" + } + ], + "ReturnType": "System.String", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Unprotect", + "Parameters": [ + { + "Name": "protector", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtector" + }, + { + "Name": "protectedData", + "Type": "System.String" + } + ], + "ReturnType": "System.String", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CreateProtector", + "Parameters": [ + { + "Name": "purpose", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtector", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.IDataProtector", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Protect", + "Parameters": [ + { + "Name": "plaintext", + "Type": "System.Byte[]" + } + ], + "ReturnType": "System.Byte[]", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Unprotect", + "Parameters": [ + { + "Name": "protectedData", + "Type": "System.Byte[]" + } + ], + "ReturnType": "System.Byte[]", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.Infrastructure.IApplicationDiscriminator", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Discriminator", + "Parameters": [], + "ReturnType": "System.String", + "GenericParameter": [] + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/AzureDataProtectionBuilderExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/AzureDataProtectionBuilderExtensions.cs new file mode 100644 index 0000000000..0701220b4b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/AzureDataProtectionBuilderExtensions.cs @@ -0,0 +1,118 @@ +// 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.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; +using Microsoft.AspNetCore.DataProtection.AzureKeyVault; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Azure.KeyVault; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Clients.ActiveDirectory; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Contains Azure KeyVault-specific extension methods for modifying a . + /// + public static class AzureDataProtectionBuilderExtensions + { + /// + /// Configures the data protection system to protect keys with specified key in Azure KeyVault. + /// + /// The builder instance to modify. + /// The Azure KeyVault key identifier used for key encryption. + /// The application client id. + /// + /// The value . + public static IDataProtectionBuilder ProtectKeysWithAzureKeyVault(this IDataProtectionBuilder builder, string keyIdentifier, string clientId, X509Certificate2 certificate) + { + if (string.IsNullOrEmpty(clientId)) + { + throw new ArgumentException(nameof(clientId)); + } + if (certificate == null) + { + throw new ArgumentNullException(nameof(certificate)); + } + + KeyVaultClient.AuthenticationCallback callback = + (authority, resource, scope) => GetTokenFromClientCertificate(authority, resource, clientId, certificate); + + return ProtectKeysWithAzureKeyVault(builder, new KeyVaultClient(callback), keyIdentifier); + } + + private static async Task GetTokenFromClientCertificate(string authority, string resource, string clientId, X509Certificate2 certificate) + { + var authContext = new AuthenticationContext(authority); + var result = await authContext.AcquireTokenAsync(resource, new ClientAssertionCertificate(clientId, certificate)); + return result.AccessToken; + } + + /// + /// Configures the data protection system to protect keys with specified key in Azure KeyVault. + /// + /// The builder instance to modify. + /// The Azure KeyVault key identifier used for key encryption. + /// The application client id. + /// The client secret to use for authentication. + /// The value . + public static IDataProtectionBuilder ProtectKeysWithAzureKeyVault(this IDataProtectionBuilder builder, string keyIdentifier, string clientId, string clientSecret) + { + if (string.IsNullOrEmpty(clientId)) + { + throw new ArgumentNullException(nameof(clientId)); + } + if (string.IsNullOrEmpty(clientSecret)) + { + throw new ArgumentNullException(nameof(clientSecret)); + } + + KeyVaultClient.AuthenticationCallback callback = + (authority, resource, scope) => GetTokenFromClientSecret(authority, resource, clientId, clientSecret); + + return ProtectKeysWithAzureKeyVault(builder, new KeyVaultClient(callback), keyIdentifier); + } + + private static async Task GetTokenFromClientSecret(string authority, string resource, string clientId, string clientSecret) + { + var authContext = new AuthenticationContext(authority); + var clientCred = new ClientCredential(clientId, clientSecret); + var result = await authContext.AcquireTokenAsync(resource, clientCred); + return result.AccessToken; + } + + /// + /// Configures the data protection system to protect keys with specified key in Azure KeyVault. + /// + /// The builder instance to modify. + /// The to use for KeyVault access. + /// The Azure KeyVault key identifier used for key encryption. + /// The value . + public static IDataProtectionBuilder ProtectKeysWithAzureKeyVault(this IDataProtectionBuilder builder, KeyVaultClient client, string keyIdentifier) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + if (client == null) + { + throw new ArgumentNullException(nameof(client)); + } + if (string.IsNullOrEmpty(keyIdentifier)) + { + throw new ArgumentException(nameof(keyIdentifier)); + } + + var vaultClientWrapper = new KeyVaultClientWrapper(client); + + builder.Services.AddSingleton(vaultClientWrapper); + builder.Services.Configure(options => + { + options.XmlEncryptor = new AzureKeyVaultXmlEncryptor(vaultClientWrapper, keyIdentifier); + }); + + return builder; + } + } +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/AzureKeyVaultXmlDecryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/AzureKeyVaultXmlDecryptor.cs new file mode 100644 index 0000000000..b9942fa84f --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/AzureKeyVaultXmlDecryptor.cs @@ -0,0 +1,52 @@ +// 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.IO; +using System.Threading.Tasks; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.DataProtection.AzureKeyVault +{ + internal class AzureKeyVaultXmlDecryptor: IXmlDecryptor + { + private readonly IKeyVaultWrappingClient _client; + + public AzureKeyVaultXmlDecryptor(IServiceProvider serviceProvider) + { + _client = serviceProvider.GetService(); + } + + public XElement Decrypt(XElement encryptedElement) + { + return DecryptAsync(encryptedElement).GetAwaiter().GetResult(); + } + + private async Task DecryptAsync(XElement encryptedElement) + { + var kid = (string)encryptedElement.Element("kid"); + var symmetricKey = Convert.FromBase64String((string)encryptedElement.Element("key")); + var symmetricIV = Convert.FromBase64String((string)encryptedElement.Element("iv")); + + var encryptedValue = Convert.FromBase64String((string)encryptedElement.Element("value")); + + var result = await _client.UnwrapKeyAsync(kid, AzureKeyVaultXmlEncryptor.DefaultKeyEncryption, symmetricKey); + + byte[] decryptedValue; + using (var symmetricAlgorithm = AzureKeyVaultXmlEncryptor.DefaultSymmetricAlgorithmFactory()) + { + using (var decryptor = symmetricAlgorithm.CreateDecryptor(result.Result, symmetricIV)) + { + decryptedValue = decryptor.TransformFinalBlock(encryptedValue, 0, encryptedValue.Length); + } + } + + using (var memoryStream = new MemoryStream(decryptedValue)) + { + return XElement.Load(memoryStream); + } + } + } +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/AzureKeyVaultXmlEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/AzureKeyVaultXmlEncryptor.cs new file mode 100644 index 0000000000..3451c3ded2 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/AzureKeyVaultXmlEncryptor.cs @@ -0,0 +1,77 @@ +// 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.IO; +using System.Security.Cryptography; +using System.Threading.Tasks; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.Azure.KeyVault.WebKey; + +namespace Microsoft.AspNetCore.DataProtection.AzureKeyVault +{ + internal class AzureKeyVaultXmlEncryptor : IXmlEncryptor + { + internal static string DefaultKeyEncryption = JsonWebKeyEncryptionAlgorithm.RSAOAEP; + internal static Func DefaultSymmetricAlgorithmFactory = Aes.Create; + + private readonly RandomNumberGenerator _randomNumberGenerator; + private readonly IKeyVaultWrappingClient _client; + private readonly string _keyId; + + public AzureKeyVaultXmlEncryptor(IKeyVaultWrappingClient client, string keyId) + : this(client, keyId, RandomNumberGenerator.Create()) + { + } + + internal AzureKeyVaultXmlEncryptor(IKeyVaultWrappingClient client, string keyId, RandomNumberGenerator randomNumberGenerator) + { + _client = client; + _keyId = keyId; + _randomNumberGenerator = randomNumberGenerator; + } + + public EncryptedXmlInfo Encrypt(XElement plaintextElement) + { + return EncryptAsync(plaintextElement).GetAwaiter().GetResult(); + } + + private async Task EncryptAsync(XElement plaintextElement) + { + byte[] value; + using (var memoryStream = new MemoryStream()) + { + plaintextElement.Save(memoryStream, SaveOptions.DisableFormatting); + value = memoryStream.ToArray(); + } + + using (var symmetricAlgorithm = DefaultSymmetricAlgorithmFactory()) + { + var symmetricBlockSize = symmetricAlgorithm.BlockSize / 8; + var symmetricKey = new byte[symmetricBlockSize]; + var symmetricIV = new byte[symmetricBlockSize]; + _randomNumberGenerator.GetBytes(symmetricKey); + _randomNumberGenerator.GetBytes(symmetricIV); + + byte[] encryptedValue; + using (var encryptor = symmetricAlgorithm.CreateEncryptor(symmetricKey, symmetricIV)) + { + encryptedValue = encryptor.TransformFinalBlock(value, 0, value.Length); + } + + var wrappedKey = await _client.WrapKeyAsync(_keyId, DefaultKeyEncryption, symmetricKey); + + var element = new XElement("encryptedKey", + new XComment(" This key is encrypted with Azure KeyVault. "), + new XElement("kid", wrappedKey.Kid), + new XElement("key", Convert.ToBase64String(wrappedKey.Result)), + new XElement("iv", Convert.ToBase64String(symmetricIV)), + new XElement("value", Convert.ToBase64String(encryptedValue))); + + return new EncryptedXmlInfo(element, typeof(AzureKeyVaultXmlDecryptor)); + } + + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/IKeyVaultWrappingClient.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/IKeyVaultWrappingClient.cs new file mode 100644 index 0000000000..2347460dc3 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/IKeyVaultWrappingClient.cs @@ -0,0 +1,14 @@ +// 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.Threading.Tasks; +using Microsoft.Azure.KeyVault.Models; + +namespace Microsoft.AspNetCore.DataProtection.AzureKeyVault +{ + internal interface IKeyVaultWrappingClient + { + Task UnwrapKeyAsync(string keyIdentifier, string algorithm, byte[] cipherText); + Task WrapKeyAsync(string keyIdentifier, string algorithm, byte[] cipherText); + } +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/KeyVaultClientWrapper.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/KeyVaultClientWrapper.cs new file mode 100644 index 0000000000..82fe0649e2 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/KeyVaultClientWrapper.cs @@ -0,0 +1,29 @@ +// 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.Threading.Tasks; +using Microsoft.Azure.KeyVault; +using Microsoft.Azure.KeyVault.Models; + +namespace Microsoft.AspNetCore.DataProtection.AzureKeyVault +{ + internal class KeyVaultClientWrapper : IKeyVaultWrappingClient + { + private readonly KeyVaultClient _client; + + public KeyVaultClientWrapper(KeyVaultClient client) + { + _client = client; + } + + public Task UnwrapKeyAsync(string keyIdentifier, string algorithm, byte[] cipherText) + { + return _client.UnwrapKeyAsync(keyIdentifier, algorithm, cipherText); + } + + public Task WrapKeyAsync(string keyIdentifier, string algorithm, byte[] cipherText) + { + return _client.WrapKeyAsync(keyIdentifier, algorithm, cipherText); + } + } +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj new file mode 100644 index 0000000000..0c7b084a2a --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj @@ -0,0 +1,20 @@ + + + + Microsoft Azure KeyVault key encryption support. + netstandard2.0 + true + aspnetcore;dataprotection;azure;keyvault + false + + + + + + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/Properties/AssemblyInfo.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..c23a3410b7 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault/Properties/AssemblyInfo.cs @@ -0,0 +1,9 @@ +// 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.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/AzureBlobXmlRepository.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/AzureBlobXmlRepository.cs new file mode 100644 index 0000000000..e39babaa31 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/AzureBlobXmlRepository.cs @@ -0,0 +1,297 @@ +// 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.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.Repositories; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Blob; + +namespace Microsoft.AspNetCore.DataProtection.AzureStorage +{ + /// + /// An which is backed by Azure Blob Storage. + /// + /// + /// Instances of this type are thread-safe. + /// + public sealed class AzureBlobXmlRepository : IXmlRepository + { + private const int ConflictMaxRetries = 5; + private static readonly TimeSpan ConflictBackoffPeriod = TimeSpan.FromMilliseconds(200); + + private static readonly XName RepositoryElementName = "repository"; + + private readonly Func _blobRefFactory; + private readonly Random _random; + private BlobData _cachedBlobData; + + /// + /// Creates a new instance of the . + /// + /// A factory which can create + /// instances. The factory must be thread-safe for invocation by multiple + /// concurrent threads, and each invocation must return a new object. + public AzureBlobXmlRepository(Func blobRefFactory) + { + if (blobRefFactory == null) + { + throw new ArgumentNullException(nameof(blobRefFactory)); + } + + _blobRefFactory = blobRefFactory; + _random = new Random(); + } + + /// + public IReadOnlyCollection GetAllElements() + { + var blobRef = CreateFreshBlobRef(); + + // Shunt the work onto a ThreadPool thread so that it's independent of any + // existing sync context or other potentially deadlock-causing items. + + var elements = Task.Run(() => GetAllElementsAsync(blobRef)).GetAwaiter().GetResult(); + return new ReadOnlyCollection(elements); + } + + /// + public void StoreElement(XElement element, string friendlyName) + { + if (element == null) + { + throw new ArgumentNullException(nameof(element)); + } + + var blobRef = CreateFreshBlobRef(); + + // Shunt the work onto a ThreadPool thread so that it's independent of any + // existing sync context or other potentially deadlock-causing items. + + Task.Run(() => StoreElementAsync(blobRef, element)).GetAwaiter().GetResult(); + } + + private XDocument CreateDocumentFromBlob(byte[] blob) + { + using (var memoryStream = new MemoryStream(blob)) + { + var xmlReaderSettings = new XmlReaderSettings() + { + DtdProcessing = DtdProcessing.Prohibit, IgnoreProcessingInstructions = true + }; + + using (var xmlReader = XmlReader.Create(memoryStream, xmlReaderSettings)) + { + return XDocument.Load(xmlReader); + } + } + } + + private ICloudBlob CreateFreshBlobRef() + { + // ICloudBlob instances aren't thread-safe, so we need to make sure we're working + // with a fresh instance that won't be mutated by another thread. + + var blobRef = _blobRefFactory(); + if (blobRef == null) + { + throw new InvalidOperationException("The ICloudBlob factory method returned null."); + } + + return blobRef; + } + + private async Task> GetAllElementsAsync(ICloudBlob blobRef) + { + var data = await GetLatestDataAsync(blobRef); + + if (data == null) + { + // no data in blob storage + return new XElement[0]; + } + + // The document will look like this: + // + // + // + // + // ... + // + // + // We want to return the first-level child elements to our caller. + + var doc = CreateDocumentFromBlob(data.BlobContents); + return doc.Root.Elements().ToList(); + } + + private async Task GetLatestDataAsync(ICloudBlob blobRef) + { + // Set the appropriate AccessCondition based on what we believe the latest + // file contents to be, then make the request. + + var latestCachedData = Volatile.Read(ref _cachedBlobData); // local ref so field isn't mutated under our feet + var accessCondition = (latestCachedData != null) + ? AccessCondition.GenerateIfNoneMatchCondition(latestCachedData.ETag) + : null; + + try + { + using (var memoryStream = new MemoryStream()) + { + await blobRef.DownloadToStreamAsync( + target: memoryStream, + accessCondition: accessCondition, + options: null, + operationContext: null); + + // At this point, our original cache either didn't exist or was outdated. + // We'll update it now and return the updated value; + + latestCachedData = new BlobData() + { + BlobContents = memoryStream.ToArray(), + ETag = blobRef.Properties.ETag + }; + + } + Volatile.Write(ref _cachedBlobData, latestCachedData); + } + catch (StorageException ex) when (ex.RequestInformation.HttpStatusCode == 304) + { + // 304 Not Modified + // Thrown when we already have the latest cached data. + // This isn't an error; we'll return our cached copy of the data. + } + catch (StorageException ex) when (ex.RequestInformation.HttpStatusCode == 404) + { + // 404 Not Found + // Thrown when no file exists in storage. + // This isn't an error; we'll delete our cached copy of data. + + latestCachedData = null; + Volatile.Write(ref _cachedBlobData, latestCachedData); + } + + return latestCachedData; + } + + private int GetRandomizedBackoffPeriod() + { + // returns a TimeSpan in the range [0.8, 1.0) * ConflictBackoffPeriod + // not used for crypto purposes + var multiplier = 0.8 + (_random.NextDouble() * 0.2); + return (int) (multiplier * ConflictBackoffPeriod.Ticks); + } + + private async Task StoreElementAsync(ICloudBlob blobRef, XElement element) + { + // holds the last error in case we need to rethrow it + ExceptionDispatchInfo lastError = null; + + for (var i = 0; i < ConflictMaxRetries; i++) + { + if (i > 1) + { + // If multiple conflicts occurred, wait a small period of time before retrying + // the operation so that other writers can make forward progress. + await Task.Delay(GetRandomizedBackoffPeriod()); + } + + if (i > 0) + { + // If at least one conflict occurred, make sure we have an up-to-date + // view of the blob contents. + await GetLatestDataAsync(blobRef); + } + + // Merge the new element into the document. If no document exists, + // create a new default document and inject this element into it. + + var latestData = Volatile.Read(ref _cachedBlobData); + var doc = (latestData != null) + ? CreateDocumentFromBlob(latestData.BlobContents) + : new XDocument(new XElement(RepositoryElementName)); + doc.Root.Add(element); + + // Turn this document back into a byte[]. + + var serializedDoc = new MemoryStream(); + doc.Save(serializedDoc, SaveOptions.DisableFormatting); + + // Generate the appropriate precondition header based on whether or not + // we believe data already exists in storage. + + AccessCondition accessCondition; + if (latestData != null) + { + accessCondition = AccessCondition.GenerateIfMatchCondition(blobRef.Properties.ETag); + } + else + { + accessCondition = AccessCondition.GenerateIfNotExistsCondition(); + blobRef.Properties.ContentType = "application/xml; charset=utf-8"; // set content type on first write + } + + try + { + // Send the request up to the server. + + var serializedDocAsByteArray = serializedDoc.ToArray(); + + await blobRef.UploadFromByteArrayAsync( + buffer: serializedDocAsByteArray, + index: 0, + count: serializedDocAsByteArray.Length, + accessCondition: accessCondition, + options: null, + operationContext: null); + + // If we got this far, success! + // We can update the cached view of the remote contents. + + Volatile.Write(ref _cachedBlobData, new BlobData() + { + BlobContents = serializedDocAsByteArray, + ETag = blobRef.Properties.ETag // was updated by Upload routine + }); + + return; + } + catch (StorageException ex) + when (ex.RequestInformation.HttpStatusCode == 409 || ex.RequestInformation.HttpStatusCode == 412) + { + // 409 Conflict + // This error is rare but can be thrown in very special circumstances, + // such as if the blob in the process of being created. We treat it + // as equivalent to 412 for the purposes of retry logic. + + // 412 Precondition Failed + // We'll get this error if another writer updated the repository and we + // have an outdated view of its contents. If this occurs, we'll just + // refresh our view of the remote contents and try again up to the max + // retry limit. + + lastError = ExceptionDispatchInfo.Capture(ex); + } + } + + // if we got this far, something went awry + lastError.Throw(); + } + + private sealed class BlobData + { + internal byte[] BlobContents; + internal string ETag; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/AzureDataProtectionBuilderExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/AzureDataProtectionBuilderExtensions.cs new file mode 100644 index 0000000000..8ff62929e2 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/AzureDataProtectionBuilderExtensions.cs @@ -0,0 +1,175 @@ +// 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 Microsoft.AspNetCore.DataProtection.AzureStorage; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Auth; +using Microsoft.WindowsAzure.Storage.Blob; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Contains Azure-specific extension methods for modifying a + /// . + /// + public static class AzureDataProtectionBuilderExtensions + { + /// + /// Configures the data protection system to persist keys to the specified path + /// in Azure Blob Storage. + /// + /// The builder instance to modify. + /// The which + /// should be utilized. + /// A relative path where the key file should be + /// stored, generally specified as "/containerName/[subDir/]keys.xml". + /// The value . + /// + /// The container referenced by must already exist. + /// + public static IDataProtectionBuilder PersistKeysToAzureBlobStorage(this IDataProtectionBuilder builder, CloudStorageAccount storageAccount, string relativePath) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + if (storageAccount == null) + { + throw new ArgumentNullException(nameof(storageAccount)); + } + if (relativePath == null) + { + throw new ArgumentNullException(nameof(relativePath)); + } + + // Simply concatenate the root storage endpoint with the relative path, + // which includes the container name and blob name. + + var uriBuilder = new UriBuilder(storageAccount.BlobEndpoint); + uriBuilder.Path = uriBuilder.Path.TrimEnd('/') + "/" + relativePath.TrimStart('/'); + + // We can create a CloudBlockBlob from the storage URI and the creds. + + var blobAbsoluteUri = uriBuilder.Uri; + var credentials = storageAccount.Credentials; + + return PersistKeystoAzureBlobStorageInternal(builder, () => new CloudBlockBlob(blobAbsoluteUri, credentials)); + } + + /// + /// Configures the data protection system to persist keys to the specified path + /// in Azure Blob Storage. + /// + /// The builder instance to modify. + /// The full URI where the key file should be stored. + /// The URI must contain the SAS token as a query string parameter. + /// The value . + /// + /// The container referenced by must already exist. + /// + public static IDataProtectionBuilder PersistKeysToAzureBlobStorage(this IDataProtectionBuilder builder, Uri blobUri) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + if (blobUri == null) + { + throw new ArgumentNullException(nameof(blobUri)); + } + + var uriBuilder = new UriBuilder(blobUri); + + // The SAS token is present in the query string. + + if (string.IsNullOrEmpty(uriBuilder.Query)) + { + throw new ArgumentException( + message: "URI does not have a SAS token in the query string.", + paramName: nameof(blobUri)); + } + + var credentials = new StorageCredentials(uriBuilder.Query); + uriBuilder.Query = null; // no longer needed + var blobAbsoluteUri = uriBuilder.Uri; + + return PersistKeystoAzureBlobStorageInternal(builder, () => new CloudBlockBlob(blobAbsoluteUri, credentials)); + } + + /// + /// Configures the data protection system to persist keys to the specified path + /// in Azure Blob Storage. + /// + /// The builder instance to modify. + /// The where the + /// key file should be stored. + /// The value . + /// + /// The container referenced by must already exist. + /// + public static IDataProtectionBuilder PersistKeysToAzureBlobStorage(this IDataProtectionBuilder builder, CloudBlockBlob blobReference) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + if (blobReference == null) + { + throw new ArgumentNullException(nameof(blobReference)); + } + + // We're basically just going to make a copy of this blob. + // Use (container, blobName) instead of (storageuri, creds) since the container + // is tied to an existing service client, which contains user-settable defaults + // like retry policy and secondary connection URIs. + + var container = blobReference.Container; + var blobName = blobReference.Name; + + return PersistKeystoAzureBlobStorageInternal(builder, () => container.GetBlockBlobReference(blobName)); + } + + /// + /// Configures the data protection system to persist keys to the specified path + /// in Azure Blob Storage. + /// + /// The builder instance to modify. + /// The in which the + /// key file should be stored. + /// The name of the key file, generally specified + /// as "[subdir/]keys.xml" + /// The value . + /// + /// The container referenced by must already exist. + /// + public static IDataProtectionBuilder PersistKeysToAzureBlobStorage(this IDataProtectionBuilder builder, CloudBlobContainer container, string blobName) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + if (container == null) + { + throw new ArgumentNullException(nameof(container)); + } + if (blobName == null) + { + throw new ArgumentNullException(nameof(blobName)); + } + return PersistKeystoAzureBlobStorageInternal(builder, () => container.GetBlockBlobReference(blobName)); + } + + // important: the Func passed into this method must return a new instance with each call + private static IDataProtectionBuilder PersistKeystoAzureBlobStorageInternal(IDataProtectionBuilder builder, Func blobRefFactory) + { + builder.Services.Configure(options => + { + options.XmlRepository = new AzureBlobXmlRepository(blobRefFactory); + }); + return builder; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/Microsoft.AspNetCore.DataProtection.AzureStorage.csproj b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/Microsoft.AspNetCore.DataProtection.AzureStorage.csproj new file mode 100644 index 0000000000..ceb83f3925 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/Microsoft.AspNetCore.DataProtection.AzureStorage.csproj @@ -0,0 +1,19 @@ + + + + Microsoft Azure Blob storrage support as key store. + netstandard2.0 + true + true + aspnetcore;dataprotection;azure;blob + + + + + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/baseline.netcore.json b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/baseline.netcore.json new file mode 100644 index 0000000000..09e208bfef --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.AzureStorage/baseline.netcore.json @@ -0,0 +1,156 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.DataProtection.AzureStorage, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.AspNetCore.DataProtection.AzureDataProtectionBuilderExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "PersistKeysToAzureBlobStorage", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "storageAccount", + "Type": "Microsoft.WindowsAzure.Storage.CloudStorageAccount" + }, + { + "Name": "relativePath", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "PersistKeysToAzureBlobStorage", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "blobUri", + "Type": "System.Uri" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "PersistKeysToAzureBlobStorage", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "blobReference", + "Type": "Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "PersistKeysToAzureBlobStorage", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "container", + "Type": "Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer" + }, + { + "Name": "blobName", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AzureStorage.AzureBlobXmlRepository", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository" + ], + "Members": [ + { + "Kind": "Method", + "Name": "GetAllElements", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyCollection", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "StoreElement", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + }, + { + "Name": "friendlyName", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "blobRefFactory", + "Type": "System.Func" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/DataProtectionKey.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/DataProtectionKey.cs new file mode 100644 index 0000000000..c236d5cb89 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/DataProtectionKey.cs @@ -0,0 +1,26 @@ +// 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. + +namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore +{ + /// + /// Code first model used by . + /// + public class DataProtectionKey + { + /// + /// The entity identifier of the . + /// + public int Id { get; set; } + + /// + /// The friendly name of the . + /// + public string FriendlyName { get; set; } + + /// + /// The XML representation of the . + /// + public string Xml { get; set; } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/EntityFrameworkCoreDataProtectionExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/EntityFrameworkCoreDataProtectionExtensions.cs new file mode 100644 index 0000000000..ff24b58eb9 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/EntityFrameworkCoreDataProtectionExtensions.cs @@ -0,0 +1,39 @@ +// 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 Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Extension method class for configuring instances of + /// + public static class EntityFrameworkCoreDataProtectionExtensions + { + /// + /// Configures the data protection system to persist keys to an EntityFrameworkCore datastore + /// + /// The instance to modify. + /// The value . + public static IDataProtectionBuilder PersistKeysToDbContext(this IDataProtectionBuilder builder) + where TContext : DbContext, IDataProtectionKeyContext + { + builder.Services.AddSingleton>(services => + { + var loggerFactory = services.GetService() ?? NullLoggerFactory.Instance; + return new ConfigureOptions(options => + { + options.XmlRepository = new EntityFrameworkCoreXmlRepository(services, loggerFactory); + }); + }); + + return builder; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/EntityFrameworkCoreXmlRepository.cs new file mode 100644 index 0000000000..62250cf3ef --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/EntityFrameworkCoreXmlRepository.cs @@ -0,0 +1,81 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore +{ + /// + /// An backed by an EntityFrameworkCore datastore. + /// + public class EntityFrameworkCoreXmlRepository : IXmlRepository + where TContext : DbContext, IDataProtectionKeyContext + { + private readonly IServiceProvider _services; + private readonly ILogger _logger; + + /// + /// Creates a new instance of the . + /// + /// + /// The . + public EntityFrameworkCoreXmlRepository(IServiceProvider services, ILoggerFactory loggerFactory) + { + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + + _logger = loggerFactory.CreateLogger>(); + _services = services ?? throw new ArgumentNullException(nameof(services)); + } + + /// + public virtual IReadOnlyCollection GetAllElements() + { + using (var scope = _services.CreateScope()) + { + var context = scope.ServiceProvider.GetRequiredService(); + return context.DataProtectionKeys.AsNoTracking().Select(key => TryParseKeyXml(key.Xml)).ToList().AsReadOnly(); + } + } + + /// + public void StoreElement(XElement element, string friendlyName) + { + using (var scope = _services.CreateScope()) + { + var context = scope.ServiceProvider.GetRequiredService(); + var newKey = new DataProtectionKey() + { + FriendlyName = friendlyName, + Xml = element.ToString(SaveOptions.DisableFormatting) + }; + + context.DataProtectionKeys.Add(newKey); + _logger.LogSavingKeyToDbContext(friendlyName, typeof(TContext).Name); + context.SaveChanges(); + } + } + + private XElement TryParseKeyXml(string xml) + { + try + { + return XElement.Parse(xml); + } + catch (Exception e) + { + _logger?.LogExceptionWhileParsingKeyXml(xml, e); + return null; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/IDataProtectionKeyContext.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/IDataProtectionKeyContext.cs new file mode 100644 index 0000000000..39998d2a79 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/IDataProtectionKeyContext.cs @@ -0,0 +1,18 @@ +// 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 Microsoft.EntityFrameworkCore; + +namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore +{ + /// + /// Interface used to store instances of in a + /// + public interface IDataProtectionKeyContext + { + /// + /// A collection of + /// + DbSet DataProtectionKeys { get; } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/LoggingExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/LoggingExtensions.cs new file mode 100644 index 0000000000..d0aeb09271 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/LoggingExtensions.cs @@ -0,0 +1,31 @@ +// 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; + +namespace Microsoft.Extensions.Logging +{ + internal static class LoggingExtensions + { + private static readonly Action _anExceptionOccurredWhileParsingKeyXml; + private static readonly Action _savingKeyToDbContext; + + static LoggingExtensions() + { + _anExceptionOccurredWhileParsingKeyXml = LoggerMessage.Define( + eventId: 1, + logLevel: LogLevel.Warning, + formatString: "An exception occurred while parsing the key xml '{Xml}'."); + _savingKeyToDbContext = LoggerMessage.Define( + eventId: 2, + logLevel: LogLevel.Debug, + formatString: "Saving key '{FriendlyName}' to '{DbContext}'."); + } + + public static void LogExceptionWhileParsingKeyXml(this ILogger logger, string keyXml, Exception exception) + => _anExceptionOccurredWhileParsingKeyXml(logger, keyXml, exception); + + public static void LogSavingKeyToDbContext(this ILogger logger, string friendlyName, string contextName) + => _savingKeyToDbContext(logger, friendlyName, contextName, null); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj new file mode 100644 index 0000000000..e1715d94f2 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj @@ -0,0 +1,23 @@ + + + + Support for storing keys using Entity Framework Core. + netstandard2.0 + true + true + aspnetcore;dataprotection;entityframeworkcore + + + + + + + + + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/baseline.netcore.json b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/baseline.netcore.json new file mode 100644 index 0000000000..9a9a7ebc1c --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore/baseline.netcore.json @@ -0,0 +1,203 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCoreDataProtectionExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "PersistKeysToDbContext", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TContext", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [ + "Microsoft.EntityFrameworkCore.DbContext", + "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.IDataProtectionKeyContext" + ] + } + ] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Id", + "Parameters": [], + "ReturnType": "System.Int32", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Id", + "Parameters": [ + { + "Name": "value", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_FriendlyName", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_FriendlyName", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Xml", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Xml", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository" + ], + "Members": [ + { + "Kind": "Method", + "Name": "GetAllElements", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyCollection", + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "StoreElement", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + }, + { + "Name": "friendlyName", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + }, + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [ + { + "ParameterName": "TContext", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [ + "Microsoft.EntityFrameworkCore.DbContext", + "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.IDataProtectionKeyContext" + ] + } + ] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.IDataProtectionKeyContext", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_DataProtectionKeys", + "Parameters": [], + "ReturnType": "Microsoft.EntityFrameworkCore.DbSet", + "GenericParameter": [] + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/BitHelpers.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/BitHelpers.cs new file mode 100644 index 0000000000..eb2063fbd8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/BitHelpers.cs @@ -0,0 +1,42 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal static class BitHelpers + { + /// + /// Reads an unsigned 64-bit integer from + /// starting at offset . Data is read big-endian. + /// + public static ulong ReadUInt64(byte[] buffer, int offset) + { + return (((ulong)buffer[offset + 0]) << 56) + | (((ulong)buffer[offset + 1]) << 48) + | (((ulong)buffer[offset + 2]) << 40) + | (((ulong)buffer[offset + 3]) << 32) + | (((ulong)buffer[offset + 4]) << 24) + | (((ulong)buffer[offset + 5]) << 16) + | (((ulong)buffer[offset + 6]) << 8) + | (ulong)buffer[offset + 7]; + } + + /// + /// Writes an unsigned 64-bit integer to starting at + /// offset . Data is written big-endian. + /// + public static void WriteUInt64(byte[] buffer, int offset, ulong value) + { + buffer[offset + 0] = (byte)(value >> 56); + buffer[offset + 1] = (byte)(value >> 48); + buffer[offset + 2] = (byte)(value >> 40); + buffer[offset + 3] = (byte)(value >> 32); + buffer[offset + 4] = (byte)(value >> 24); + buffer[offset + 5] = (byte)(value >> 16); + buffer[offset + 6] = (byte)(value >> 8); + buffer[offset + 7] = (byte)(value); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/DataProtectionAdvancedExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/DataProtectionAdvancedExtensions.cs new file mode 100644 index 0000000000..6e4c2aabac --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/DataProtectionAdvancedExtensions.cs @@ -0,0 +1,169 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Helpful extension methods for data protection APIs. + /// + public static class DataProtectionAdvancedExtensions + { + /// + /// Cryptographically protects a piece of plaintext data, expiring the data after + /// the specified amount of time has elapsed. + /// + /// The protector to use. + /// The plaintext data to protect. + /// The amount of time after which the payload should no longer be unprotectable. + /// The protected form of the plaintext data. + public static byte[] Protect(this ITimeLimitedDataProtector protector, byte[] plaintext, TimeSpan lifetime) + { + if (protector == null) + { + throw new ArgumentNullException(nameof(protector)); + } + + if (plaintext == null) + { + throw new ArgumentNullException(nameof(plaintext)); + } + + return protector.Protect(plaintext, DateTimeOffset.UtcNow + lifetime); + } + + /// + /// Cryptographically protects a piece of plaintext data, expiring the data at + /// the chosen time. + /// + /// The protector to use. + /// The plaintext data to protect. + /// The time when this payload should expire. + /// The protected form of the plaintext data. + public static string Protect(this ITimeLimitedDataProtector protector, string plaintext, DateTimeOffset expiration) + { + if (protector == null) + { + throw new ArgumentNullException(nameof(protector)); + } + + if (plaintext == null) + { + throw new ArgumentNullException(nameof(plaintext)); + } + + var wrappingProtector = new TimeLimitedWrappingProtector(protector) { Expiration = expiration }; + return wrappingProtector.Protect(plaintext); + } + + /// + /// Cryptographically protects a piece of plaintext data, expiring the data after + /// the specified amount of time has elapsed. + /// + /// The protector to use. + /// The plaintext data to protect. + /// The amount of time after which the payload should no longer be unprotectable. + /// The protected form of the plaintext data. + public static string Protect(this ITimeLimitedDataProtector protector, string plaintext, TimeSpan lifetime) + { + if (protector == null) + { + throw new ArgumentNullException(nameof(protector)); + } + + if (plaintext == null) + { + throw new ArgumentNullException(nameof(plaintext)); + } + + return Protect(protector, plaintext, DateTimeOffset.Now + lifetime); + } + + /// + /// Converts an into an + /// so that payloads can be protected with a finite lifetime. + /// + /// The to convert to a time-limited protector. + /// An . + public static ITimeLimitedDataProtector ToTimeLimitedDataProtector(this IDataProtector protector) + { + if (protector == null) + { + throw new ArgumentNullException(nameof(protector)); + } + + return (protector as ITimeLimitedDataProtector) ?? new TimeLimitedDataProtector(protector); + } + + /// + /// Cryptographically unprotects a piece of protected data. + /// + /// The protector to use. + /// The protected data to unprotect. + /// An 'out' parameter which upon a successful unprotect + /// operation receives the expiration date of the payload. + /// The plaintext form of the protected data. + /// + /// Thrown if is invalid, malformed, or expired. + /// + public static string Unprotect(this ITimeLimitedDataProtector protector, string protectedData, out DateTimeOffset expiration) + { + if (protector == null) + { + throw new ArgumentNullException(nameof(protector)); + } + + if (protectedData == null) + { + throw new ArgumentNullException(nameof(protectedData)); + } + + var wrappingProtector = new TimeLimitedWrappingProtector(protector); + string retVal = wrappingProtector.Unprotect(protectedData); + expiration = wrappingProtector.Expiration; + return retVal; + } + + private sealed class TimeLimitedWrappingProtector : IDataProtector + { + public DateTimeOffset Expiration; + private readonly ITimeLimitedDataProtector _innerProtector; + + public TimeLimitedWrappingProtector(ITimeLimitedDataProtector innerProtector) + { + _innerProtector = innerProtector; + } + + public IDataProtector CreateProtector(string purpose) + { + if (purpose == null) + { + throw new ArgumentNullException(nameof(purpose)); + } + + throw new NotImplementedException(); + } + + public byte[] Protect(byte[] plaintext) + { + if (plaintext == null) + { + throw new ArgumentNullException(nameof(plaintext)); + } + + return _innerProtector.Protect(plaintext, Expiration); + } + + public byte[] Unprotect(byte[] protectedData) + { + if (protectedData == null) + { + throw new ArgumentNullException(nameof(protectedData)); + } + + return _innerProtector.Unprotect(protectedData, out Expiration); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/DataProtectionProvider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/DataProtectionProvider.cs new file mode 100644 index 0000000000..cc82fe9ef8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/DataProtectionProvider.cs @@ -0,0 +1,178 @@ +// 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.IO; +using System.Security.Cryptography.X509Certificates; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Contains factory methods for creating an where keys are stored + /// at a particular location on the file system. + /// + /// Use these methods when not using dependency injection to provide the service to the application. + public static class DataProtectionProvider + { + /// + /// Creates a that store keys in a location based on + /// the platform and operating system. + /// + /// An identifier that uniquely discriminates this application from all other + /// applications on the machine. + public static IDataProtectionProvider Create(string applicationName) + { + if (string.IsNullOrEmpty(applicationName)) + { + throw new ArgumentNullException(nameof(applicationName)); + } + + return CreateProvider( + keyDirectory: null, + setupAction: builder => { builder.SetApplicationName(applicationName); }, + certificate: null); + } + + /// + /// Creates an given a location at which to store keys. + /// + /// The in which keys should be stored. This may + /// represent a directory on a local disk or a UNC share. + public static IDataProtectionProvider Create(DirectoryInfo keyDirectory) + { + if (keyDirectory == null) + { + throw new ArgumentNullException(nameof(keyDirectory)); + } + + return CreateProvider(keyDirectory, setupAction: builder => { }, certificate: null); + } + + /// + /// Creates an given a location at which to store keys and an + /// optional configuration callback. + /// + /// The in which keys should be stored. This may + /// represent a directory on a local disk or a UNC share. + /// An optional callback which provides further configuration of the data protection + /// system. See for more information. + public static IDataProtectionProvider Create( + DirectoryInfo keyDirectory, + Action setupAction) + { + if (keyDirectory == null) + { + throw new ArgumentNullException(nameof(keyDirectory)); + } + if (setupAction == null) + { + throw new ArgumentNullException(nameof(setupAction)); + } + + return CreateProvider(keyDirectory, setupAction, certificate: null); + } + + /// + /// Creates a that store keys in a location based on + /// the platform and operating system and uses the given to encrypt the keys. + /// + /// An identifier that uniquely discriminates this application from all other + /// applications on the machine. + /// The to be used for encryption. + public static IDataProtectionProvider Create(string applicationName, X509Certificate2 certificate) + { + if (string.IsNullOrEmpty(applicationName)) + { + throw new ArgumentNullException(nameof(applicationName)); + } + if (certificate == null) + { + throw new ArgumentNullException(nameof(certificate)); + } + + return CreateProvider( + keyDirectory: null, + setupAction: builder => { builder.SetApplicationName(applicationName); }, + certificate: certificate); + } + + /// + /// Creates an given a location at which to store keys + /// and a used to encrypt the keys. + /// + /// The in which keys should be stored. This may + /// represent a directory on a local disk or a UNC share. + /// The to be used for encryption. + public static IDataProtectionProvider Create( + DirectoryInfo keyDirectory, + X509Certificate2 certificate) + { + if (keyDirectory == null) + { + throw new ArgumentNullException(nameof(keyDirectory)); + } + if (certificate == null) + { + throw new ArgumentNullException(nameof(certificate)); + } + + return CreateProvider(keyDirectory, setupAction: builder => { }, certificate: certificate); + } + + /// + /// Creates an given a location at which to store keys, an + /// optional configuration callback and a used to encrypt the keys. + /// + /// The in which keys should be stored. This may + /// represent a directory on a local disk or a UNC share. + /// An optional callback which provides further configuration of the data protection + /// system. See for more information. + /// The to be used for encryption. + public static IDataProtectionProvider Create( + DirectoryInfo keyDirectory, + Action setupAction, + X509Certificate2 certificate) + { + if (keyDirectory == null) + { + throw new ArgumentNullException(nameof(keyDirectory)); + } + if (setupAction == null) + { + throw new ArgumentNullException(nameof(setupAction)); + } + if (certificate == null) + { + throw new ArgumentNullException(nameof(certificate)); + } + + return CreateProvider(keyDirectory, setupAction, certificate); + } + + internal static IDataProtectionProvider CreateProvider( + DirectoryInfo keyDirectory, + Action setupAction, + X509Certificate2 certificate) + { + // build the service collection + var serviceCollection = new ServiceCollection(); + var builder = serviceCollection.AddDataProtection(); + + if (keyDirectory != null) + { + builder.PersistKeysToFileSystem(keyDirectory); + } + + if (certificate != null) + { + builder.ProtectKeysWithCertificate(certificate); + } + + setupAction(builder); + + // extract the provider instance from the service collection + return serviceCollection.BuildServiceProvider().GetRequiredService(); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/ITimeLimitedDataProtector.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/ITimeLimitedDataProtector.cs new file mode 100644 index 0000000000..71fa609f21 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/ITimeLimitedDataProtector.cs @@ -0,0 +1,55 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// An interface that can provide data protection services where payloads have + /// a finite lifetime. + /// + /// + /// It is intended that payload lifetimes be somewhat short. Payloads protected + /// via this mechanism are not intended for long-term persistence (e.g., longer + /// than a few weeks). + /// + public interface ITimeLimitedDataProtector : IDataProtector + { + /// + /// Creates an given a purpose. + /// + /// + /// The purpose to be assigned to the newly-created . + /// + /// An tied to the provided purpose. + /// + /// The parameter must be unique for the intended use case; two + /// different instances created with two different + /// values will not be able to decipher each other's payloads. The parameter + /// value is not intended to be kept secret. + /// + new ITimeLimitedDataProtector CreateProtector(string purpose); + + /// + /// Cryptographically protects a piece of plaintext data, expiring the data at + /// the chosen time. + /// + /// The plaintext data to protect. + /// The time when this payload should expire. + /// The protected form of the plaintext data. + byte[] Protect(byte[] plaintext, DateTimeOffset expiration); + + /// + /// Cryptographically unprotects a piece of protected data. + /// + /// The protected data to unprotect. + /// An 'out' parameter which upon a successful unprotect + /// operation receives the expiration date of the payload. + /// The plaintext form of the protected data. + /// + /// Thrown if is invalid, malformed, or expired. + /// + byte[] Unprotect(byte[] protectedData, out DateTimeOffset expiration); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Microsoft.AspNetCore.DataProtection.Extensions.csproj b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Microsoft.AspNetCore.DataProtection.Extensions.csproj new file mode 100644 index 0000000000..44885e5711 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Microsoft.AspNetCore.DataProtection.Extensions.csproj @@ -0,0 +1,22 @@ + + + + Additional APIs for ASP.NET Core data protection. + netstandard2.0 + true + aspnetcore;dataprotection + + + + + + + + + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Properties/AssemblyInfo.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..022a5a3e6c --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// 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.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.DataProtection.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Properties/Resources.Designer.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..8fba5cd9f2 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Properties/Resources.Designer.cs @@ -0,0 +1,72 @@ +// +namespace Microsoft.AspNetCore.DataProtection.Extensions +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.AspNetCore.DataProtection.Extensions.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// An error occurred during a cryptographic operation. + /// + internal static string CryptCommon_GenericError + { + get => GetString("CryptCommon_GenericError"); + } + + /// + /// An error occurred during a cryptographic operation. + /// + internal static string FormatCryptCommon_GenericError() + => GetString("CryptCommon_GenericError"); + + /// + /// The payload expired at {0}. + /// + internal static string TimeLimitedDataProtector_PayloadExpired + { + get => GetString("TimeLimitedDataProtector_PayloadExpired"); + } + + /// + /// The payload expired at {0}. + /// + internal static string FormatTimeLimitedDataProtector_PayloadExpired(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("TimeLimitedDataProtector_PayloadExpired"), p0); + + /// + /// The payload is invalid. + /// + internal static string TimeLimitedDataProtector_PayloadInvalid + { + get => GetString("TimeLimitedDataProtector_PayloadInvalid"); + } + + /// + /// The payload is invalid. + /// + internal static string FormatTimeLimitedDataProtector_PayloadInvalid() + => GetString("TimeLimitedDataProtector_PayloadInvalid"); + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Resources.resx b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Resources.resx new file mode 100644 index 0000000000..b53d26e321 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/Resources.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + An error occurred during a cryptographic operation. + + + The payload expired at {0}. + + + The payload is invalid. + + \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/TimeLimitedDataProtector.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/TimeLimitedDataProtector.cs new file mode 100644 index 0000000000..71e9c3c553 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/TimeLimitedDataProtector.cs @@ -0,0 +1,149 @@ +// 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.Security.Cryptography; +using System.Threading; +using Microsoft.AspNetCore.DataProtection.Extensions; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Wraps an existing and appends a purpose that allows + /// protecting data with a finite lifetime. + /// + internal sealed class TimeLimitedDataProtector : ITimeLimitedDataProtector + { + private const string MyPurposeString = "Microsoft.AspNetCore.DataProtection.TimeLimitedDataProtector.v1"; + + private readonly IDataProtector _innerProtector; + private IDataProtector _innerProtectorWithTimeLimitedPurpose; // created on-demand + + public TimeLimitedDataProtector(IDataProtector innerProtector) + { + _innerProtector = innerProtector; + } + + public ITimeLimitedDataProtector CreateProtector(string purpose) + { + if (purpose == null) + { + throw new ArgumentNullException(nameof(purpose)); + } + + return new TimeLimitedDataProtector(_innerProtector.CreateProtector(purpose)); + } + + private IDataProtector GetInnerProtectorWithTimeLimitedPurpose() + { + // thread-safe lazy init pattern with multi-execution and single publication + var retVal = Volatile.Read(ref _innerProtectorWithTimeLimitedPurpose); + if (retVal == null) + { + var newValue = _innerProtector.CreateProtector(MyPurposeString); // we always append our purpose to the end of the chain + retVal = Interlocked.CompareExchange(ref _innerProtectorWithTimeLimitedPurpose, newValue, null) ?? newValue; + } + return retVal; + } + + public byte[] Protect(byte[] plaintext, DateTimeOffset expiration) + { + if (plaintext == null) + { + throw new ArgumentNullException(nameof(plaintext)); + } + + // We prepend the expiration time (as a 64-bit UTC tick count) to the unprotected data. + byte[] plaintextWithHeader = new byte[checked(8 + plaintext.Length)]; + BitHelpers.WriteUInt64(plaintextWithHeader, 0, (ulong)expiration.UtcTicks); + Buffer.BlockCopy(plaintext, 0, plaintextWithHeader, 8, plaintext.Length); + + return GetInnerProtectorWithTimeLimitedPurpose().Protect(plaintextWithHeader); + } + + public byte[] Unprotect(byte[] protectedData, out DateTimeOffset expiration) + { + if (protectedData == null) + { + throw new ArgumentNullException(nameof(protectedData)); + } + + return UnprotectCore(protectedData, DateTimeOffset.UtcNow, out expiration); + } + + internal byte[] UnprotectCore(byte[] protectedData, DateTimeOffset now, out DateTimeOffset expiration) + { + if (protectedData == null) + { + throw new ArgumentNullException(nameof(protectedData)); + } + + try + { + byte[] plaintextWithHeader = GetInnerProtectorWithTimeLimitedPurpose().Unprotect(protectedData); + if (plaintextWithHeader.Length < 8) + { + // header isn't present + throw new CryptographicException(Resources.TimeLimitedDataProtector_PayloadInvalid); + } + + // Read expiration time back out of the payload + ulong utcTicksExpiration = BitHelpers.ReadUInt64(plaintextWithHeader, 0); + DateTimeOffset embeddedExpiration = new DateTimeOffset(checked((long)utcTicksExpiration), TimeSpan.Zero /* UTC */); + + // Are we expired? + if (now > embeddedExpiration) + { + throw new CryptographicException(Resources.FormatTimeLimitedDataProtector_PayloadExpired(embeddedExpiration)); + } + + // Not expired - split and return payload + byte[] retVal = new byte[plaintextWithHeader.Length - 8]; + Buffer.BlockCopy(plaintextWithHeader, 8, retVal, 0, retVal.Length); + expiration = embeddedExpiration; + return retVal; + } + catch (Exception ex) when (ex.RequiresHomogenization()) + { + // Homogenize all failures to CryptographicException + throw new CryptographicException(Resources.CryptCommon_GenericError, ex); + } + } + + /* + * EXPLICIT INTERFACE IMPLEMENTATIONS + */ + + IDataProtector IDataProtectionProvider.CreateProtector(string purpose) + { + if (purpose == null) + { + throw new ArgumentNullException(nameof(purpose)); + } + + return CreateProtector(purpose); + } + + byte[] IDataProtector.Protect(byte[] plaintext) + { + if (plaintext == null) + { + throw new ArgumentNullException(nameof(plaintext)); + } + + // MaxValue essentially means 'no expiration' + return Protect(plaintext, DateTimeOffset.MaxValue); + } + + byte[] IDataProtector.Unprotect(byte[] protectedData) + { + if (protectedData == null) + { + throw new ArgumentNullException(nameof(protectedData)); + } + + DateTimeOffset expiration; // unused + return Unprotect(protectedData, out expiration); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/baseline.netcore.json b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/baseline.netcore.json new file mode 100644 index 0000000000..5bb3088d07 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.Extensions/baseline.netcore.json @@ -0,0 +1,298 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.DataProtection.Extensions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.AspNetCore.DataProtection.DataProtectionAdvancedExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Protect", + "Parameters": [ + { + "Name": "protector", + "Type": "Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector" + }, + { + "Name": "plaintext", + "Type": "System.Byte[]" + }, + { + "Name": "lifetime", + "Type": "System.TimeSpan" + } + ], + "ReturnType": "System.Byte[]", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Protect", + "Parameters": [ + { + "Name": "protector", + "Type": "Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector" + }, + { + "Name": "plaintext", + "Type": "System.String" + }, + { + "Name": "expiration", + "Type": "System.DateTimeOffset" + } + ], + "ReturnType": "System.String", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Protect", + "Parameters": [ + { + "Name": "protector", + "Type": "Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector" + }, + { + "Name": "plaintext", + "Type": "System.String" + }, + { + "Name": "lifetime", + "Type": "System.TimeSpan" + } + ], + "ReturnType": "System.String", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ToTimeLimitedDataProtector", + "Parameters": [ + { + "Name": "protector", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtector" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Unprotect", + "Parameters": [ + { + "Name": "protector", + "Type": "Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector" + }, + { + "Name": "protectedData", + "Type": "System.String" + }, + { + "Name": "expiration", + "Type": "System.DateTimeOffset", + "Direction": "Out" + } + ], + "ReturnType": "System.String", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.DataProtectionProvider", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Create", + "Parameters": [ + { + "Name": "applicationName", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Create", + "Parameters": [ + { + "Name": "keyDirectory", + "Type": "System.IO.DirectoryInfo" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Create", + "Parameters": [ + { + "Name": "keyDirectory", + "Type": "System.IO.DirectoryInfo" + }, + { + "Name": "setupAction", + "Type": "System.Action" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Create", + "Parameters": [ + { + "Name": "applicationName", + "Type": "System.String" + }, + { + "Name": "certificate", + "Type": "System.Security.Cryptography.X509Certificates.X509Certificate2" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Create", + "Parameters": [ + { + "Name": "keyDirectory", + "Type": "System.IO.DirectoryInfo" + }, + { + "Name": "certificate", + "Type": "System.Security.Cryptography.X509Certificates.X509Certificate2" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Create", + "Parameters": [ + { + "Name": "keyDirectory", + "Type": "System.IO.DirectoryInfo" + }, + { + "Name": "setupAction", + "Type": "System.Action" + }, + { + "Name": "certificate", + "Type": "System.Security.Cryptography.X509Certificates.X509Certificate2" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.IDataProtector" + ], + "Members": [ + { + "Kind": "Method", + "Name": "CreateProtector", + "Parameters": [ + { + "Name": "purpose", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Protect", + "Parameters": [ + { + "Name": "plaintext", + "Type": "System.Byte[]" + }, + { + "Name": "expiration", + "Type": "System.DateTimeOffset" + } + ], + "ReturnType": "System.Byte[]", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Unprotect", + "Parameters": [ + { + "Name": "protectedData", + "Type": "System.Byte[]" + }, + { + "Name": "expiration", + "Type": "System.DateTimeOffset", + "Direction": "Out" + } + ], + "ReturnType": "System.Byte[]", + "GenericParameter": [] + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj new file mode 100644 index 0000000000..1aa6874fff --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj @@ -0,0 +1,19 @@ + + + + Support for storing data protection keys in Redis. + netstandard2.0 + true + true + aspnetcore;dataprotection;redis + + + + + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis/RedisDataProtectionBuilderExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis/RedisDataProtectionBuilderExtensions.cs new file mode 100644 index 0000000000..ead1b37db5 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis/RedisDataProtectionBuilderExtensions.cs @@ -0,0 +1,79 @@ +// 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 StackExchange.Redis; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.DataProtection.StackExchangeRedis; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Contains Redis-specific extension methods for modifying a . + /// + public static class StackExchangeRedisDataProtectionBuilderExtensions + { + private const string DataProtectionKeysName = "DataProtection-Keys"; + + /// + /// Configures the data protection system to persist keys to specified key in Redis database + /// + /// The builder instance to modify. + /// The delegate used to create instances. + /// The used to store key list. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataProtectionBuilder builder, Func databaseFactory, RedisKey key) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + if (databaseFactory == null) + { + throw new ArgumentNullException(nameof(databaseFactory)); + } + return PersistKeysToStackExchangeRedisInternal(builder, databaseFactory, key); + } + + /// + /// Configures the data protection system to persist keys to the default key ('DataProtection-Keys') in Redis database + /// + /// The builder instance to modify. + /// The for database access. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataProtectionBuilder builder, IConnectionMultiplexer connectionMultiplexer) + { + return PersistKeysToStackExchangeRedis(builder, connectionMultiplexer, DataProtectionKeysName); + } + + /// + /// Configures the data protection system to persist keys to the specified key in Redis database + /// + /// The builder instance to modify. + /// The for database access. + /// The used to store key list. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataProtectionBuilder builder, IConnectionMultiplexer connectionMultiplexer, RedisKey key) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + if (connectionMultiplexer == null) + { + throw new ArgumentNullException(nameof(connectionMultiplexer)); + } + return PersistKeysToStackExchangeRedisInternal(builder, () => connectionMultiplexer.GetDatabase(), key); + } + + private static IDataProtectionBuilder PersistKeysToStackExchangeRedisInternal(IDataProtectionBuilder builder, Func databaseFactory, RedisKey key) + { + builder.Services.Configure(options => + { + options.XmlRepository = new RedisXmlRepository(databaseFactory, key); + }); + return builder; + } + } +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis/RedisXmlRepository.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis/RedisXmlRepository.cs new file mode 100644 index 0000000000..2665fd1408 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis/RedisXmlRepository.cs @@ -0,0 +1,59 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using StackExchange.Redis; +using Microsoft.AspNetCore.DataProtection.Repositories; + +namespace Microsoft.AspNetCore.DataProtection.StackExchangeRedis +{ + /// + /// An XML repository backed by a Redis list entry. + /// + public class RedisXmlRepository : IXmlRepository + { + private readonly Func _databaseFactory; + private readonly RedisKey _key; + + /// + /// Creates a with keys stored at the given directory. + /// + /// The delegate used to create instances. + /// The used to store key list. + public RedisXmlRepository(Func databaseFactory, RedisKey key) + { + _databaseFactory = databaseFactory; + _key = key; + } + + /// + public IReadOnlyCollection GetAllElements() + { + return GetAllElementsCore().ToList().AsReadOnly(); + } + + private IEnumerable GetAllElementsCore() + { + // Note: Inability to read any value is considered a fatal error (since the file may contain + // revocation information), and we'll fail the entire operation rather than return a partial + // set of elements. If a value contains well-formed XML but its contents are meaningless, we + // won't fail that operation here. The caller is responsible for failing as appropriate given + // that scenario. + var database = _databaseFactory(); + foreach (var value in database.ListRange(_key)) + { + yield return XElement.Parse(value); + } + } + + /// + public void StoreElement(XElement element, string friendlyName) + { + var database = _databaseFactory(); + database.ListRightPush(_key, element.ToString(SaveOptions.DisableFormatting)); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/CompatibilityDataProtector.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/CompatibilityDataProtector.cs new file mode 100644 index 0000000000..739afe83bd --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/CompatibilityDataProtector.cs @@ -0,0 +1,133 @@ +// 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.ComponentModel; +using System.Configuration; +using System.Security.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection.SystemWeb +{ + /// + /// A that can be used by ASP.NET 4.x to interact with ASP.NET Core's + /// DataProtection stack. This type is for internal use only and shouldn't be directly used by + /// developers. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class CompatibilityDataProtector : DataProtector + { + private static readonly Lazy _lazyProtectionProvider = new Lazy(CreateProtectionProvider); + + [ThreadStatic] + private static bool _suppressPrimaryPurpose; + + private readonly Lazy _lazyProtector; + private readonly Lazy _lazyProtectorSuppressedPrimaryPurpose; + + public CompatibilityDataProtector(string applicationName, string primaryPurpose, string[] specificPurposes) + : base("application-name", "primary-purpose", null) // we feed dummy values to the base ctor + { + // We don't want to evaluate the IDataProtectionProvider factory quite yet, + // as we'd rather defer failures to the call to Protect so that we can bubble + // up a good error message to the developer. + + _lazyProtector = new Lazy(() => _lazyProtectionProvider.Value.CreateProtector(primaryPurpose, specificPurposes)); + + // System.Web always provides "User.MachineKey.Protect" as the primary purpose for calls + // to MachineKey.Protect. Only in this case should we allow suppressing the primary + // purpose, as then we can easily map calls to MachineKey.Protect(userData, purposes) + // into calls to provider.GetProtector(purposes).Protect(userData). + if (primaryPurpose == "User.MachineKey.Protect") + { + _lazyProtectorSuppressedPrimaryPurpose = new Lazy(() => _lazyProtectionProvider.Value.CreateProtector(specificPurposes)); + } + else + { + _lazyProtectorSuppressedPrimaryPurpose = _lazyProtector; + } + } + + // We take care of flowing purposes ourselves. + protected override bool PrependHashedPurposeToPlaintext { get; } = false; + + // Retrieves the appropriate protector (potentially with a suppressed primary purpose) for this operation. + private IDataProtector Protector => ((_suppressPrimaryPurpose) ? _lazyProtectorSuppressedPrimaryPurpose : _lazyProtector).Value; + + private static IDataProtectionProvider CreateProtectionProvider() + { + // Read from the startup type we need to use, then create it + const string APPSETTINGS_KEY = "aspnet:dataProtectionStartupType"; + string startupTypeName = ConfigurationManager.AppSettings[APPSETTINGS_KEY]; + if (String.IsNullOrEmpty(startupTypeName)) + { + // fall back to default startup type if one hasn't been specified in config + startupTypeName = typeof(DataProtectionStartup).AssemblyQualifiedName; + } + Type startupType = Type.GetType(startupTypeName, throwOnError: true); + var startupInstance = (DataProtectionStartup)Activator.CreateInstance(startupType); + + // Use it to initialize the system. + return startupInstance.InternalConfigureServicesAndCreateProtectionProvider(); + } + + public override bool IsReprotectRequired(byte[] encryptedData) + { + // Nobody ever calls this. + return false; + } + + protected override byte[] ProviderProtect(byte[] userData) + { + try + { + return Protector.Protect(userData); + } + catch (Exception ex) + { + // System.Web special-cases ConfigurationException errors and allows them to bubble + // up to the developer without being homogenized. Since a call to Protect should + // never fail, any exceptions here really do imply a misconfiguration. + +#pragma warning disable CS0618 // Type or member is obsolete + throw new ConfigurationException(Resources.DataProtector_ProtectFailed, ex); +#pragma warning restore CS0618 // Type or member is obsolete + } + } + + protected override byte[] ProviderUnprotect(byte[] encryptedData) + { + return Protector.Unprotect(encryptedData); + } + + /// + /// Invokes a delegate where calls to + /// and will ignore the primary + /// purpose and instead use only the sub-purposes. + /// + public static byte[] RunWithSuppressedPrimaryPurpose(Func callback, object state, byte[] input) + { + if (_suppressPrimaryPurpose) + { + return callback(state, input); // already suppressed - just forward call + } + + try + { + try + { + _suppressPrimaryPurpose = true; + return callback(state, input); + } + finally + { + _suppressPrimaryPurpose = false; + } + } + catch + { + // defeat exception filters + throw; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/DataProtectionStartup.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/DataProtectionStartup.cs new file mode 100644 index 0000000000..f3760df207 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/DataProtectionStartup.cs @@ -0,0 +1,102 @@ +// 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.Configuration; +using System.Web; +using System.Web.Configuration; +using Microsoft.AspNetCore.DataProtection.Infrastructure; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.DataProtection.SystemWeb +{ + /// + /// Allows controlling the configuration of the ASP.NET Core Data Protection system. + /// + /// + /// Developers should not call these APIs directly. Instead, developers should subclass + /// this type and override the + /// method or methods + /// as appropriate. + /// + public class DataProtectionStartup + { + /// + /// Configures services used by the Data Protection system. + /// + /// A mutable collection of services. + /// + /// Developers may override this method to change the default behaviors of + /// the Data Protection system. + /// + public virtual void ConfigureServices(IServiceCollection services) + { + // InternalConfigureServices already takes care of default configuration. + // The reason we don't configure default logic in this method is that we don't + // want to punish the developer for forgetting to call base.ConfigureServices + // from within his own override. + } + + /// + /// Creates a new instance of an . + /// + /// A collection of services from which to create the . + /// An . + /// + /// Developers should generally override the + /// method instead of this method. + /// + public virtual IDataProtectionProvider CreateDataProtectionProvider(IServiceProvider services) + { + return services.GetDataProtectionProvider(); + } + + /// + /// Provides a default implementation of required services, calls the developer's + /// configuration overrides, then creates an . + /// + internal IDataProtectionProvider InternalConfigureServicesAndCreateProtectionProvider() + { + // Configure the default implementation, passing in our custom discriminator + var services = new ServiceCollection(); + services.AddDataProtection(); + services.AddSingleton(new SystemWebApplicationDiscriminator()); + + // Run user-specified configuration and get an instance of the provider + ConfigureServices(services); + var provider = CreateDataProtectionProvider(services.BuildServiceProvider()); + if (provider == null) + { + throw new InvalidOperationException(Resources.Startup_CreateProviderReturnedNull); + } + + // And we're done! + return provider; + } + + private sealed class SystemWebApplicationDiscriminator : IApplicationDiscriminator + { + private readonly Lazy _lazyDiscriminator = new Lazy(GetAppDiscriminatorCore); + + public string Discriminator => _lazyDiscriminator.Value; + + private static string GetAppDiscriminatorCore() + { + // Try reading the discriminator from defined + // at the web app root. If the value was set explicitly (even if the value is empty), + // honor it as the discriminator. + var machineKeySection = (MachineKeySection)WebConfigurationManager.GetWebApplicationSection("system.web/machineKey"); + if (machineKeySection.ElementInformation.Properties["applicationName"].ValueOrigin != PropertyValueOrigin.Default) + { + return machineKeySection.ApplicationName; + } + else + { + // Otherwise, fall back to the IIS metabase config path. + // This is unique per machine. + return HttpRuntime.AppDomainAppId; + } + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/Microsoft.AspNetCore.DataProtection.SystemWeb.csproj b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/Microsoft.AspNetCore.DataProtection.SystemWeb.csproj new file mode 100644 index 0000000000..a40024990e --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/Microsoft.AspNetCore.DataProtection.SystemWeb.csproj @@ -0,0 +1,25 @@ + + + + A component to allow the ASP.NET Core data protection stack to work with the ASP.NET 4.x <machineKey> element. + net461 + $(NoWarn);CS1591 + true + aspnet;aspnetcore;dataprotection + + + + + + + + + + + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/Properties/Resources.Designer.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..ddc7e53910 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/Properties/Resources.Designer.cs @@ -0,0 +1,58 @@ +// +namespace Microsoft.AspNetCore.DataProtection.SystemWeb +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.AspNetCore.DataProtection.SystemWeb.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// A call to Protect failed. This most likely means that the data protection system is misconfigured. See the inner exception for more information. + /// + internal static string DataProtector_ProtectFailed + { + get => GetString("DataProtector_ProtectFailed"); + } + + /// + /// A call to Protect failed. This most likely means that the data protection system is misconfigured. See the inner exception for more information. + /// + internal static string FormatDataProtector_ProtectFailed() + => GetString("DataProtector_ProtectFailed"); + + /// + /// The CreateDataProtectionProvider method returned null. + /// + internal static string Startup_CreateProviderReturnedNull + { + get => GetString("Startup_CreateProviderReturnedNull"); + } + + /// + /// The CreateDataProtectionProvider method returned null. + /// + internal static string FormatStartup_CreateProviderReturnedNull() + => GetString("Startup_CreateProviderReturnedNull"); + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/Resources.resx b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/Resources.resx new file mode 100644 index 0000000000..0923e71d3c --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/Resources.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + A call to Protect failed. This most likely means that the data protection system is misconfigured. See the inner exception for more information. + + + The CreateDataProtectionProvider method returned null. + + \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/baseline.netframework.json b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/baseline.netframework.json new file mode 100644 index 0000000000..c068f832bb --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/baseline.netframework.json @@ -0,0 +1,157 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.DataProtection.SystemWeb, Version=2.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.AspNetCore.DataProtection.SystemWeb.CompatibilityDataProtector", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "BaseType": "System.Security.Cryptography.DataProtector", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_PrependHashedPurposeToPlaintext", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Protected", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "IsReprotectRequired", + "Parameters": [ + { + "Name": "encryptedData", + "Type": "System.Byte[]" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ProviderProtect", + "Parameters": [ + { + "Name": "userData", + "Type": "System.Byte[]" + } + ], + "ReturnType": "System.Byte[]", + "Virtual": true, + "Override": true, + "Visibility": "Protected", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ProviderUnprotect", + "Parameters": [ + { + "Name": "encryptedData", + "Type": "System.Byte[]" + } + ], + "ReturnType": "System.Byte[]", + "Virtual": true, + "Override": true, + "Visibility": "Protected", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "RunWithSuppressedPrimaryPurpose", + "Parameters": [ + { + "Name": "callback", + "Type": "System.Func" + }, + { + "Name": "state", + "Type": "System.Object" + }, + { + "Name": "input", + "Type": "System.Byte[]" + } + ], + "ReturnType": "System.Byte[]", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "applicationName", + "Type": "System.String" + }, + { + "Name": "primaryPurpose", + "Type": "System.String" + }, + { + "Name": "specificPurposes", + "Type": "System.String[]" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.SystemWeb.DataProtectionStartup", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "ConfigureServices", + "Parameters": [ + { + "Name": "services", + "Type": "Microsoft.Extensions.DependencyInjection.IServiceCollection" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CreateDataProtectionProvider", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Virtual": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/web.config.transform b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/web.config.transform new file mode 100644 index 0000000000..8d5a699252 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection.SystemWeb/web.config.transform @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ActivatorExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ActivatorExtensions.cs new file mode 100644 index 0000000000..a485958fc9 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ActivatorExtensions.cs @@ -0,0 +1,43 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Extension methods for working with . + /// + internal static class ActivatorExtensions + { + /// + /// Creates an instance of and ensures + /// that it is assignable to . + /// + public static T CreateInstance(this IActivator activator, string implementationTypeName) + where T : class + { + if (implementationTypeName == null) + { + throw new ArgumentNullException(nameof(implementationTypeName)); + } + + return activator.CreateInstance(typeof(T), implementationTypeName) as T + ?? CryptoUtil.Fail("CreateInstance returned null."); + } + + /// + /// Returns a given an . + /// Guaranteed to return non-null, even if is null. + /// + public static IActivator GetActivator(this IServiceProvider serviceProvider) + { + return (serviceProvider != null) + ? (serviceProvider.GetService() ?? new SimpleActivator(serviceProvider)) + : SimpleActivator.DefaultWithoutServices; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ApplyPolicyAttribute.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ApplyPolicyAttribute.cs new file mode 100644 index 0000000000..f73a745b1e --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ApplyPolicyAttribute.cs @@ -0,0 +1,13 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Signifies that the should bind this property from the registry. + /// + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + internal sealed class ApplyPolicyAttribute : Attribute { } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ArraySegmentExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ArraySegmentExtensions.cs new file mode 100644 index 0000000000..f468560f77 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ArraySegmentExtensions.cs @@ -0,0 +1,30 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal static class ArraySegmentExtensions + { + public static byte[] AsStandaloneArray(this ArraySegment arraySegment) + { + // Fast-track: Don't need to duplicate the array. + if (arraySegment.Offset == 0 && arraySegment.Count == arraySegment.Array.Length) + { + return arraySegment.Array; + } + + var retVal = new byte[arraySegment.Count]; + Buffer.BlockCopy(arraySegment.Array, arraySegment.Offset, retVal, 0, retVal.Length); + return retVal; + } + + public static void Validate(this ArraySegment arraySegment) + { + // Since ArraySegment is a struct, it can be improperly initialized or torn. + // We call the ctor again to make sure the instance data is valid. + var unused = new ArraySegment(arraySegment.Array, arraySegment.Offset, arraySegment.Count); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/AlgorithmAssert.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/AlgorithmAssert.cs new file mode 100644 index 0000000000..cd3dd8432e --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/AlgorithmAssert.cs @@ -0,0 +1,55 @@ +// 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 Microsoft.AspNetCore.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + internal static class AlgorithmAssert + { + // Our analysis re: IV collision resistance for CBC only holds if we're working with block ciphers + // with a block length of 64 bits or greater. + private const uint SYMMETRIC_ALG_MIN_BLOCK_SIZE_IN_BITS = 64; + + // Min security bar: encryption algorithm must have a min 128-bit key. + private const uint SYMMETRIC_ALG_MIN_KEY_LENGTH_IN_BITS = 128; + + // Min security bar: authentication tag must have at least 128 bits of output. + private const uint HASH_ALG_MIN_DIGEST_LENGTH_IN_BITS = 128; + + // Since we're performing some stack allocs based on these buffers, make sure we don't explode. + private const uint MAX_SIZE_IN_BITS = Constants.MAX_STACKALLOC_BYTES * 8; + + public static void IsAllowableSymmetricAlgorithmBlockSize(uint blockSizeInBits) + { + if (!IsValidCore(blockSizeInBits, SYMMETRIC_ALG_MIN_BLOCK_SIZE_IN_BITS)) + { + throw new InvalidOperationException(Resources.FormatAlgorithmAssert_BadBlockSize(blockSizeInBits)); + } + } + + public static void IsAllowableSymmetricAlgorithmKeySize(uint keySizeInBits) + { + if (!IsValidCore(keySizeInBits, SYMMETRIC_ALG_MIN_KEY_LENGTH_IN_BITS)) + { + throw new InvalidOperationException(Resources.FormatAlgorithmAssert_BadKeySize(keySizeInBits)); + } + } + + public static void IsAllowableValidationAlgorithmDigestSize(uint digestSizeInBits) + { + if (!IsValidCore(digestSizeInBits, HASH_ALG_MIN_DIGEST_LENGTH_IN_BITS)) + { + throw new InvalidOperationException(Resources.FormatAlgorithmAssert_BadDigestSize(digestSizeInBits)); + } + } + + private static bool IsValidCore(uint value, uint minValue) + { + return (value % 8 == 0) // must be whole bytes + && (value >= minValue) // must meet our basic security requirements + && (value <= MAX_SIZE_IN_BITS); // mustn't overflow our stack + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorExtensions.cs new file mode 100644 index 0000000000..31f31a9a28 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorExtensions.cs @@ -0,0 +1,55 @@ +// 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 Microsoft.AspNetCore.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + internal static class AuthenticatedEncryptorExtensions + { + public static byte[] Encrypt(this IAuthenticatedEncryptor encryptor, ArraySegment plaintext, ArraySegment additionalAuthenticatedData, uint preBufferSize, uint postBufferSize) + { + // Can we call the optimized version? + var optimizedEncryptor = encryptor as IOptimizedAuthenticatedEncryptor; + if (optimizedEncryptor != null) + { + return optimizedEncryptor.Encrypt(plaintext, additionalAuthenticatedData, preBufferSize, postBufferSize); + } + + // Fall back to the unoptimized version + if (preBufferSize == 0 && postBufferSize == 0) + { + // optimization: call through to inner encryptor with no modifications + return encryptor.Encrypt(plaintext, additionalAuthenticatedData); + } + else + { + var temp = encryptor.Encrypt(plaintext, additionalAuthenticatedData); + var retVal = new byte[checked(preBufferSize + temp.Length + postBufferSize)]; + Buffer.BlockCopy(temp, 0, retVal, checked((int)preBufferSize), temp.Length); + return retVal; + } + } + + /// + /// Performs a self-test of this encryptor by running a sample payload through an + /// encrypt-then-decrypt operation. Throws if the operation fails. + /// + public static void PerformSelfTest(this IAuthenticatedEncryptor encryptor) + { + // Arrange + var plaintextAsGuid = Guid.NewGuid(); + var plaintextAsBytes = plaintextAsGuid.ToByteArray(); + var aad = Guid.NewGuid().ToByteArray(); + + // Act + var protectedData = encryptor.Encrypt(new ArraySegment(plaintextAsBytes), new ArraySegment(aad)); + var roundTrippedData = encryptor.Decrypt(new ArraySegment(protectedData), new ArraySegment(aad)); + + // Assert + CryptoUtil.Assert(roundTrippedData != null && roundTrippedData.Length == plaintextAsBytes.Length && plaintextAsGuid == new Guid(roundTrippedData), + "Plaintext did not round-trip properly through the authenticated encryptor."); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorFactory.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorFactory.cs new file mode 100644 index 0000000000..f9be1e1994 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorFactory.cs @@ -0,0 +1,182 @@ +// 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.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + /// + /// An to create an + /// based on the . + /// + public sealed class AuthenticatedEncryptorFactory : IAuthenticatedEncryptorFactory + { + private readonly ILoggerFactory _loggerFactory; + + public AuthenticatedEncryptorFactory(ILoggerFactory loggerFactory) + { + _loggerFactory = loggerFactory; + } + + public IAuthenticatedEncryptor CreateEncryptorInstance(IKey key) + { + var descriptor = key.Descriptor as AuthenticatedEncryptorDescriptor; + if (descriptor == null) + { + return null; + } + + return CreateAuthenticatedEncryptorInstance(descriptor.MasterKey, descriptor.Configuration); + } + + internal IAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance( + ISecret secret, + AuthenticatedEncryptorConfiguration authenticatedConfiguration) + { + if (authenticatedConfiguration == null) + { + return null; + } + + if (IsGcmAlgorithm(authenticatedConfiguration.EncryptionAlgorithm)) + { + // GCM requires CNG, and CNG is only supported on Windows. + if (!OSVersionUtil.IsWindows()) + { + throw new PlatformNotSupportedException(Resources.Platform_WindowsRequiredForGcm); + } + + var configuration = new CngGcmAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm), + EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm) + }; + + return new CngGcmAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration); + } + else + { + if (OSVersionUtil.IsWindows()) + { + // CNG preferred over managed implementations if running on Windows + var configuration = new CngCbcAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm), + EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm), + HashAlgorithm = GetBCryptAlgorithmNameFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm) + }; + + return new CngCbcAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration); + } + else + { + // Use managed implementations as a fallback + var configuration = new ManagedAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithmType = GetManagedTypeFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm), + EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm), + ValidationAlgorithmType = GetManagedTypeFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm) + }; + + return new ManagedAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration); + } + } + } + + internal static bool IsGcmAlgorithm(EncryptionAlgorithm algorithm) + { + return (EncryptionAlgorithm.AES_128_GCM <= algorithm && algorithm <= EncryptionAlgorithm.AES_256_GCM); + } + + private static int GetAlgorithmKeySizeInBits(EncryptionAlgorithm algorithm) + { + switch (algorithm) + { + case EncryptionAlgorithm.AES_128_CBC: + case EncryptionAlgorithm.AES_128_GCM: + return 128; + + case EncryptionAlgorithm.AES_192_CBC: + case EncryptionAlgorithm.AES_192_GCM: + return 192; + + case EncryptionAlgorithm.AES_256_CBC: + case EncryptionAlgorithm.AES_256_GCM: + return 256; + + default: + throw new ArgumentOutOfRangeException(nameof(EncryptionAlgorithm)); + } + } + + private static string GetBCryptAlgorithmNameFromEncryptionAlgorithm(EncryptionAlgorithm algorithm) + { + switch (algorithm) + { + case EncryptionAlgorithm.AES_128_CBC: + case EncryptionAlgorithm.AES_192_CBC: + case EncryptionAlgorithm.AES_256_CBC: + case EncryptionAlgorithm.AES_128_GCM: + case EncryptionAlgorithm.AES_192_GCM: + case EncryptionAlgorithm.AES_256_GCM: + return Constants.BCRYPT_AES_ALGORITHM; + + default: + throw new ArgumentOutOfRangeException(nameof(EncryptionAlgorithm)); + } + } + + private static string GetBCryptAlgorithmNameFromValidationAlgorithm(ValidationAlgorithm algorithm) + { + switch (algorithm) + { + case ValidationAlgorithm.HMACSHA256: + return Constants.BCRYPT_SHA256_ALGORITHM; + + case ValidationAlgorithm.HMACSHA512: + return Constants.BCRYPT_SHA512_ALGORITHM; + + default: + throw new ArgumentOutOfRangeException(nameof(ValidationAlgorithm)); + } + } + + private static Type GetManagedTypeFromEncryptionAlgorithm(EncryptionAlgorithm algorithm) + { + switch (algorithm) + { + case EncryptionAlgorithm.AES_128_CBC: + case EncryptionAlgorithm.AES_192_CBC: + case EncryptionAlgorithm.AES_256_CBC: + case EncryptionAlgorithm.AES_128_GCM: + case EncryptionAlgorithm.AES_192_GCM: + case EncryptionAlgorithm.AES_256_GCM: + return typeof(Aes); + + default: + throw new ArgumentOutOfRangeException(nameof(EncryptionAlgorithm)); + } + } + + private static Type GetManagedTypeFromValidationAlgorithm(ValidationAlgorithm algorithm) + { + switch (algorithm) + { + case ValidationAlgorithm.HMACSHA256: + return typeof(HMACSHA256); + + case ValidationAlgorithm.HMACSHA512: + return typeof(HMACSHA512); + + default: + throw new ArgumentOutOfRangeException(nameof(ValidationAlgorithm)); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorFactory.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorFactory.cs new file mode 100644 index 0000000000..1ccc76d501 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorFactory.cs @@ -0,0 +1,127 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + /// + /// An for . + /// + public sealed class CngCbcAuthenticatedEncryptorFactory : IAuthenticatedEncryptorFactory + { + private readonly ILogger _logger; + + public CngCbcAuthenticatedEncryptorFactory(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + } + + public IAuthenticatedEncryptor CreateEncryptorInstance(IKey key) + { + var descriptor = key.Descriptor as CngCbcAuthenticatedEncryptorDescriptor; + if (descriptor == null) + { + return null; + } + + return CreateAuthenticatedEncryptorInstance(descriptor.MasterKey, descriptor.Configuration); + } + + internal CbcAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance( + ISecret secret, + CngCbcAuthenticatedEncryptorConfiguration configuration) + { + if (configuration == null) + { + return null; + } + + return new CbcAuthenticatedEncryptor( + keyDerivationKey: new Secret(secret), + symmetricAlgorithmHandle: GetSymmetricBlockCipherAlgorithmHandle(configuration), + symmetricAlgorithmKeySizeInBytes: (uint)(configuration.EncryptionAlgorithmKeySize / 8), + hmacAlgorithmHandle: GetHmacAlgorithmHandle(configuration)); + } + + private BCryptAlgorithmHandle GetHmacAlgorithmHandle(CngCbcAuthenticatedEncryptorConfiguration configuration) + { + // basic argument checking + if (String.IsNullOrEmpty(configuration.HashAlgorithm)) + { + throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(configuration.HashAlgorithm)); + } + + _logger.OpeningCNGAlgorithmFromProviderWithHMAC(configuration.HashAlgorithm, configuration.HashAlgorithmProvider); + BCryptAlgorithmHandle algorithmHandle = null; + + // Special-case cached providers + if (configuration.HashAlgorithmProvider == null) + { + if (configuration.HashAlgorithm == Constants.BCRYPT_SHA1_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA1; } + else if (configuration.HashAlgorithm == Constants.BCRYPT_SHA256_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA256; } + else if (configuration.HashAlgorithm == Constants.BCRYPT_SHA512_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA512; } + } + + // Look up the provider dynamically if we couldn't fetch a cached instance + if (algorithmHandle == null) + { + algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(configuration.HashAlgorithm, configuration.HashAlgorithmProvider, hmac: true); + } + + // Make sure we're using a hash algorithm. We require a minimum 128-bit digest. + uint digestSize = algorithmHandle.GetHashDigestLength(); + AlgorithmAssert.IsAllowableValidationAlgorithmDigestSize(checked(digestSize * 8)); + + // all good! + return algorithmHandle; + } + + private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle(CngCbcAuthenticatedEncryptorConfiguration configuration) + { + // basic argument checking + if (String.IsNullOrEmpty(configuration.EncryptionAlgorithm)) + { + throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(EncryptionAlgorithm)); + } + if (configuration.EncryptionAlgorithmKeySize < 0) + { + throw Error.Common_PropertyMustBeNonNegative(nameof(configuration.EncryptionAlgorithmKeySize)); + } + + _logger.OpeningCNGAlgorithmFromProviderWithChainingModeCBC(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider); + + BCryptAlgorithmHandle algorithmHandle = null; + + // Special-case cached providers + if (configuration.EncryptionAlgorithmProvider == null) + { + if (configuration.EncryptionAlgorithm == Constants.BCRYPT_AES_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.AES_CBC; } + } + + // Look up the provider dynamically if we couldn't fetch a cached instance + if (algorithmHandle == null) + { + algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider); + algorithmHandle.SetChainingMode(Constants.BCRYPT_CHAIN_MODE_CBC); + } + + // make sure we're using a block cipher with an appropriate key size & block size + AlgorithmAssert.IsAllowableSymmetricAlgorithmBlockSize(checked(algorithmHandle.GetCipherBlockLength() * 8)); + AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked((uint)configuration.EncryptionAlgorithmKeySize)); + + // make sure the provided key length is valid + algorithmHandle.GetSupportedKeyLengths().EnsureValidKeyLength((uint)configuration.EncryptionAlgorithmKeySize); + + // all good! + return algorithmHandle; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorFactory.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorFactory.cs new file mode 100644 index 0000000000..39b6c0e55d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorFactory.cs @@ -0,0 +1,92 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + /// + /// An for . + /// + public sealed class CngGcmAuthenticatedEncryptorFactory : IAuthenticatedEncryptorFactory + { + private readonly ILogger _logger; + + public CngGcmAuthenticatedEncryptorFactory(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + } + + public IAuthenticatedEncryptor CreateEncryptorInstance(IKey key) + { + var descriptor = key.Descriptor as CngGcmAuthenticatedEncryptorDescriptor; + if (descriptor == null) + { + return null; + } + + return CreateAuthenticatedEncryptorInstance(descriptor.MasterKey, descriptor.Configuration); + } + + internal GcmAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance( + ISecret secret, + CngGcmAuthenticatedEncryptorConfiguration configuration) + { + if (configuration == null) + { + return null; + } + + return new GcmAuthenticatedEncryptor( + keyDerivationKey: new Secret(secret), + symmetricAlgorithmHandle: GetSymmetricBlockCipherAlgorithmHandle(configuration), + symmetricAlgorithmKeySizeInBytes: (uint)(configuration.EncryptionAlgorithmKeySize / 8)); + } + + private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle(CngGcmAuthenticatedEncryptorConfiguration configuration) + { + // basic argument checking + if (String.IsNullOrEmpty(configuration.EncryptionAlgorithm)) + { + throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(EncryptionAlgorithm)); + } + if (configuration.EncryptionAlgorithmKeySize < 0) + { + throw Error.Common_PropertyMustBeNonNegative(nameof(configuration.EncryptionAlgorithmKeySize)); + } + + BCryptAlgorithmHandle algorithmHandle = null; + + _logger?.OpeningCNGAlgorithmFromProviderWithChainingModeGCM(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider); + // Special-case cached providers + if (configuration.EncryptionAlgorithmProvider == null) + { + if (configuration.EncryptionAlgorithm == Constants.BCRYPT_AES_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.AES_GCM; } + } + + // Look up the provider dynamically if we couldn't fetch a cached instance + if (algorithmHandle == null) + { + algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider); + algorithmHandle.SetChainingMode(Constants.BCRYPT_CHAIN_MODE_GCM); + } + + // make sure we're using a block cipher with an appropriate key size & block size + CryptoUtil.Assert(algorithmHandle.GetCipherBlockLength() == 128 / 8, "GCM requires a block cipher algorithm with a 128-bit block size."); + AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked((uint)configuration.EncryptionAlgorithmKeySize)); + + // make sure the provided key length is valid + algorithmHandle.GetSupportedKeyLengths().EnsureValidKeyLength((uint)configuration.EncryptionAlgorithmKeySize); + + // all good! + return algorithmHandle; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AlgorithmConfiguration.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AlgorithmConfiguration.cs new file mode 100644 index 0000000000..4fddb0a706 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AlgorithmConfiguration.cs @@ -0,0 +1,20 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public abstract class AlgorithmConfiguration + { + internal const int KDK_SIZE_IN_BYTES = 512 / 8; + + /// + /// Creates a new instance based on this + /// configuration. The newly-created instance contains unique key material and is distinct + /// from all other descriptors created by the method. + /// + /// A unique . + public abstract IAuthenticatedEncryptorDescriptor CreateNewDescriptor(); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorConfiguration.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorConfiguration.cs new file mode 100644 index 0000000000..606d7484fb --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorConfiguration.cs @@ -0,0 +1,59 @@ +// 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.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// Represents a generalized authenticated encryption mechanism. + /// + public sealed class AuthenticatedEncryptorConfiguration : AlgorithmConfiguration, IInternalAlgorithmConfiguration + { + /// + /// The algorithm to use for symmetric encryption (confidentiality). + /// + /// + /// The default value is . + /// + public EncryptionAlgorithm EncryptionAlgorithm { get; set; } = EncryptionAlgorithm.AES_256_CBC; + + /// + /// The algorithm to use for message authentication (tamper-proofing). + /// + /// + /// The default value is . + /// This property is ignored if specifies a 'GCM' algorithm. + /// + public ValidationAlgorithm ValidationAlgorithm { get; set; } = ValidationAlgorithm.HMACSHA256; + + public override IAuthenticatedEncryptorDescriptor CreateNewDescriptor() + { + var internalConfiguration = (IInternalAlgorithmConfiguration)this; + return internalConfiguration.CreateDescriptorFromSecret(Secret.Random(KDK_SIZE_IN_BYTES)); + } + + IAuthenticatedEncryptorDescriptor IInternalAlgorithmConfiguration.CreateDescriptorFromSecret(ISecret secret) + { + return new AuthenticatedEncryptorDescriptor(this, secret); + } + + void IInternalAlgorithmConfiguration.Validate() + { + var factory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + // Run a sample payload through an encrypt -> decrypt operation to make sure data round-trips properly. + var encryptor = factory.CreateAuthenticatedEncryptorInstance(Secret.Random(512 / 8), this); + try + { + encryptor.PerformSelfTest(); + } + finally + { + (encryptor as IDisposable)?.Dispose(); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptor.cs new file mode 100644 index 0000000000..9539c9eb76 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptor.cs @@ -0,0 +1,59 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A descriptor which can create an authenticated encryption system based upon the + /// configuration provided by an object. + /// + public sealed class AuthenticatedEncryptorDescriptor : IAuthenticatedEncryptorDescriptor + { + public AuthenticatedEncryptorDescriptor(AuthenticatedEncryptorConfiguration configuration, ISecret masterKey) + { + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + if (masterKey == null) + { + throw new ArgumentNullException(nameof(masterKey)); + } + + Configuration = configuration; + MasterKey = masterKey; + } + + internal ISecret MasterKey { get; } + + internal AuthenticatedEncryptorConfiguration Configuration { get; } + + public XmlSerializedDescriptorInfo ExportToXml() + { + // + // + // + // ... + // + + var encryptionElement = new XElement("encryption", + new XAttribute("algorithm", Configuration.EncryptionAlgorithm)); + + var validationElement = (AuthenticatedEncryptorFactory.IsGcmAlgorithm(Configuration.EncryptionAlgorithm)) + ? (object)new XComment(" AES-GCM includes a 128-bit authentication tag, no extra validation algorithm required. ") + : (object)new XElement("validation", + new XAttribute("algorithm", Configuration.ValidationAlgorithm)); + + var outerElement = new XElement("descriptor", + encryptionElement, + validationElement, + MasterKey.ToMasterKeyElement()); + + return new XmlSerializedDescriptorInfo(outerElement, typeof(AuthenticatedEncryptorDescriptorDeserializer)); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs new file mode 100644 index 0000000000..96737b75c3 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs @@ -0,0 +1,48 @@ +// 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 System.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A class that can deserialize an that represents the serialized version + /// of an . + /// + public sealed class AuthenticatedEncryptorDescriptorDeserializer : IAuthenticatedEncryptorDescriptorDeserializer + { + /// + /// Imports the from serialized XML. + /// + public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) + { + if (element == null) + { + throw new ArgumentNullException(nameof(element)); + } + + // + // + // + // ... + // + + var configuration = new AuthenticatedEncryptorConfiguration(); + + var encryptionElement = element.Element("encryption"); + configuration.EncryptionAlgorithm = (EncryptionAlgorithm)Enum.Parse(typeof(EncryptionAlgorithm), (string)encryptionElement.Attribute("algorithm")); + + // only read if not GCM + if (!AuthenticatedEncryptorFactory.IsGcmAlgorithm(configuration.EncryptionAlgorithm)) + { + var validationElement = element.Element("validation"); + configuration.ValidationAlgorithm = (ValidationAlgorithm)Enum.Parse(typeof(ValidationAlgorithm), (string)validationElement.Attribute("algorithm")); + } + + Secret masterKey = ((string)element.Elements("masterKey").Single()).ToSecret(); + return new AuthenticatedEncryptorDescriptor(configuration, masterKey); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfiguration.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfiguration.cs new file mode 100644 index 0000000000..1c23957db2 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfiguration.cs @@ -0,0 +1,100 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// Represents a configured authenticated encryption mechanism which uses + /// Windows CNG algorithms in CBC encryption + HMAC authentication modes. + /// + public sealed class CngCbcAuthenticatedEncryptorConfiguration : AlgorithmConfiguration, IInternalAlgorithmConfiguration + { + /// + /// The name of the algorithm to use for symmetric encryption. + /// This property corresponds to the 'pszAlgId' parameter of BCryptOpenAlgorithmProvider. + /// This property is required to have a value. + /// + /// + /// The algorithm must support CBC-style encryption and must have a block size of 64 bits + /// or greater. + /// The default value is 'AES'. + /// + [ApplyPolicy] + public string EncryptionAlgorithm { get; set; } = Constants.BCRYPT_AES_ALGORITHM; + + /// + /// The name of the provider which contains the implementation of the symmetric encryption algorithm. + /// This property corresponds to the 'pszImplementation' parameter of BCryptOpenAlgorithmProvider. + /// This property is optional. + /// + /// + /// The default value is null. + /// + [ApplyPolicy] + public string EncryptionAlgorithmProvider { get; set; } = null; + + /// + /// The length (in bits) of the key that will be used for symmetric encryption. + /// This property is required to have a value. + /// + /// + /// The key length must be 128 bits or greater. + /// The default value is 256. + /// + [ApplyPolicy] + public int EncryptionAlgorithmKeySize { get; set; } = 256; + + /// + /// The name of the algorithm to use for hashing data. + /// This property corresponds to the 'pszAlgId' parameter of BCryptOpenAlgorithmProvider. + /// This property is required to have a value. + /// + /// + /// The algorithm must support being opened in HMAC mode and must have a digest length + /// of 128 bits or greater. + /// The default value is 'SHA256'. + /// + [ApplyPolicy] + public string HashAlgorithm { get; set; } = Constants.BCRYPT_SHA256_ALGORITHM; + + /// + /// The name of the provider which contains the implementation of the hash algorithm. + /// This property corresponds to the 'pszImplementation' parameter of BCryptOpenAlgorithmProvider. + /// This property is optional. + /// + /// + /// The default value is null. + /// + [ApplyPolicy] + public string HashAlgorithmProvider { get; set; } = null; + + public override IAuthenticatedEncryptorDescriptor CreateNewDescriptor() + { + var internalConfiguration = (IInternalAlgorithmConfiguration)this; + return internalConfiguration.CreateDescriptorFromSecret(Secret.Random(KDK_SIZE_IN_BYTES)); + } + + IAuthenticatedEncryptorDescriptor IInternalAlgorithmConfiguration.CreateDescriptorFromSecret(ISecret secret) + { + return new CngCbcAuthenticatedEncryptorDescriptor(this, secret); + } + + /// + /// Validates that this is well-formed, i.e., + /// that the specified algorithms actually exist and that they can be instantiated properly. + /// An exception will be thrown if validation fails. + /// + void IInternalAlgorithmConfiguration.Validate() + { + var factory = new CngCbcAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + // Run a sample payload through an encrypt -> decrypt operation to make sure data round-trips properly. + using (var encryptor = factory.CreateAuthenticatedEncryptorInstance(Secret.Random(512 / 8), this)) + { + encryptor.PerformSelfTest(); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptor.cs new file mode 100644 index 0000000000..0003f948ae --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptor.cs @@ -0,0 +1,68 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A descriptor which can create an authenticated encryption system based upon the + /// configuration provided by an object. + /// + public sealed class CngCbcAuthenticatedEncryptorDescriptor : IAuthenticatedEncryptorDescriptor + { + public CngCbcAuthenticatedEncryptorDescriptor(CngCbcAuthenticatedEncryptorConfiguration configuration, ISecret masterKey) + { + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + if (masterKey == null) + { + throw new ArgumentNullException(nameof(masterKey)); + } + + Configuration = configuration; + MasterKey = masterKey; + } + + internal ISecret MasterKey { get; } + + internal CngCbcAuthenticatedEncryptorConfiguration Configuration { get; } + + public XmlSerializedDescriptorInfo ExportToXml() + { + // + // + // + // + // ... + // + + var encryptionElement = new XElement("encryption", + new XAttribute("algorithm", Configuration.EncryptionAlgorithm), + new XAttribute("keyLength", Configuration.EncryptionAlgorithmKeySize)); + if (Configuration.EncryptionAlgorithmProvider != null) + { + encryptionElement.SetAttributeValue("provider", Configuration.EncryptionAlgorithmProvider); + } + + var hashElement = new XElement("hash", + new XAttribute("algorithm", Configuration.HashAlgorithm)); + if (Configuration.HashAlgorithmProvider != null) + { + hashElement.SetAttributeValue("provider", Configuration.HashAlgorithmProvider); + } + + var rootElement = new XElement("descriptor", + new XComment(" Algorithms provided by Windows CNG, using CBC-mode encryption with HMAC validation "), + encryptionElement, + hashElement, + MasterKey.ToMasterKeyElement()); + + return new XmlSerializedDescriptorInfo(rootElement, typeof(CngCbcAuthenticatedEncryptorDescriptorDeserializer)); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs new file mode 100644 index 0000000000..534604839a --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs @@ -0,0 +1,48 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A class that can deserialize an that represents the serialized version + /// of an . + /// + public sealed class CngCbcAuthenticatedEncryptorDescriptorDeserializer : IAuthenticatedEncryptorDescriptorDeserializer + { + /// + /// Imports the from serialized XML. + /// + public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) + { + if (element == null) + { + throw new ArgumentNullException(nameof(element)); + } + + // + // + // + // + // ... + // + + var configuration = new CngCbcAuthenticatedEncryptorConfiguration(); + + var encryptionElement = element.Element("encryption"); + configuration.EncryptionAlgorithm = (string)encryptionElement.Attribute("algorithm"); + configuration.EncryptionAlgorithmKeySize = (int)encryptionElement.Attribute("keyLength"); + configuration.EncryptionAlgorithmProvider = (string)encryptionElement.Attribute("provider"); // could be null + + var hashElement = element.Element("hash"); + configuration.HashAlgorithm = (string)hashElement.Attribute("algorithm"); + configuration.HashAlgorithmProvider = (string)hashElement.Attribute("provider"); // could be null + + Secret masterKey = ((string)element.Element("masterKey")).ToSecret(); + + return new CngCbcAuthenticatedEncryptorDescriptor(configuration, masterKey); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfiguration.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfiguration.cs new file mode 100644 index 0000000000..d9c1f84718 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfiguration.cs @@ -0,0 +1,76 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// Represents a configured authenticated encryption mechanism which uses + /// Windows CNG algorithms in GCM encryption + authentication modes. + /// + public sealed class CngGcmAuthenticatedEncryptorConfiguration : AlgorithmConfiguration, IInternalAlgorithmConfiguration + { + /// + /// The name of the algorithm to use for symmetric encryption. + /// This property corresponds to the 'pszAlgId' parameter of BCryptOpenAlgorithmProvider. + /// This property is required to have a value. + /// + /// + /// The algorithm must support GCM-style encryption and must have a block size exactly + /// 128 bits. + /// The default value is 'AES'. + /// + [ApplyPolicy] + public string EncryptionAlgorithm { get; set; } = Constants.BCRYPT_AES_ALGORITHM; + + /// + /// The name of the provider which contains the implementation of the symmetric encryption algorithm. + /// This property corresponds to the 'pszImplementation' parameter of BCryptOpenAlgorithmProvider. + /// This property is optional. + /// + /// + /// The default value is null. + /// + [ApplyPolicy] + public string EncryptionAlgorithmProvider { get; set; } = null; + + /// + /// The length (in bits) of the key that will be used for symmetric encryption. + /// This property is required to have a value. + /// + /// + /// The key length must be 128 bits or greater. + /// The default value is 256. + /// + [ApplyPolicy] + public int EncryptionAlgorithmKeySize { get; set; } = 256; + + public override IAuthenticatedEncryptorDescriptor CreateNewDescriptor() + { + var internalConfiguration = (IInternalAlgorithmConfiguration)this; + return internalConfiguration.CreateDescriptorFromSecret(Secret.Random(KDK_SIZE_IN_BYTES)); + } + + IAuthenticatedEncryptorDescriptor IInternalAlgorithmConfiguration.CreateDescriptorFromSecret(ISecret secret) + { + return new CngGcmAuthenticatedEncryptorDescriptor(this, secret); + } + + /// + /// Validates that this is well-formed, i.e., + /// that the specified algorithm actually exists and can be instantiated properly. + /// An exception will be thrown if validation fails. + /// + void IInternalAlgorithmConfiguration.Validate() + { + var factory = new CngGcmAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + // Run a sample payload through an encrypt -> decrypt operation to make sure data round-trips properly. + using (var encryptor = factory.CreateAuthenticatedEncryptorInstance(Secret.Random(512 / 8), this)) + { + encryptor.PerformSelfTest(); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptor.cs new file mode 100644 index 0000000000..28c0103a95 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptor.cs @@ -0,0 +1,60 @@ +// 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.Xml.Linq; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A descriptor which can create an authenticated encryption system based upon the + /// configuration provided by an object. + /// + public sealed class CngGcmAuthenticatedEncryptorDescriptor : IAuthenticatedEncryptorDescriptor + { + public CngGcmAuthenticatedEncryptorDescriptor(CngGcmAuthenticatedEncryptorConfiguration configuration, ISecret masterKey) + { + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + if (masterKey == null) + { + throw new ArgumentNullException(nameof(masterKey)); + } + + Configuration = configuration; + MasterKey = masterKey; + } + + internal ISecret MasterKey { get; } + + internal CngGcmAuthenticatedEncryptorConfiguration Configuration { get; } + + public XmlSerializedDescriptorInfo ExportToXml() + { + // + // + // + // ... + // + + var encryptionElement = new XElement("encryption", + new XAttribute("algorithm", Configuration.EncryptionAlgorithm), + new XAttribute("keyLength", Configuration.EncryptionAlgorithmKeySize)); + if (Configuration.EncryptionAlgorithmProvider != null) + { + encryptionElement.SetAttributeValue("provider", Configuration.EncryptionAlgorithmProvider); + } + + var rootElement = new XElement("descriptor", + new XComment(" Algorithms provided by Windows CNG, using Galois/Counter Mode encryption and validation "), + encryptionElement, + MasterKey.ToMasterKeyElement()); + + return new XmlSerializedDescriptorInfo(rootElement, typeof(CngGcmAuthenticatedEncryptorDescriptorDeserializer)); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs new file mode 100644 index 0000000000..0981fb55af --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs @@ -0,0 +1,44 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A class that can deserialize an that represents the serialized version + /// of an . + /// + public sealed class CngGcmAuthenticatedEncryptorDescriptorDeserializer : IAuthenticatedEncryptorDescriptorDeserializer + { + + /// + /// Imports the from serialized XML. + /// + public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) + { + if (element == null) + { + throw new ArgumentNullException(nameof(element)); + } + + // + // + // + // ... + // + + var configuration = new CngGcmAuthenticatedEncryptorConfiguration(); + + var encryptionElement = element.Element("encryption"); + configuration.EncryptionAlgorithm = (string)encryptionElement.Attribute("algorithm"); + configuration.EncryptionAlgorithmKeySize = (int)encryptionElement.Attribute("keyLength"); + configuration.EncryptionAlgorithmProvider = (string)encryptionElement.Attribute("provider"); // could be null + + Secret masterKey = ((string)element.Element("masterKey")).ToSecret(); + + return new CngGcmAuthenticatedEncryptorDescriptor(configuration, masterKey); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptor.cs new file mode 100644 index 0000000000..6176929583 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptor.cs @@ -0,0 +1,30 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A self-contained descriptor that wraps all information (including secret key + /// material) necessary to create an instance of an . + /// + public interface IAuthenticatedEncryptorDescriptor + { + /// + /// Exports the current descriptor to XML. + /// + /// + /// An wrapping the which represents the serialized + /// current descriptor object. The deserializer type must be assignable to . + /// + /// + /// If an element contains sensitive information (such as key material), the + /// element should be marked via the + /// extension method, and the caller should encrypt the element before persisting + /// the XML to storage. + /// + XmlSerializedDescriptorInfo ExportToXml(); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptorDeserializer.cs new file mode 100644 index 0000000000..c1db3bcc91 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptorDeserializer.cs @@ -0,0 +1,20 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// The basic interface for deserializing an XML element into an . + /// + public interface IAuthenticatedEncryptorDescriptorDeserializer + { + /// + /// Deserializes the specified XML element. + /// + /// The element to deserialize. + /// The represented by . + IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/IInternalAlgorithmConfiguration.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/IInternalAlgorithmConfiguration.cs new file mode 100644 index 0000000000..ede736e99d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/IInternalAlgorithmConfiguration.cs @@ -0,0 +1,27 @@ +// 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. + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A type that knows how to create instances of an + /// given specific secret key material. + /// + /// + /// This type is not public because we don't want to lock ourselves into a contract stating + /// that a descriptor is simply a configuration plus a single serializable, reproducible secret. + /// + internal interface IInternalAlgorithmConfiguration + { + /// + /// Creates a new instance from this configuration + /// given specific secret key material. + /// + IAuthenticatedEncryptorDescriptor CreateDescriptorFromSecret(ISecret secret); + + /// + /// Performs a self-test of the algorithm specified by the configuration object. + /// + void Validate(); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfiguration.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfiguration.cs new file mode 100644 index 0000000000..dad6cd9dbc --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfiguration.cs @@ -0,0 +1,108 @@ +// 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.Security.Cryptography; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// Represents a configured authenticated encryption mechanism which uses + /// managed and + /// types. + /// + public sealed class ManagedAuthenticatedEncryptorConfiguration : AlgorithmConfiguration, IInternalAlgorithmConfiguration + { + /// + /// The type of the algorithm to use for symmetric encryption. + /// The type must subclass . + /// This property is required to have a value. + /// + /// + /// The algorithm must support CBC-style encryption and PKCS#7 padding and must have a block size of 64 bits or greater. + /// The default algorithm is AES. + /// + [ApplyPolicy] + public Type EncryptionAlgorithmType { get; set; } = typeof(Aes); + + /// + /// The length (in bits) of the key that will be used for symmetric encryption. + /// This property is required to have a value. + /// + /// + /// The key length must be 128 bits or greater. + /// The default value is 256. + /// + [ApplyPolicy] + public int EncryptionAlgorithmKeySize { get; set; } = 256; + + /// + /// The type of the algorithm to use for validation. + /// Type type must subclass . + /// This property is required to have a value. + /// + /// + /// The algorithm must have a digest length of 128 bits or greater. + /// The default algorithm is HMACSHA256. + /// + [ApplyPolicy] + public Type ValidationAlgorithmType { get; set; } = typeof(HMACSHA256); + + public override IAuthenticatedEncryptorDescriptor CreateNewDescriptor() + { + var internalConfiguration = (IInternalAlgorithmConfiguration)this; + return internalConfiguration.CreateDescriptorFromSecret(Secret.Random(KDK_SIZE_IN_BYTES)); + } + + IAuthenticatedEncryptorDescriptor IInternalAlgorithmConfiguration.CreateDescriptorFromSecret(ISecret secret) + { + return new ManagedAuthenticatedEncryptorDescriptor(this, secret); + } + + /// + /// Validates that this is well-formed, i.e., + /// that the specified algorithms actually exist and can be instantiated properly. + /// An exception will be thrown if validation fails. + /// + void IInternalAlgorithmConfiguration.Validate() + { + var factory = new ManagedAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + // Run a sample payload through an encrypt -> decrypt operation to make sure data round-trips properly. + using (var encryptor = factory.CreateAuthenticatedEncryptorInstance(Secret.Random(512 / 8), this)) + { + encryptor.PerformSelfTest(); + } + } + + // Any changes to this method should also be be reflected + // in ManagedAuthenticatedEncryptorDescriptorDeserializer.FriendlyNameToType. + private static string TypeToFriendlyName(Type type) + { + if (type == typeof(Aes)) + { + return nameof(Aes); + } + else if (type == typeof(HMACSHA1)) + { + return nameof(HMACSHA1); + } + else if (type == typeof(HMACSHA256)) + { + return nameof(HMACSHA256); + } + else if (type == typeof(HMACSHA384)) + { + return nameof(HMACSHA384); + } + else if (type == typeof(HMACSHA512)) + { + return nameof(HMACSHA512); + } + else + { + return type.AssemblyQualifiedName; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptor.cs new file mode 100644 index 0000000000..2061115b42 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptor.cs @@ -0,0 +1,91 @@ +// 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.Security.Cryptography; +using System.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A descriptor which can create an authenticated encryption system based upon the + /// configuration provided by an object. + /// + public sealed class ManagedAuthenticatedEncryptorDescriptor : IAuthenticatedEncryptorDescriptor + { + public ManagedAuthenticatedEncryptorDescriptor(ManagedAuthenticatedEncryptorConfiguration configuration, ISecret masterKey) + { + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + if (masterKey == null) + { + throw new ArgumentNullException(nameof(masterKey)); + } + + Configuration = configuration; + MasterKey = masterKey; + } + + internal ISecret MasterKey { get; } + + internal ManagedAuthenticatedEncryptorConfiguration Configuration { get; } + + public XmlSerializedDescriptorInfo ExportToXml() + { + // + // + // + // + // ... + // + + var encryptionElement = new XElement("encryption", + new XAttribute("algorithm", TypeToFriendlyName(Configuration.EncryptionAlgorithmType)), + new XAttribute("keyLength", Configuration.EncryptionAlgorithmKeySize)); + + var validationElement = new XElement("validation", + new XAttribute("algorithm", TypeToFriendlyName(Configuration.ValidationAlgorithmType))); + + var rootElement = new XElement("descriptor", + new XComment(" Algorithms provided by specified SymmetricAlgorithm and KeyedHashAlgorithm "), + encryptionElement, + validationElement, + MasterKey.ToMasterKeyElement()); + + return new XmlSerializedDescriptorInfo(rootElement, typeof(ManagedAuthenticatedEncryptorDescriptorDeserializer)); + } + + // Any changes to this method should also be be reflected + // in ManagedAuthenticatedEncryptorDescriptorDeserializer.FriendlyNameToType. + private static string TypeToFriendlyName(Type type) + { + if (type == typeof(Aes)) + { + return nameof(Aes); + } + else if (type == typeof(HMACSHA1)) + { + return nameof(HMACSHA1); + } + else if (type == typeof(HMACSHA256)) + { + return nameof(HMACSHA256); + } + else if (type == typeof(HMACSHA384)) + { + return nameof(HMACSHA384); + } + else if (type == typeof(HMACSHA512)) + { + return nameof(HMACSHA512); + } + else + { + return type.AssemblyQualifiedName; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs new file mode 100644 index 0000000000..0f09c3a52e --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs @@ -0,0 +1,77 @@ +// 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.Security.Cryptography; +using System.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// A class that can deserialize an that represents the serialized version + /// of an . + /// + public sealed class ManagedAuthenticatedEncryptorDescriptorDeserializer : IAuthenticatedEncryptorDescriptorDeserializer + { + /// + /// Imports the from serialized XML. + /// + public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) + { + if (element == null) + { + throw new ArgumentNullException(nameof(element)); + } + + // + // + // + // + // ... + // + + var configuration = new ManagedAuthenticatedEncryptorConfiguration(); + + var encryptionElement = element.Element("encryption"); + configuration.EncryptionAlgorithmType = FriendlyNameToType((string)encryptionElement.Attribute("algorithm")); + configuration.EncryptionAlgorithmKeySize = (int)encryptionElement.Attribute("keyLength"); + + var validationElement = element.Element("validation"); + configuration.ValidationAlgorithmType = FriendlyNameToType((string)validationElement.Attribute("algorithm")); + + Secret masterKey = ((string)element.Element("masterKey")).ToSecret(); + + return new ManagedAuthenticatedEncryptorDescriptor(configuration, masterKey); + } + + // Any changes to this method should also be be reflected + // in ManagedAuthenticatedEncryptorDescriptor.TypeToFriendlyName. + private static Type FriendlyNameToType(string typeName) + { + if (typeName == nameof(Aes)) + { + return typeof(Aes); + } + else if (typeName == nameof(HMACSHA1)) + { + return typeof(HMACSHA1); + } + else if (typeName == nameof(HMACSHA256)) + { + return typeof(HMACSHA256); + } + else if (typeName == nameof(HMACSHA384)) + { + return typeof(HMACSHA384); + } + else if (typeName == nameof(HMACSHA512)) + { + return typeof(HMACSHA512); + } + else + { + return Type.GetType(typeName, throwOnError: true); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/SecretExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/SecretExtensions.cs new file mode 100644 index 0000000000..75444140c8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/SecretExtensions.cs @@ -0,0 +1,63 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + internal unsafe static class SecretExtensions + { + /// + /// Converts an to an <masterKey> element which is marked + /// as requiring encryption. + /// + /// + public static XElement ToMasterKeyElement(this ISecret secret) + { + // Technically we'll be keeping the unprotected secret around in memory as + // a string, so it can get moved by the GC, but we should be good citizens + // and try to pin / clear our our temporary buffers regardless. + byte[] unprotectedSecretRawBytes = new byte[secret.Length]; + string unprotectedSecretAsBase64String; + fixed (byte* __unused__ = unprotectedSecretRawBytes) + { + try + { + secret.WriteSecretIntoBuffer(new ArraySegment(unprotectedSecretRawBytes)); + unprotectedSecretAsBase64String = Convert.ToBase64String(unprotectedSecretRawBytes); + } + finally + { + Array.Clear(unprotectedSecretRawBytes, 0, unprotectedSecretRawBytes.Length); + } + } + + var masterKeyElement = new XElement("masterKey", + new XComment(" Warning: the key below is in an unencrypted form. "), + new XElement("value", unprotectedSecretAsBase64String)); + masterKeyElement.MarkAsRequiresEncryption(); + return masterKeyElement; + } + + /// + /// Converts a base64-encoded string into an . + /// + /// + public static Secret ToSecret(this string base64String) + { + byte[] unprotectedSecret = Convert.FromBase64String(base64String); + fixed (byte* __unused__ = unprotectedSecret) + { + try + { + return new Secret(unprotectedSecret); + } + finally + { + Array.Clear(unprotectedSecret, 0, unprotectedSecret.Length); + } + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/XmlExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/XmlExtensions.cs new file mode 100644 index 0000000000..572a0cba59 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/XmlExtensions.cs @@ -0,0 +1,30 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public static class XmlExtensions + { + internal static bool IsMarkedAsRequiringEncryption(this XElement element) + { + return ((bool?)element.Attribute(XmlConstants.RequiresEncryptionAttributeName)).GetValueOrDefault(); + } + + /// + /// Marks the provided as requiring encryption before being persisted + /// to storage. Use when implementing . + /// + public static void MarkAsRequiresEncryption(this XElement element) + { + if (element == null) + { + throw new ArgumentNullException(nameof(element)); + } + + element.SetAttributeValue(XmlConstants.RequiresEncryptionAttributeName, true); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/XmlSerializedDescriptorInfo.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/XmlSerializedDescriptorInfo.cs new file mode 100644 index 0000000000..1b935d8e15 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ConfigurationModel/XmlSerializedDescriptorInfo.cs @@ -0,0 +1,57 @@ +// 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.Reflection; +using System.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + /// + /// Wraps an that contains the XML-serialized representation of an + /// along with the type that can be used + /// to deserialize it. + /// + public sealed class XmlSerializedDescriptorInfo + { + /// + /// Creates an instance of an . + /// + /// The XML-serialized form of the . + /// The class whose + /// method can be used to deserialize . + public XmlSerializedDescriptorInfo(XElement serializedDescriptorElement, Type deserializerType) + { + if (serializedDescriptorElement == null) + { + throw new ArgumentNullException(nameof(serializedDescriptorElement)); + } + + if (deserializerType == null) + { + throw new ArgumentNullException(nameof(deserializerType)); + } + + if (!typeof(IAuthenticatedEncryptorDescriptorDeserializer).IsAssignableFrom(deserializerType)) + { + throw new ArgumentException( + Resources.FormatTypeExtensions_BadCast(deserializerType.FullName, typeof(IAuthenticatedEncryptorDescriptorDeserializer).FullName), + nameof(deserializerType)); + } + + SerializedDescriptorElement = serializedDescriptorElement; + DeserializerType = deserializerType; + } + + /// + /// The class whose + /// method can be used to deserialize the value stored in . + /// + public Type DeserializerType { get; } + + /// + /// An XML-serialized representation of an . + /// + public XElement SerializedDescriptorElement { get; } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/EncryptionAlgorithm.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/EncryptionAlgorithm.cs new file mode 100644 index 0000000000..d6fbf28020 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/EncryptionAlgorithm.cs @@ -0,0 +1,52 @@ +// 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. + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + /// + /// Specifies a symmetric encryption algorithm to use for providing confidentiality + /// to protected payloads. + /// + public enum EncryptionAlgorithm + { + /// + /// The AES algorithm (FIPS 197) with a 128-bit key running in Cipher Block Chaining mode. + /// + AES_128_CBC, + + /// + /// The AES algorithm (FIPS 197) with a 192-bit key running in Cipher Block Chaining mode. + /// + AES_192_CBC, + + /// + /// The AES algorithm (FIPS 197) with a 256-bit key running in Cipher Block Chaining mode. + /// + AES_256_CBC, + + /// + /// The AES algorithm (FIPS 197) with a 128-bit key running in Galois/Counter Mode (FIPS SP 800-38D). + /// + /// + /// This cipher mode produces a 128-bit authentication tag. This algorithm is currently only + /// supported on Windows. + /// + AES_128_GCM, + + /// + /// The AES algorithm (FIPS 197) with a 192-bit key running in Galois/Counter Mode (FIPS SP 800-38D). + /// + /// + /// This cipher mode produces a 128-bit authentication tag. + /// + AES_192_GCM, + + /// + /// The AES algorithm (FIPS 197) with a 256-bit key running in Galois/Counter Mode (FIPS SP 800-38D). + /// + /// + /// This cipher mode produces a 128-bit authentication tag. + /// + AES_256_GCM, + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/IAuthenticatedEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/IAuthenticatedEncryptor.cs new file mode 100644 index 0000000000..5ec2fa8444 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/IAuthenticatedEncryptor.cs @@ -0,0 +1,36 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + /// + /// The basic interface for providing an authenticated encryption and decryption routine. + /// + public interface IAuthenticatedEncryptor + { + /// + /// Validates the authentication tag of and decrypts a blob of encrypted data. + /// + /// The ciphertext (including authentication tag) to decrypt. + /// Any ancillary data which was used during computation + /// of the authentication tag. The same AAD must have been specified in the corresponding + /// call to 'Encrypt'. + /// The original plaintext data (if the authentication tag was validated and decryption succeeded). + /// All cryptography-related exceptions should be homogenized to CryptographicException. + byte[] Decrypt(ArraySegment ciphertext, ArraySegment additionalAuthenticatedData); + + /// + /// Encrypts and tamper-proofs a piece of data. + /// + /// The plaintext to encrypt. This input may be zero bytes in length. + /// A piece of data which will not be included in + /// the returned ciphertext but which will still be covered by the authentication tag. + /// This input may be zero bytes in length. The same AAD must be specified in the corresponding + /// call to Decrypt. + /// The ciphertext blob, including authentication tag. + /// All cryptography-related exceptions should be homogenized to CryptographicException. + byte[] Encrypt(ArraySegment plaintext, ArraySegment additionalAuthenticatedData); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/IAuthenticatedEncryptorFactory.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/IAuthenticatedEncryptorFactory.cs new file mode 100644 index 0000000000..b66f14422c --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/IAuthenticatedEncryptorFactory.cs @@ -0,0 +1,22 @@ +// 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 Microsoft.AspNetCore.DataProtection.KeyManagement; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + public interface IAuthenticatedEncryptorFactory + { + /// + /// Creates an instance based on the given . + /// + /// An instance. + /// + /// For a given , any two instances returned by this method should + /// be considered equivalent, e.g., the payload returned by one's + /// method should be consumable by the other's method. + /// + IAuthenticatedEncryptor CreateEncryptorInstance(IKey key); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/IOptimizedAuthenticatedEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/IOptimizedAuthenticatedEncryptor.cs new file mode 100644 index 0000000000..3cc0a7ca92 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/IOptimizedAuthenticatedEncryptor.cs @@ -0,0 +1,42 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + /// + /// An optimized encryptor that can avoid buffer allocations in common code paths. + /// + internal interface IOptimizedAuthenticatedEncryptor : IAuthenticatedEncryptor + { + /// + /// Encrypts and tamper-proofs a piece of data. + /// + /// The plaintext to encrypt. This input may be zero bytes in length. + /// A piece of data which will not be included in + /// the returned ciphertext but which will still be covered by the authentication tag. + /// This input may be zero bytes in length. The same AAD must be specified in the corresponding + /// call to Decrypt. + /// The number of bytes to pad before the ciphertext in the output. + /// The number of bytes to pad after the ciphertext in the output. + /// + /// The ciphertext blob, including authentication tag. The ciphertext blob will be surrounded by + /// the number of padding bytes requested. For instance, if the given (plaintext, AAD) input results + /// in a (ciphertext, auth tag) output of 0x0102030405, and if 'preBufferSize' is 3 and + /// 'postBufferSize' is 5, then the return value will be 0xYYYYYY0102030405ZZZZZZZZZZ, where bytes + /// YY and ZZ are undefined. + /// + /// + /// This method allows for a slight performance improvement over IAuthenticatedEncryptor.Encrypt + /// in the case where the caller needs to prepend or append some data to the resulting ciphertext. + /// For instance, if the caller needs to append a 32-bit header to the resulting ciphertext, then + /// he can specify 4 for 'preBufferSize' and overwrite the first 32 bits of the buffer returned + /// by this function. This saves the caller from having to allocate a new buffer to hold the final + /// transformed result. + /// + /// All cryptography-related exceptions should be homogenized to CryptographicException. + /// + byte[] Encrypt(ArraySegment plaintext, ArraySegment additionalAuthenticatedData, uint preBufferSize, uint postBufferSize); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorFactory.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorFactory.cs new file mode 100644 index 0000000000..32fb4f44f4 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorFactory.cs @@ -0,0 +1,132 @@ +// 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.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Managed; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + /// + /// An for . + /// + public sealed class ManagedAuthenticatedEncryptorFactory : IAuthenticatedEncryptorFactory + { + private readonly ILogger _logger; + + public ManagedAuthenticatedEncryptorFactory(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + } + + public IAuthenticatedEncryptor CreateEncryptorInstance(IKey key) + { + var descriptor = key.Descriptor as ManagedAuthenticatedEncryptorDescriptor; + if (descriptor == null) + { + return null; + } + + return CreateAuthenticatedEncryptorInstance(descriptor.MasterKey, descriptor.Configuration); + } + + internal ManagedAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance( + ISecret secret, + ManagedAuthenticatedEncryptorConfiguration configuration) + { + if (configuration == null) + { + return null; + } + + return new ManagedAuthenticatedEncryptor( + keyDerivationKey: new Secret(secret), + symmetricAlgorithmFactory: GetSymmetricBlockCipherAlgorithmFactory(configuration), + symmetricAlgorithmKeySizeInBytes: configuration.EncryptionAlgorithmKeySize / 8, + validationAlgorithmFactory: GetKeyedHashAlgorithmFactory(configuration)); + } + + private Func GetKeyedHashAlgorithmFactory(ManagedAuthenticatedEncryptorConfiguration configuration) + { + // basic argument checking + if (configuration.ValidationAlgorithmType == null) + { + throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(configuration.ValidationAlgorithmType)); + } + + _logger.UsingManagedKeyedHashAlgorithm(configuration.ValidationAlgorithmType.FullName); + if (configuration.ValidationAlgorithmType == typeof(HMACSHA256)) + { + return () => new HMACSHA256(); + } + else if (configuration.ValidationAlgorithmType == typeof(HMACSHA512)) + { + return () => new HMACSHA512(); + } + else + { + return AlgorithmActivator.CreateFactory(configuration.ValidationAlgorithmType); + } + } + + private Func GetSymmetricBlockCipherAlgorithmFactory(ManagedAuthenticatedEncryptorConfiguration configuration) + { + // basic argument checking + if (configuration.EncryptionAlgorithmType == null) + { + throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(configuration.EncryptionAlgorithmType)); + } + typeof(SymmetricAlgorithm).AssertIsAssignableFrom(configuration.EncryptionAlgorithmType); + if (configuration.EncryptionAlgorithmKeySize < 0) + { + throw Error.Common_PropertyMustBeNonNegative(nameof(configuration.EncryptionAlgorithmKeySize)); + } + + _logger.UsingManagedSymmetricAlgorithm(configuration.EncryptionAlgorithmType.FullName); + + if (configuration.EncryptionAlgorithmType == typeof(Aes)) + { + Func factory = null; + if (OSVersionUtil.IsWindows()) + { + // If we're on desktop CLR and running on Windows, use the FIPS-compliant implementation. + factory = () => new AesCryptoServiceProvider(); + } + + return factory ?? Aes.Create; + } + else + { + return AlgorithmActivator.CreateFactory(configuration.EncryptionAlgorithmType); + } + } + + /// + /// Contains helper methods for generating cryptographic algorithm factories. + /// + private static class AlgorithmActivator + { + /// + /// Creates a factory that wraps a call to . + /// + public static Func CreateFactory(Type implementation) + { + return ((IActivator)Activator.CreateInstance(typeof(AlgorithmActivatorCore<>).MakeGenericType(implementation))).Creator; + } + + private interface IActivator + { + Func Creator { get; } + } + + private class AlgorithmActivatorCore : IActivator where T : new() + { + public Func Creator { get; } = Activator.CreateInstance; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ValidationAlgorithm.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ValidationAlgorithm.cs new file mode 100644 index 0000000000..520cb707a4 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/AuthenticatedEncryption/ValidationAlgorithm.cs @@ -0,0 +1,24 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + /// + /// Specifies a message authentication algorithm to use for providing tamper-proofing + /// to protected payloads. + /// + public enum ValidationAlgorithm + { + /// + /// The HMAC algorithm (RFC 2104) using the SHA-256 hash function (FIPS 180-4). + /// + HMACSHA256, + + /// + /// The HMAC algorithm (RFC 2104) using the SHA-512 hash function (FIPS 180-4). + /// + HMACSHA512, + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/BitHelpers.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/BitHelpers.cs new file mode 100644 index 0000000000..65e7415008 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/BitHelpers.cs @@ -0,0 +1,59 @@ +// 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.Runtime.CompilerServices; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal unsafe static class BitHelpers + { + /// + /// Writes an unsigned 32-bit value to a memory address, big-endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteTo(void* ptr, uint value) + { + byte* bytePtr = (byte*)ptr; + bytePtr[0] = (byte)(value >> 24); + bytePtr[1] = (byte)(value >> 16); + bytePtr[2] = (byte)(value >> 8); + bytePtr[3] = (byte)(value); + } + + /// + /// Writes an unsigned 32-bit value to a memory address, big-endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteTo(ref byte* ptr, uint value) + { + byte* pTemp = ptr; + pTemp[0] = (byte)(value >> 24); + pTemp[1] = (byte)(value >> 16); + pTemp[2] = (byte)(value >> 8); + pTemp[3] = (byte)(value); + ptr = &pTemp[4]; + } + + /// + /// Writes a signed 32-bit value to a memory address, big-endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteTo(byte[] buffer, ref int idx, int value) + { + WriteTo(buffer, ref idx, (uint)value); + } + + /// + /// Writes a signed 32-bit value to a memory address, big-endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteTo(byte[] buffer, ref int idx, uint value) + { + buffer[idx++] = (byte)(value >> 24); + buffer[idx++] = (byte)(value >> 16); + buffer[idx++] = (byte)(value >> 8); + buffer[idx++] = (byte)(value); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/BCryptGenRandomImpl.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/BCryptGenRandomImpl.cs new file mode 100644 index 0000000000..5bdceabb6d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/BCryptGenRandomImpl.cs @@ -0,0 +1,22 @@ +// 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 Microsoft.AspNetCore.Cryptography.Cng; + +namespace Microsoft.AspNetCore.DataProtection.Cng +{ + internal unsafe sealed class BCryptGenRandomImpl : IBCryptGenRandom + { + public static readonly BCryptGenRandomImpl Instance = new BCryptGenRandomImpl(); + + private BCryptGenRandomImpl() + { + } + + public void GenRandom(byte* pbBuffer, uint cbBuffer) + { + BCryptUtil.GenRandom(pbBuffer, cbBuffer); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/CbcAuthenticatedEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/CbcAuthenticatedEncryptor.cs new file mode 100644 index 0000000000..c8840beff4 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/CbcAuthenticatedEncryptor.cs @@ -0,0 +1,422 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.Cng.Internal; +using Microsoft.AspNetCore.DataProtection.SP800_108; + +namespace Microsoft.AspNetCore.DataProtection.Cng +{ + // An encryptor which does Encrypt(CBC) + HMAC using the Windows CNG (BCrypt*) APIs. + // The payloads produced by this encryptor should be compatible with the payloads + // produced by the managed Encrypt(CBC) + HMAC encryptor. + internal unsafe sealed class CbcAuthenticatedEncryptor : CngAuthenticatedEncryptorBase + { + // Even when IVs are chosen randomly, CBC is susceptible to IV collisions within a single + // key. For a 64-bit block cipher (like 3DES), we'd expect a collision after 2^32 block + // encryption operations, which a high-traffic web server might perform in mere hours. + // AES and other 128-bit block ciphers are less susceptible to this due to the larger IV + // space, but unfortunately some organizations require older 64-bit block ciphers. To address + // the collision issue, we'll feed 128 bits of entropy to the KDF when performing subkey + // generation. This creates >= 192 bits total entropy for each operation, so we shouldn't + // expect a collision until >= 2^96 operations. Even 2^80 operations still maintains a <= 2^-32 + // probability of collision, and this is acceptable for the expected KDK lifetime. + private const uint KEY_MODIFIER_SIZE_IN_BYTES = 128 / 8; + + private readonly byte[] _contextHeader; + private readonly IBCryptGenRandom _genRandom; + private readonly BCryptAlgorithmHandle _hmacAlgorithmHandle; + private readonly uint _hmacAlgorithmDigestLengthInBytes; + private readonly uint _hmacAlgorithmSubkeyLengthInBytes; + private readonly ISP800_108_CTR_HMACSHA512Provider _sp800_108_ctr_hmac_provider; + private readonly BCryptAlgorithmHandle _symmetricAlgorithmHandle; + private readonly uint _symmetricAlgorithmBlockSizeInBytes; + private readonly uint _symmetricAlgorithmSubkeyLengthInBytes; + + public CbcAuthenticatedEncryptor(Secret keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, BCryptAlgorithmHandle hmacAlgorithmHandle, IBCryptGenRandom genRandom = null) + { + _genRandom = genRandom ?? BCryptGenRandomImpl.Instance; + _sp800_108_ctr_hmac_provider = SP800_108_CTR_HMACSHA512Util.CreateProvider(keyDerivationKey); + _symmetricAlgorithmHandle = symmetricAlgorithmHandle; + _symmetricAlgorithmBlockSizeInBytes = symmetricAlgorithmHandle.GetCipherBlockLength(); + _symmetricAlgorithmSubkeyLengthInBytes = symmetricAlgorithmKeySizeInBytes; + _hmacAlgorithmHandle = hmacAlgorithmHandle; + _hmacAlgorithmDigestLengthInBytes = hmacAlgorithmHandle.GetHashDigestLength(); + _hmacAlgorithmSubkeyLengthInBytes = _hmacAlgorithmDigestLengthInBytes; // for simplicity we'll generate HMAC subkeys with a length equal to the digest length + + // Argument checking on the algorithms and lengths passed in to us + AlgorithmAssert.IsAllowableSymmetricAlgorithmBlockSize(checked(_symmetricAlgorithmBlockSizeInBytes * 8)); + AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked(_symmetricAlgorithmSubkeyLengthInBytes * 8)); + AlgorithmAssert.IsAllowableValidationAlgorithmDigestSize(checked(_hmacAlgorithmDigestLengthInBytes * 8)); + + _contextHeader = CreateContextHeader(); + } + + private byte[] CreateContextHeader() + { + var retVal = new byte[checked( + 1 /* KDF alg */ + + 1 /* chaining mode */ + + sizeof(uint) /* sym alg key size */ + + sizeof(uint) /* sym alg block size */ + + sizeof(uint) /* hmac alg key size */ + + sizeof(uint) /* hmac alg digest size */ + + _symmetricAlgorithmBlockSizeInBytes /* ciphertext of encrypted empty string */ + + _hmacAlgorithmDigestLengthInBytes /* digest of HMACed empty string */)]; + + fixed (byte* pbRetVal = retVal) + { + byte* ptr = pbRetVal; + + // First is the two-byte header + *(ptr++) = 0; // 0x00 = SP800-108 CTR KDF w/ HMACSHA512 PRF + *(ptr++) = 0; // 0x00 = CBC encryption + HMAC authentication + + // Next is information about the symmetric algorithm (key size followed by block size) + BitHelpers.WriteTo(ref ptr, _symmetricAlgorithmSubkeyLengthInBytes); + BitHelpers.WriteTo(ref ptr, _symmetricAlgorithmBlockSizeInBytes); + + // Next is information about the HMAC algorithm (key size followed by digest size) + BitHelpers.WriteTo(ref ptr, _hmacAlgorithmSubkeyLengthInBytes); + BitHelpers.WriteTo(ref ptr, _hmacAlgorithmDigestLengthInBytes); + + // See the design document for an explanation of the following code. + var tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes]; + fixed (byte* pbTempKeys = tempKeys) + { + byte dummy; + + // Derive temporary keys for encryption + HMAC. + using (var provider = SP800_108_CTR_HMACSHA512Util.CreateEmptyProvider()) + { + provider.DeriveKey( + pbLabel: &dummy, + cbLabel: 0, + pbContext: &dummy, + cbContext: 0, + pbDerivedKey: pbTempKeys, + cbDerivedKey: (uint)tempKeys.Length); + } + + // At this point, tempKeys := { K_E || K_H }. + byte* pbSymmetricEncryptionSubkey = pbTempKeys; + byte* pbHmacSubkey = &pbTempKeys[_symmetricAlgorithmSubkeyLengthInBytes]; + + // Encrypt a zero-length input string with an all-zero IV and copy the ciphertext to the return buffer. + using (var symmetricKeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes)) + { + fixed (byte* pbIV = new byte[_symmetricAlgorithmBlockSizeInBytes] /* will be zero-initialized */) + { + DoCbcEncrypt( + symmetricKeyHandle: symmetricKeyHandle, + pbIV: pbIV, + pbInput: &dummy, + cbInput: 0, + pbOutput: ptr, + cbOutput: _symmetricAlgorithmBlockSizeInBytes); + } + } + ptr += _symmetricAlgorithmBlockSizeInBytes; + + // MAC a zero-length input string and copy the digest to the return buffer. + using (var hashHandle = _hmacAlgorithmHandle.CreateHmac(pbHmacSubkey, _hmacAlgorithmSubkeyLengthInBytes)) + { + hashHandle.HashData( + pbInput: &dummy, + cbInput: 0, + pbHashDigest: ptr, + cbHashDigest: _hmacAlgorithmDigestLengthInBytes); + } + + ptr += _hmacAlgorithmDigestLengthInBytes; + CryptoUtil.Assert(ptr - pbRetVal == retVal.Length, "ptr - pbRetVal == retVal.Length"); + } + } + + // retVal := { version || chainingMode || symAlgKeySize || symAlgBlockSize || hmacAlgKeySize || hmacAlgDigestSize || E("") || MAC("") }. + return retVal; + } + + protected override byte[] DecryptImpl(byte* pbCiphertext, uint cbCiphertext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData) + { + // Argument checking - input must at the absolute minimum contain a key modifier, IV, and MAC + if (cbCiphertext < checked(KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + _hmacAlgorithmDigestLengthInBytes)) + { + throw Error.CryptCommon_PayloadInvalid(); + } + + // Assumption: pbCipherText := { keyModifier | IV | encryptedData | MAC(IV | encryptedPayload) } + + var cbEncryptedData = checked(cbCiphertext - (KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + _hmacAlgorithmDigestLengthInBytes)); + + // Calculate offsets + byte* pbKeyModifier = pbCiphertext; + byte* pbIV = &pbKeyModifier[KEY_MODIFIER_SIZE_IN_BYTES]; + byte* pbEncryptedData = &pbIV[_symmetricAlgorithmBlockSizeInBytes]; + byte* pbActualHmac = &pbEncryptedData[cbEncryptedData]; + + // Use the KDF to recreate the symmetric encryption and HMAC subkeys + // We'll need a temporary buffer to hold them + var cbTempSubkeys = checked(_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes); + byte* pbTempSubkeys = stackalloc byte[checked((int)cbTempSubkeys)]; + try + { + _sp800_108_ctr_hmac_provider.DeriveKeyWithContextHeader( + pbLabel: pbAdditionalAuthenticatedData, + cbLabel: cbAdditionalAuthenticatedData, + contextHeader: _contextHeader, + pbContext: pbKeyModifier, + cbContext: KEY_MODIFIER_SIZE_IN_BYTES, + pbDerivedKey: pbTempSubkeys, + cbDerivedKey: cbTempSubkeys); + + // Calculate offsets + byte* pbSymmetricEncryptionSubkey = pbTempSubkeys; + byte* pbHmacSubkey = &pbTempSubkeys[_symmetricAlgorithmSubkeyLengthInBytes]; + + // First, perform an explicit integrity check over (iv | encryptedPayload) to ensure the + // data hasn't been tampered with. The integrity check is also implicitly performed over + // keyModifier since that value was provided to the KDF earlier. + using (var hashHandle = _hmacAlgorithmHandle.CreateHmac(pbHmacSubkey, _hmacAlgorithmSubkeyLengthInBytes)) + { + if (!ValidateHash(hashHandle, pbIV, _symmetricAlgorithmBlockSizeInBytes + cbEncryptedData, pbActualHmac)) + { + throw Error.CryptCommon_PayloadInvalid(); + } + } + + // If the integrity check succeeded, decrypt the payload. + using (var decryptionSubkeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes)) + { + return DoCbcDecrypt(decryptionSubkeyHandle, pbIV, pbEncryptedData, cbEncryptedData); + } + } + finally + { + // Buffer contains sensitive key material; delete. + UnsafeBufferUtil.SecureZeroMemory(pbTempSubkeys, cbTempSubkeys); + } + } + + public override void Dispose() + { + _sp800_108_ctr_hmac_provider.Dispose(); + + // We don't want to dispose of the underlying algorithm instances because they + // might be reused. + } + + // 'pbIV' must be a pointer to a buffer equal in length to the symmetric algorithm block size. + private byte[] DoCbcDecrypt(BCryptKeyHandle symmetricKeyHandle, byte* pbIV, byte* pbInput, uint cbInput) + { + // BCryptDecrypt mutates the provided IV; we need to clone it to prevent mutation of the original value + byte* pbClonedIV = stackalloc byte[checked((int)_symmetricAlgorithmBlockSizeInBytes)]; + UnsafeBufferUtil.BlockCopy(from: pbIV, to: pbClonedIV, byteCount: _symmetricAlgorithmBlockSizeInBytes); + + // First, figure out how large an output buffer we require. + // Ideally we'd be able to transform the last block ourselves and strip + // off the padding before creating the return value array, but we don't + // know the actual padding scheme being used under the covers (we can't + // assume PKCS#7). So unfortunately we're stuck with the temporary buffer. + // (Querying the output size won't mutate the IV.) + uint dwEstimatedDecryptedByteCount; + var ntstatus = UnsafeNativeMethods.BCryptDecrypt( + hKey: symmetricKeyHandle, + pbInput: pbInput, + cbInput: cbInput, + pPaddingInfo: null, + pbIV: pbClonedIV, + cbIV: _symmetricAlgorithmBlockSizeInBytes, + pbOutput: null, + cbOutput: 0, + pcbResult: out dwEstimatedDecryptedByteCount, + dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + + var decryptedPayload = new byte[dwEstimatedDecryptedByteCount]; + uint dwActualDecryptedByteCount; + fixed (byte* pbDecryptedPayload = decryptedPayload) + { + byte dummy; + + // Perform the actual decryption. + ntstatus = UnsafeNativeMethods.BCryptDecrypt( + hKey: symmetricKeyHandle, + pbInput: pbInput, + cbInput: cbInput, + pPaddingInfo: null, + pbIV: pbClonedIV, + cbIV: _symmetricAlgorithmBlockSizeInBytes, + pbOutput: (pbDecryptedPayload != null) ? pbDecryptedPayload : &dummy, // CLR won't pin zero-length arrays + cbOutput: dwEstimatedDecryptedByteCount, + pcbResult: out dwActualDecryptedByteCount, + dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + } + + // Decryption finished! + CryptoUtil.Assert(dwActualDecryptedByteCount <= dwEstimatedDecryptedByteCount, "dwActualDecryptedByteCount <= dwEstimatedDecryptedByteCount"); + if (dwActualDecryptedByteCount == dwEstimatedDecryptedByteCount) + { + // payload takes up the entire buffer + return decryptedPayload; + } + else + { + // payload takes up only a partial buffer + var resizedDecryptedPayload = new byte[dwActualDecryptedByteCount]; + Buffer.BlockCopy(decryptedPayload, 0, resizedDecryptedPayload, 0, resizedDecryptedPayload.Length); + return resizedDecryptedPayload; + } + } + + // 'pbIV' must be a pointer to a buffer equal in length to the symmetric algorithm block size. + private void DoCbcEncrypt(BCryptKeyHandle symmetricKeyHandle, byte* pbIV, byte* pbInput, uint cbInput, byte* pbOutput, uint cbOutput) + { + // BCryptEncrypt mutates the provided IV; we need to clone it to prevent mutation of the original value + byte* pbClonedIV = stackalloc byte[checked((int)_symmetricAlgorithmBlockSizeInBytes)]; + UnsafeBufferUtil.BlockCopy(from: pbIV, to: pbClonedIV, byteCount: _symmetricAlgorithmBlockSizeInBytes); + + uint dwEncryptedBytes; + var ntstatus = UnsafeNativeMethods.BCryptEncrypt( + hKey: symmetricKeyHandle, + pbInput: pbInput, + cbInput: cbInput, + pPaddingInfo: null, + pbIV: pbClonedIV, + cbIV: _symmetricAlgorithmBlockSizeInBytes, + pbOutput: pbOutput, + cbOutput: cbOutput, + pcbResult: out dwEncryptedBytes, + dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + + // Need to make sure we didn't underrun the buffer - means caller passed a bad value + CryptoUtil.Assert(dwEncryptedBytes == cbOutput, "dwEncryptedBytes == cbOutput"); + } + + protected override byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer) + { + // This buffer will be used to hold the symmetric encryption and HMAC subkeys + // used in the generation of this payload. + var cbTempSubkeys = checked(_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes); + byte* pbTempSubkeys = stackalloc byte[checked((int)cbTempSubkeys)]; + + try + { + // Randomly generate the key modifier and IV. + var cbKeyModifierAndIV = checked(KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes); + byte* pbKeyModifierAndIV = stackalloc byte[checked((int)cbKeyModifierAndIV)]; + _genRandom.GenRandom(pbKeyModifierAndIV, cbKeyModifierAndIV); + + // Calculate offsets + byte* pbKeyModifier = pbKeyModifierAndIV; + byte* pbIV = &pbKeyModifierAndIV[KEY_MODIFIER_SIZE_IN_BYTES]; + + // Use the KDF to generate a new symmetric encryption and HMAC subkey + _sp800_108_ctr_hmac_provider.DeriveKeyWithContextHeader( + pbLabel: pbAdditionalAuthenticatedData, + cbLabel: cbAdditionalAuthenticatedData, + contextHeader: _contextHeader, + pbContext: pbKeyModifier, + cbContext: KEY_MODIFIER_SIZE_IN_BYTES, + pbDerivedKey: pbTempSubkeys, + cbDerivedKey: cbTempSubkeys); + + // Calculate offsets + byte* pbSymmetricEncryptionSubkey = pbTempSubkeys; + byte* pbHmacSubkey = &pbTempSubkeys[_symmetricAlgorithmSubkeyLengthInBytes]; + + using (var symmetricKeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes)) + { + // We can't assume PKCS#7 padding (maybe the underlying provider is really using CTS), + // so we need to query the padded output size before we can allocate the return value array. + var cbOutputCiphertext = GetCbcEncryptedOutputSizeWithPadding(symmetricKeyHandle, pbPlaintext, cbPlaintext); + + // Allocate return value array and start copying some data + var retVal = new byte[checked(cbPreBuffer + KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + cbOutputCiphertext + _hmacAlgorithmDigestLengthInBytes + cbPostBuffer)]; + fixed (byte* pbRetVal = retVal) + { + // Calculate offsets + byte* pbOutputKeyModifier = &pbRetVal[cbPreBuffer]; + byte* pbOutputIV = &pbOutputKeyModifier[KEY_MODIFIER_SIZE_IN_BYTES]; + byte* pbOutputCiphertext = &pbOutputIV[_symmetricAlgorithmBlockSizeInBytes]; + byte* pbOutputHmac = &pbOutputCiphertext[cbOutputCiphertext]; + + UnsafeBufferUtil.BlockCopy(from: pbKeyModifierAndIV, to: pbOutputKeyModifier, byteCount: cbKeyModifierAndIV); + + // retVal will eventually contain { preBuffer | keyModifier | iv | encryptedData | HMAC(iv | encryptedData) | postBuffer } + // At this point, retVal := { preBuffer | keyModifier | iv | _____ | _____ | postBuffer } + + DoCbcEncrypt( + symmetricKeyHandle: symmetricKeyHandle, + pbIV: pbIV, + pbInput: pbPlaintext, + cbInput: cbPlaintext, + pbOutput: pbOutputCiphertext, + cbOutput: cbOutputCiphertext); + + // At this point, retVal := { preBuffer | keyModifier | iv | encryptedData | _____ | postBuffer } + + // Compute the HMAC over the IV and the ciphertext (prevents IV tampering). + // The HMAC is already implicitly computed over the key modifier since the key + // modifier is used as input to the KDF. + using (var hashHandle = _hmacAlgorithmHandle.CreateHmac(pbHmacSubkey, _hmacAlgorithmSubkeyLengthInBytes)) + { + hashHandle.HashData( + pbInput: pbOutputIV, + cbInput: checked(_symmetricAlgorithmBlockSizeInBytes + cbOutputCiphertext), + pbHashDigest: pbOutputHmac, + cbHashDigest: _hmacAlgorithmDigestLengthInBytes); + } + + // At this point, retVal := { preBuffer | keyModifier | iv | encryptedData | HMAC(iv | encryptedData) | postBuffer } + // And we're done! + return retVal; + } + } + } + finally + { + // Buffer contains sensitive material; delete it. + UnsafeBufferUtil.SecureZeroMemory(pbTempSubkeys, cbTempSubkeys); + } + } + + private uint GetCbcEncryptedOutputSizeWithPadding(BCryptKeyHandle symmetricKeyHandle, byte* pbInput, uint cbInput) + { + // ok for this memory to remain uninitialized since nobody depends on it + byte* pbIV = stackalloc byte[checked((int)_symmetricAlgorithmBlockSizeInBytes)]; + + // Calling BCryptEncrypt with a null output pointer will cause it to return the total number + // of bytes required for the output buffer. + uint dwResult; + var ntstatus = UnsafeNativeMethods.BCryptEncrypt( + hKey: symmetricKeyHandle, + pbInput: pbInput, + cbInput: cbInput, + pPaddingInfo: null, + pbIV: pbIV, + cbIV: _symmetricAlgorithmBlockSizeInBytes, + pbOutput: null, + cbOutput: 0, + pcbResult: out dwResult, + dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + + return dwResult; + } + + // 'pbExpectedDigest' must point to a '_hmacAlgorithmDigestLengthInBytes'-length buffer + private bool ValidateHash(BCryptHashHandle hashHandle, byte* pbInput, uint cbInput, byte* pbExpectedDigest) + { + byte* pbActualDigest = stackalloc byte[checked((int)_hmacAlgorithmDigestLengthInBytes)]; + hashHandle.HashData(pbInput, cbInput, pbActualDigest, _hmacAlgorithmDigestLengthInBytes); + return CryptoUtil.TimeConstantBuffersAreEqual(pbExpectedDigest, pbActualDigest, _hmacAlgorithmDigestLengthInBytes); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/DpapiSecretSerializerHelper.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/DpapiSecretSerializerHelper.cs new file mode 100644 index 0000000000..61bbb4f9ea --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/DpapiSecretSerializerHelper.cs @@ -0,0 +1,356 @@ +// 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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.SafeHandles; + +namespace Microsoft.AspNetCore.DataProtection.Cng +{ + internal unsafe static class DpapiSecretSerializerHelper + { + // from ncrypt.h + private const uint NCRYPT_SILENT_FLAG = 0x00000040; + + // from dpapi.h + private const uint CRYPTPROTECT_UI_FORBIDDEN = 0x1; + private const uint CRYPTPROTECT_LOCAL_MACHINE = 0x4; + + private static readonly byte[] _purpose = Encoding.UTF8.GetBytes("DPAPI-Protected Secret"); + + // Probes to see if protecting to the current Windows user account is available. + // In theory this should never fail if the user profile is available, so it's more a defense-in-depth check. + public static bool CanProtectToCurrentUserAccount() + { + try + { + Guid dummy; + ProtectWithDpapi(new Secret((byte*)&dummy, sizeof(Guid)), protectToLocalMachine: false); + return true; + } + catch + { + return false; + } + } + + public static byte[] ProtectWithDpapi(ISecret secret, bool protectToLocalMachine = false) + { + Debug.Assert(secret != null); + + var plaintextSecret = new byte[secret.Length]; + fixed (byte* pbPlaintextSecret = plaintextSecret) + { + try + { + secret.WriteSecretIntoBuffer(new ArraySegment(plaintextSecret)); + fixed (byte* pbPurpose = _purpose) + { + return ProtectWithDpapiCore(pbPlaintextSecret, (uint)plaintextSecret.Length, pbPurpose, (uint)_purpose.Length, fLocalMachine: protectToLocalMachine); + } + } + finally + { + // To limit exposure to the GC. + Array.Clear(plaintextSecret, 0, plaintextSecret.Length); + } + } + } + + internal static byte[] ProtectWithDpapiCore(byte* pbSecret, uint cbSecret, byte* pbOptionalEntropy, uint cbOptionalEntropy, bool fLocalMachine = false) + { + byte dummy; // provides a valid memory address if the secret or entropy has zero length + + var dataIn = new DATA_BLOB() + { + cbData = cbSecret, + pbData = (pbSecret != null) ? pbSecret : &dummy + }; + var entropy = new DATA_BLOB() + { + cbData = cbOptionalEntropy, + pbData = (pbOptionalEntropy != null) ? pbOptionalEntropy : &dummy + }; + var dataOut = default(DATA_BLOB); + + RuntimeHelpers.PrepareConstrainedRegions(); + + try + { + var success = UnsafeNativeMethods.CryptProtectData( + pDataIn: &dataIn, + szDataDescr: IntPtr.Zero, + pOptionalEntropy: &entropy, + pvReserved: IntPtr.Zero, + pPromptStruct: IntPtr.Zero, + dwFlags: CRYPTPROTECT_UI_FORBIDDEN | ((fLocalMachine) ? CRYPTPROTECT_LOCAL_MACHINE : 0), + pDataOut: out dataOut); + if (!success) + { + var errorCode = Marshal.GetLastWin32Error(); + throw new CryptographicException(errorCode); + } + + var dataLength = checked((int)dataOut.cbData); + var retVal = new byte[dataLength]; + Marshal.Copy((IntPtr)dataOut.pbData, retVal, 0, dataLength); + return retVal; + } + finally + { + // Free memory so that we don't leak. + // FreeHGlobal actually calls LocalFree. + if (dataOut.pbData != null) + { + Marshal.FreeHGlobal((IntPtr)dataOut.pbData); + } + } + } + + public static byte[] ProtectWithDpapiNG(ISecret secret, NCryptDescriptorHandle protectionDescriptorHandle) + { + Debug.Assert(secret != null); + Debug.Assert(protectionDescriptorHandle != null); + + var plaintextSecret = new byte[secret.Length]; + fixed (byte* pbPlaintextSecret = plaintextSecret) + { + try + { + secret.WriteSecretIntoBuffer(new ArraySegment(plaintextSecret)); + + byte dummy; // used to provide a valid memory address if secret is zero-length + return ProtectWithDpapiNGCore( + protectionDescriptorHandle: protectionDescriptorHandle, + pbData: (pbPlaintextSecret != null) ? pbPlaintextSecret : &dummy, + cbData: (uint)plaintextSecret.Length); + } + finally + { + // Limits secret exposure to garbage collector. + Array.Clear(plaintextSecret, 0, plaintextSecret.Length); + } + } + } + + private static byte[] ProtectWithDpapiNGCore(NCryptDescriptorHandle protectionDescriptorHandle, byte* pbData, uint cbData) + { + Debug.Assert(protectionDescriptorHandle != null); + Debug.Assert(pbData != null); + + // Perform the encryption operation, putting the protected data into LocalAlloc-allocated memory. + LocalAllocHandle protectedData; + uint cbProtectedData; + var ntstatus = UnsafeNativeMethods.NCryptProtectSecret( + hDescriptor: protectionDescriptorHandle, + dwFlags: NCRYPT_SILENT_FLAG, + pbData: pbData, + cbData: cbData, + pMemPara: IntPtr.Zero, + hWnd: IntPtr.Zero, + ppbProtectedBlob: out protectedData, + pcbProtectedBlob: out cbProtectedData); + UnsafeNativeMethods.ThrowExceptionForNCryptStatus(ntstatus); + CryptoUtil.AssertSafeHandleIsValid(protectedData); + + // Copy the data from LocalAlloc-allocated memory into a managed memory buffer. + using (protectedData) + { + var retVal = new byte[cbProtectedData]; + if (cbProtectedData > 0) + { + fixed (byte* pbRetVal = retVal) + { + var handleAcquired = false; + + RuntimeHelpers.PrepareConstrainedRegions(); + + try + { + protectedData.DangerousAddRef(ref handleAcquired); + UnsafeBufferUtil.BlockCopy(from: (void*)protectedData.DangerousGetHandle(), to: pbRetVal, byteCount: cbProtectedData); + } + finally + { + if (handleAcquired) + { + protectedData.DangerousRelease(); + } + } + } + } + return retVal; + } + } + + public static Secret UnprotectWithDpapi(byte[] protectedSecret) + { + Debug.Assert(protectedSecret != null); + + fixed (byte* pbProtectedSecret = protectedSecret) + { + fixed (byte* pbPurpose = _purpose) + { + return UnprotectWithDpapiCore(pbProtectedSecret, (uint)protectedSecret.Length, pbPurpose, (uint)_purpose.Length); + } + } + } + + internal static Secret UnprotectWithDpapiCore(byte* pbProtectedData, uint cbProtectedData, byte* pbOptionalEntropy, uint cbOptionalEntropy) + { + byte dummy; // provides a valid memory address if the secret or entropy has zero length + + var dataIn = new DATA_BLOB() + { + cbData = cbProtectedData, + pbData = (pbProtectedData != null) ? pbProtectedData : &dummy + }; + var entropy = new DATA_BLOB() + { + cbData = cbOptionalEntropy, + pbData = (pbOptionalEntropy != null) ? pbOptionalEntropy : &dummy + }; + var dataOut = default(DATA_BLOB); + + RuntimeHelpers.PrepareConstrainedRegions(); + + try + { + var success = UnsafeNativeMethods.CryptUnprotectData( + pDataIn: &dataIn, + ppszDataDescr: IntPtr.Zero, + pOptionalEntropy: &entropy, + pvReserved: IntPtr.Zero, + pPromptStruct: IntPtr.Zero, + dwFlags: CRYPTPROTECT_UI_FORBIDDEN, + pDataOut: out dataOut); + if (!success) + { + var errorCode = Marshal.GetLastWin32Error(); + throw new CryptographicException(errorCode); + } + + return new Secret(dataOut.pbData, checked((int)dataOut.cbData)); + } + finally + { + // Zero and free memory so that we don't leak secrets. + // FreeHGlobal actually calls LocalFree. + if (dataOut.pbData != null) + { + UnsafeBufferUtil.SecureZeroMemory(dataOut.pbData, dataOut.cbData); + Marshal.FreeHGlobal((IntPtr)dataOut.pbData); + } + } + } + + public static Secret UnprotectWithDpapiNG(byte[] protectedData) + { + Debug.Assert(protectedData != null); + + fixed (byte* pbProtectedData = protectedData) + { + byte dummy; // used to provide a valid memory address if protected data is zero-length + return UnprotectWithDpapiNGCore( + pbData: (pbProtectedData != null) ? pbProtectedData : &dummy, + cbData: (uint)protectedData.Length); + } + } + + private static Secret UnprotectWithDpapiNGCore(byte* pbData, uint cbData) + { + Debug.Assert(pbData != null); + + // First, decrypt the payload into LocalAlloc-allocated memory. + LocalAllocHandle unencryptedPayloadHandle; + uint cbUnencryptedPayload; + var ntstatus = UnsafeNativeMethods.NCryptUnprotectSecret( + phDescriptor: IntPtr.Zero, + dwFlags: NCRYPT_SILENT_FLAG, + pbProtectedBlob: pbData, + cbProtectedBlob: cbData, + pMemPara: IntPtr.Zero, + hWnd: IntPtr.Zero, + ppbData: out unencryptedPayloadHandle, + pcbData: out cbUnencryptedPayload); + UnsafeNativeMethods.ThrowExceptionForNCryptStatus(ntstatus); + CryptoUtil.AssertSafeHandleIsValid(unencryptedPayloadHandle); + + // Copy the data from LocalAlloc-allocated memory into a CryptProtectMemory-protected buffer. + // There's a small window between NCryptUnprotectSecret returning and the call to PrepareConstrainedRegions + // below where the AppDomain could rudely unload. This won't leak memory (due to the SafeHandle), but it + // will cause the secret not to be zeroed out before the memory is freed. We won't worry about this since + // the window is extremely small and AppDomain unloads should not happen here in practice. + using (unencryptedPayloadHandle) + { + var handleAcquired = false; + + RuntimeHelpers.PrepareConstrainedRegions(); + + try + { + unencryptedPayloadHandle.DangerousAddRef(ref handleAcquired); + return new Secret((byte*)unencryptedPayloadHandle.DangerousGetHandle(), checked((int)cbUnencryptedPayload)); + } + finally + { + if (handleAcquired) + { + UnsafeBufferUtil.SecureZeroMemory((byte*)unencryptedPayloadHandle.DangerousGetHandle(), cbUnencryptedPayload); + unencryptedPayloadHandle.DangerousRelease(); + } + } + } + } + + public static string GetRuleFromDpapiNGProtectedPayload(byte[] protectedData) + { + Debug.Assert(protectedData != null); + + fixed (byte* pbProtectedData = protectedData) + { + byte dummy; // used to provide a valid memory address if protected data is zero-length + return GetRuleFromDpapiNGProtectedPayloadCore( + pbData: (pbProtectedData != null) ? pbProtectedData : &dummy, + cbData: (uint)protectedData.Length); + } + } + + private static string GetRuleFromDpapiNGProtectedPayloadCore(byte* pbData, uint cbData) + { + // from ncryptprotect.h + const uint NCRYPT_UNPROTECT_NO_DECRYPT = 0x00000001; + + NCryptDescriptorHandle descriptorHandle; + LocalAllocHandle unprotectedDataHandle; + uint cbUnprotectedData; + var ntstatus = UnsafeNativeMethods.NCryptUnprotectSecret( + phDescriptor: out descriptorHandle, + dwFlags: NCRYPT_UNPROTECT_NO_DECRYPT, + pbProtectedBlob: pbData, + cbProtectedBlob: cbData, + pMemPara: IntPtr.Zero, + hWnd: IntPtr.Zero, + ppbData: out unprotectedDataHandle, + pcbData: out cbUnprotectedData); + UnsafeNativeMethods.ThrowExceptionForNCryptStatus(ntstatus); + CryptoUtil.AssertSafeHandleIsValid(descriptorHandle); + + if (unprotectedDataHandle != null && !unprotectedDataHandle.IsInvalid) + { + // we don't care about this value + unprotectedDataHandle.Dispose(); + } + + using (descriptorHandle) + { + return descriptorHandle.GetProtectionDescriptorRuleString(); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/GcmAuthenticatedEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/GcmAuthenticatedEncryptor.cs new file mode 100644 index 0000000000..2e9b4ad31c --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/GcmAuthenticatedEncryptor.cs @@ -0,0 +1,289 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.Cng.Internal; +using Microsoft.AspNetCore.DataProtection.SP800_108; + +namespace Microsoft.AspNetCore.DataProtection.Cng +{ + // GCM is defined in NIST SP 800-38D (http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf). + // Heed closely the uniqueness requirements called out in Sec. 8: the probability that the GCM encryption + // routine is ever invoked on two or more distinct sets of input data with the same (key, IV) shall not + // exceed 2^-32. If we fix the key and use a random 96-bit IV for each invocation, this means that after + // 2^32 encryption operations the odds of reusing any (key, IV) pair is 2^-32 (see Sec. 8.3). This won't + // work for our use since a high-traffic web server can go through 2^32 requests in mere days. Instead, + // we'll use 224 bits of entropy for each operation, with 128 bits going to the KDF and 96 bits + // going to the IV. This means that we'll only hit the 2^-32 probability limit after 2^96 encryption + // operations, which will realistically never happen. (At the absurd rate of one encryption operation + // per nanosecond, it would still take 180 times the age of the universe to hit 2^96 operations.) + internal unsafe sealed class GcmAuthenticatedEncryptor : CngAuthenticatedEncryptorBase + { + // Having a key modifier ensures with overwhelming probability that no two encryption operations + // will ever derive the same (encryption subkey, MAC subkey) pair. This limits an attacker's + // ability to mount a key-dependent chosen ciphertext attack. See also the class-level comment + // for how this is used to overcome GCM's IV limitations. + private const uint KEY_MODIFIER_SIZE_IN_BYTES = 128 / 8; + + private const uint NONCE_SIZE_IN_BYTES = 96 / 8; // GCM has a fixed 96-bit IV + private const uint TAG_SIZE_IN_BYTES = 128 / 8; // we're hardcoding a 128-bit authentication tag size + + private readonly byte[] _contextHeader; + private readonly IBCryptGenRandom _genRandom; + private readonly ISP800_108_CTR_HMACSHA512Provider _sp800_108_ctr_hmac_provider; + private readonly BCryptAlgorithmHandle _symmetricAlgorithmHandle; + private readonly uint _symmetricAlgorithmSubkeyLengthInBytes; + + public GcmAuthenticatedEncryptor(Secret keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, IBCryptGenRandom genRandom = null) + { + // Is the key size appropriate? + AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked(symmetricAlgorithmKeySizeInBytes * 8)); + CryptoUtil.Assert(symmetricAlgorithmHandle.GetCipherBlockLength() == 128 / 8, "GCM requires a block cipher algorithm with a 128-bit block size."); + + _genRandom = genRandom ?? BCryptGenRandomImpl.Instance; + _sp800_108_ctr_hmac_provider = SP800_108_CTR_HMACSHA512Util.CreateProvider(keyDerivationKey); + _symmetricAlgorithmHandle = symmetricAlgorithmHandle; + _symmetricAlgorithmSubkeyLengthInBytes = symmetricAlgorithmKeySizeInBytes; + _contextHeader = CreateContextHeader(); + } + + private byte[] CreateContextHeader() + { + var retVal = new byte[checked( + 1 /* KDF alg */ + + 1 /* chaining mode */ + + sizeof(uint) /* sym alg key size */ + + sizeof(uint) /* GCM nonce size */ + + sizeof(uint) /* sym alg block size */ + + sizeof(uint) /* GCM tag size */ + + TAG_SIZE_IN_BYTES /* tag of GCM-encrypted empty string */)]; + + fixed (byte* pbRetVal = retVal) + { + byte* ptr = pbRetVal; + + // First is the two-byte header + *(ptr++) = 0; // 0x00 = SP800-108 CTR KDF w/ HMACSHA512 PRF + *(ptr++) = 1; // 0x01 = GCM encryption + authentication + + // Next is information about the symmetric algorithm (key size, nonce size, block size, tag size) + BitHelpers.WriteTo(ref ptr, _symmetricAlgorithmSubkeyLengthInBytes); + BitHelpers.WriteTo(ref ptr, NONCE_SIZE_IN_BYTES); + BitHelpers.WriteTo(ref ptr, TAG_SIZE_IN_BYTES); // block size = tag size + BitHelpers.WriteTo(ref ptr, TAG_SIZE_IN_BYTES); + + // See the design document for an explanation of the following code. + var tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes]; + fixed (byte* pbTempKeys = tempKeys) + { + byte dummy; + + // Derive temporary key for encryption. + using (var provider = SP800_108_CTR_HMACSHA512Util.CreateEmptyProvider()) + { + provider.DeriveKey( + pbLabel: &dummy, + cbLabel: 0, + pbContext: &dummy, + cbContext: 0, + pbDerivedKey: pbTempKeys, + cbDerivedKey: (uint)tempKeys.Length); + } + + // Encrypt a zero-length input string with an all-zero nonce and copy the tag to the return buffer. + byte* pbNonce = stackalloc byte[(int)NONCE_SIZE_IN_BYTES]; + UnsafeBufferUtil.SecureZeroMemory(pbNonce, NONCE_SIZE_IN_BYTES); + DoGcmEncrypt( + pbKey: pbTempKeys, + cbKey: _symmetricAlgorithmSubkeyLengthInBytes, + pbNonce: pbNonce, + pbPlaintextData: &dummy, + cbPlaintextData: 0, + pbEncryptedData: &dummy, + pbTag: ptr); + } + + ptr += TAG_SIZE_IN_BYTES; + CryptoUtil.Assert(ptr - pbRetVal == retVal.Length, "ptr - pbRetVal == retVal.Length"); + } + + // retVal := { version || chainingMode || symAlgKeySize || nonceSize || symAlgBlockSize || symAlgTagSize || TAG-of-E("") }. + return retVal; + } + + protected override byte[] DecryptImpl(byte* pbCiphertext, uint cbCiphertext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData) + { + // Argument checking: input must at the absolute minimum contain a key modifier, nonce, and tag + if (cbCiphertext < KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + TAG_SIZE_IN_BYTES) + { + throw Error.CryptCommon_PayloadInvalid(); + } + + // Assumption: pbCipherText := { keyModifier || nonce || encryptedData || authenticationTag } + + var cbPlaintext = checked(cbCiphertext - (KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + TAG_SIZE_IN_BYTES)); + + var retVal = new byte[cbPlaintext]; + fixed (byte* pbRetVal = retVal) + { + // Calculate offsets + byte* pbKeyModifier = pbCiphertext; + byte* pbNonce = &pbKeyModifier[KEY_MODIFIER_SIZE_IN_BYTES]; + byte* pbEncryptedData = &pbNonce[NONCE_SIZE_IN_BYTES]; + byte* pbAuthTag = &pbEncryptedData[cbPlaintext]; + + // Use the KDF to recreate the symmetric block cipher key + // We'll need a temporary buffer to hold the symmetric encryption subkey + byte* pbSymmetricDecryptionSubkey = stackalloc byte[checked((int)_symmetricAlgorithmSubkeyLengthInBytes)]; + try + { + _sp800_108_ctr_hmac_provider.DeriveKeyWithContextHeader( + pbLabel: pbAdditionalAuthenticatedData, + cbLabel: cbAdditionalAuthenticatedData, + contextHeader: _contextHeader, + pbContext: pbKeyModifier, + cbContext: KEY_MODIFIER_SIZE_IN_BYTES, + pbDerivedKey: pbSymmetricDecryptionSubkey, + cbDerivedKey: _symmetricAlgorithmSubkeyLengthInBytes); + + // Perform the decryption operation + + using (var decryptionSubkeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricDecryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes)) + { + byte dummy; + byte* pbPlaintext = (pbRetVal != null) ? pbRetVal : &dummy; // CLR doesn't like pinning empty buffers + + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo; + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.Init(out authInfo); + authInfo.pbNonce = pbNonce; + authInfo.cbNonce = NONCE_SIZE_IN_BYTES; + authInfo.pbTag = pbAuthTag; + authInfo.cbTag = TAG_SIZE_IN_BYTES; + + // The call to BCryptDecrypt will also validate the authentication tag + uint cbDecryptedBytesWritten; + var ntstatus = UnsafeNativeMethods.BCryptDecrypt( + hKey: decryptionSubkeyHandle, + pbInput: pbEncryptedData, + cbInput: cbPlaintext, + pPaddingInfo: &authInfo, + pbIV: null, // IV not used; nonce provided in pPaddingInfo + cbIV: 0, + pbOutput: pbPlaintext, + cbOutput: cbPlaintext, + pcbResult: out cbDecryptedBytesWritten, + dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + CryptoUtil.Assert(cbDecryptedBytesWritten == cbPlaintext, "cbDecryptedBytesWritten == cbPlaintext"); + + // At this point, retVal := { decryptedPayload } + // And we're done! + return retVal; + } + } + finally + { + // The buffer contains key material, so delete it. + UnsafeBufferUtil.SecureZeroMemory(pbSymmetricDecryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes); + } + } + } + + public override void Dispose() + { + _sp800_108_ctr_hmac_provider.Dispose(); + + // We don't want to dispose of the underlying algorithm instances because they + // might be reused. + } + + // 'pbNonce' must point to a 96-bit buffer. + // 'pbTag' must point to a 128-bit buffer. + // 'pbEncryptedData' must point to a buffer the same length as 'pbPlaintextData'. + private void DoGcmEncrypt(byte* pbKey, uint cbKey, byte* pbNonce, byte* pbPlaintextData, uint cbPlaintextData, byte* pbEncryptedData, byte* pbTag) + { + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authCipherInfo; + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.Init(out authCipherInfo); + authCipherInfo.pbNonce = pbNonce; + authCipherInfo.cbNonce = NONCE_SIZE_IN_BYTES; + authCipherInfo.pbTag = pbTag; + authCipherInfo.cbTag = TAG_SIZE_IN_BYTES; + + using (var keyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbKey, cbKey)) + { + uint cbResult; + var ntstatus = UnsafeNativeMethods.BCryptEncrypt( + hKey: keyHandle, + pbInput: pbPlaintextData, + cbInput: cbPlaintextData, + pPaddingInfo: &authCipherInfo, + pbIV: null, + cbIV: 0, + pbOutput: pbEncryptedData, + cbOutput: cbPlaintextData, + pcbResult: out cbResult, + dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + CryptoUtil.Assert(cbResult == cbPlaintextData, "cbResult == cbPlaintextData"); + } + } + + protected override byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer) + { + // Allocate a buffer to hold the key modifier, nonce, encrypted data, and tag. + // In GCM, the encrypted output will be the same length as the plaintext input. + var retVal = new byte[checked(cbPreBuffer + KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + cbPlaintext + TAG_SIZE_IN_BYTES + cbPostBuffer)]; + fixed (byte* pbRetVal = retVal) + { + // Calculate offsets + byte* pbKeyModifier = &pbRetVal[cbPreBuffer]; + byte* pbNonce = &pbKeyModifier[KEY_MODIFIER_SIZE_IN_BYTES]; + byte* pbEncryptedData = &pbNonce[NONCE_SIZE_IN_BYTES]; + byte* pbAuthTag = &pbEncryptedData[cbPlaintext]; + + // Randomly generate the key modifier and nonce + _genRandom.GenRandom(pbKeyModifier, KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES); + + // At this point, retVal := { preBuffer | keyModifier | nonce | _____ | _____ | postBuffer } + + // Use the KDF to generate a new symmetric block cipher key + // We'll need a temporary buffer to hold the symmetric encryption subkey + byte* pbSymmetricEncryptionSubkey = stackalloc byte[checked((int)_symmetricAlgorithmSubkeyLengthInBytes)]; + try + { + _sp800_108_ctr_hmac_provider.DeriveKeyWithContextHeader( + pbLabel: pbAdditionalAuthenticatedData, + cbLabel: cbAdditionalAuthenticatedData, + contextHeader: _contextHeader, + pbContext: pbKeyModifier, + cbContext: KEY_MODIFIER_SIZE_IN_BYTES, + pbDerivedKey: pbSymmetricEncryptionSubkey, + cbDerivedKey: _symmetricAlgorithmSubkeyLengthInBytes); + + // Perform the encryption operation + DoGcmEncrypt( + pbKey: pbSymmetricEncryptionSubkey, + cbKey: _symmetricAlgorithmSubkeyLengthInBytes, + pbNonce: pbNonce, + pbPlaintextData: pbPlaintext, + cbPlaintextData: cbPlaintext, + pbEncryptedData: pbEncryptedData, + pbTag: pbAuthTag); + + // At this point, retVal := { preBuffer | keyModifier | nonce | encryptedData | authenticationTag | postBuffer } + // And we're done! + return retVal; + } + finally + { + // The buffer contains key material, so delete it. + UnsafeBufferUtil.SecureZeroMemory(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes); + } + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/IBCryptGenRandom.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/IBCryptGenRandom.cs new file mode 100644 index 0000000000..e1cf9b7dbe --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/IBCryptGenRandom.cs @@ -0,0 +1,12 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.Cng +{ + internal unsafe interface IBCryptGenRandom + { + void GenRandom(byte* pbBuffer, uint cbBuffer); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/Internal/CngAuthenticatedEncryptorBase.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/Internal/CngAuthenticatedEncryptorBase.cs new file mode 100644 index 0000000000..7b7e3e2d79 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Cng/Internal/CngAuthenticatedEncryptorBase.cs @@ -0,0 +1,87 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; + +namespace Microsoft.AspNetCore.DataProtection.Cng.Internal +{ + /// + /// Base class used for all CNG-related authentication encryption operations. + /// + public unsafe abstract class CngAuthenticatedEncryptorBase : IOptimizedAuthenticatedEncryptor, IDisposable + { + public byte[] Decrypt(ArraySegment ciphertext, ArraySegment additionalAuthenticatedData) + { + // This wrapper simply converts ArraySegment to byte* and calls the impl method. + + // Input validation + ciphertext.Validate(); + additionalAuthenticatedData.Validate(); + + byte dummy; // used only if plaintext or AAD is empty, since otherwise 'fixed' returns null pointer + fixed (byte* pbCiphertextArray = ciphertext.Array) + { + fixed (byte* pbAdditionalAuthenticatedDataArray = additionalAuthenticatedData.Array) + { + try + { + return DecryptImpl( + pbCiphertext: (pbCiphertextArray != null) ? &pbCiphertextArray[ciphertext.Offset] : &dummy, + cbCiphertext: (uint)ciphertext.Count, + pbAdditionalAuthenticatedData: (pbAdditionalAuthenticatedDataArray != null) ? &pbAdditionalAuthenticatedDataArray[additionalAuthenticatedData.Offset] : &dummy, + cbAdditionalAuthenticatedData: (uint)additionalAuthenticatedData.Count); + } + catch (Exception ex) when (ex.RequiresHomogenization()) + { + // Homogenize to CryptographicException. + throw Error.CryptCommon_GenericError(ex); + } + } + } + } + + protected abstract byte[] DecryptImpl(byte* pbCiphertext, uint cbCiphertext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData); + + public abstract void Dispose(); + + public byte[] Encrypt(ArraySegment plaintext, ArraySegment additionalAuthenticatedData) + { + return Encrypt(plaintext, additionalAuthenticatedData, 0, 0); + } + + public byte[] Encrypt(ArraySegment plaintext, ArraySegment additionalAuthenticatedData, uint preBufferSize, uint postBufferSize) + { + // This wrapper simply converts ArraySegment to byte* and calls the impl method. + + // Input validation + plaintext.Validate(); + additionalAuthenticatedData.Validate(); + + byte dummy; // used only if plaintext or AAD is empty, since otherwise 'fixed' returns null pointer + fixed (byte* pbPlaintextArray = plaintext.Array) + { + fixed (byte* pbAdditionalAuthenticatedDataArray = additionalAuthenticatedData.Array) + { + try + { + return EncryptImpl( + pbPlaintext: (pbPlaintextArray != null) ? &pbPlaintextArray[plaintext.Offset] : &dummy, + cbPlaintext: (uint)plaintext.Count, + pbAdditionalAuthenticatedData: (pbAdditionalAuthenticatedDataArray != null) ? &pbAdditionalAuthenticatedDataArray[additionalAuthenticatedData.Offset] : &dummy, + cbAdditionalAuthenticatedData: (uint)additionalAuthenticatedData.Count, + cbPreBuffer: preBufferSize, + cbPostBuffer: postBufferSize); + } + catch (Exception ex) when (ex.RequiresHomogenization()) + { + // Homogenize to CryptographicException. + throw Error.CryptCommon_GenericError(ex); + } + } + } + } + + protected abstract byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionBuilderExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionBuilderExtensions.cs new file mode 100644 index 0000000000..7789ca074f --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionBuilderExtensions.cs @@ -0,0 +1,628 @@ +// 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.ComponentModel; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Repositories; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Microsoft.Win32; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Extensions for configuring data protection using an . + /// + public static class DataProtectionBuilderExtensions + { + /// + /// Sets the unique name of this application within the data protection system. + /// + /// The . + /// The application name. + /// A reference to the after this operation has completed. + /// + /// This API corresponds to setting the property + /// to the value of . + /// + public static IDataProtectionBuilder SetApplicationName(this IDataProtectionBuilder builder, string applicationName) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + builder.Services.Configure(options => + { + options.ApplicationDiscriminator = applicationName; + }); + + return builder; + } + + /// + /// Registers a to perform escrow before keys are persisted to storage. + /// + /// The . + /// The instance of the to register. + /// A reference to the after this operation has completed. + /// + /// Registrations are additive. + /// + public static IDataProtectionBuilder AddKeyEscrowSink(this IDataProtectionBuilder builder, IKeyEscrowSink sink) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (sink == null) + { + throw new ArgumentNullException(nameof(sink)); + } + + builder.Services.Configure(options => + { + options.KeyEscrowSinks.Add(sink); + }); + + return builder; + } + + /// + /// Registers a to perform escrow before keys are persisted to storage. + /// + /// The concrete type of the to register. + /// The . + /// A reference to the after this operation has completed. + /// + /// Registrations are additive. The factory is registered as . + /// + public static IDataProtectionBuilder AddKeyEscrowSink(this IDataProtectionBuilder builder) + where TImplementation : class, IKeyEscrowSink + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + builder.Services.AddSingleton>(services => + { + var implementationInstance = services.GetRequiredService(); + return new ConfigureOptions(options => + { + options.KeyEscrowSinks.Add(implementationInstance); + }); + }); + + return builder; + } + + /// + /// Registers a to perform escrow before keys are persisted to storage. + /// + /// The . + /// A factory that creates the instance. + /// A reference to the after this operation has completed. + /// + /// Registrations are additive. The factory is registered as . + /// + public static IDataProtectionBuilder AddKeyEscrowSink(this IDataProtectionBuilder builder, Func factory) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (factory == null) + { + throw new ArgumentNullException(nameof(factory)); + } + + builder.Services.AddSingleton>(services => + { + var instance = factory(services); + return new ConfigureOptions(options => + { + options.KeyEscrowSinks.Add(instance); + }); + }); + + return builder; + } + + /// + /// Configures the key management options for the data protection system. + /// + /// The . + /// An to configure the provided . + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder AddKeyManagementOptions(this IDataProtectionBuilder builder, Action setupAction) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (setupAction == null) + { + throw new ArgumentNullException(nameof(setupAction)); + } + + builder.Services.Configure(setupAction); + return builder; + } + + /// + /// Configures the data protection system not to generate new keys automatically. + /// + /// The . + /// A reference to the after this operation has completed. + /// + /// Calling this API corresponds to setting + /// to 'false'. See that property's documentation for more information. + /// + public static IDataProtectionBuilder DisableAutomaticKeyGeneration(this IDataProtectionBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + builder.Services.Configure(options => + { + options.AutoGenerateKeys = false; + }); + return builder; + } + + /// + /// Configures the data protection system to persist keys to the specified directory. + /// This path may be on the local machine or may point to a UNC share. + /// + /// The . + /// The directory in which to store keys. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder PersistKeysToFileSystem(this IDataProtectionBuilder builder, DirectoryInfo directory) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (directory == null) + { + throw new ArgumentNullException(nameof(directory)); + } + + builder.Services.AddSingleton>(services => + { + var loggerFactory = services.GetService() ?? NullLoggerFactory.Instance; + return new ConfigureOptions(options => + { + options.XmlRepository = new FileSystemXmlRepository(directory, loggerFactory); + }); + }); + + return builder; + } + + /// + /// Configures the data protection system to persist keys to the Windows registry. + /// + /// The . + /// The location in the registry where keys should be stored. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder PersistKeysToRegistry(this IDataProtectionBuilder builder, RegistryKey registryKey) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (registryKey == null) + { + throw new ArgumentNullException(nameof(registryKey)); + } + + builder.Services.AddSingleton>(services => + { + var loggerFactory = services.GetService() ?? NullLoggerFactory.Instance; + return new ConfigureOptions(options => + { + options.XmlRepository = new RegistryXmlRepository(registryKey, loggerFactory); + }); + }); + + return builder; + } + + /// + /// Configures keys to be encrypted to a given certificate before being persisted to storage. + /// + /// The . + /// The certificate to use when encrypting keys. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder ProtectKeysWithCertificate(this IDataProtectionBuilder builder, X509Certificate2 certificate) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (certificate == null) + { + throw new ArgumentNullException(nameof(certificate)); + } + + builder.Services.AddSingleton>(services => + { + var loggerFactory = services.GetService() ?? NullLoggerFactory.Instance; + return new ConfigureOptions(options => + { + options.XmlEncryptor = new CertificateXmlEncryptor(certificate, loggerFactory); + }); + }); + + builder.Services.Configure(o => o.AddKeyDecryptionCertificate(certificate)); + + return builder; + } + + /// + /// Configures keys to be encrypted to a given certificate before being persisted to storage. + /// + /// The . + /// The thumbprint of the certificate to use when encrypting keys. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder ProtectKeysWithCertificate(this IDataProtectionBuilder builder, string thumbprint) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (thumbprint == null) + { + throw new ArgumentNullException(nameof(thumbprint)); + } + + // Make sure the thumbprint corresponds to a valid certificate. + if (new CertificateResolver().ResolveCertificate(thumbprint) == null) + { + throw Error.CertificateXmlEncryptor_CertificateNotFound(thumbprint); + } + + // ICertificateResolver is necessary for this type to work correctly, so register it + // if it doesn't already exist. + builder.Services.TryAddSingleton(); + + builder.Services.AddSingleton>(services => + { + var loggerFactory = services.GetService() ?? NullLoggerFactory.Instance; + var certificateResolver = services.GetRequiredService(); + return new ConfigureOptions(options => + { + options.XmlEncryptor = new CertificateXmlEncryptor(thumbprint, certificateResolver, loggerFactory); + }); + }); + + return builder; + } + + /// + /// Configures certificates which can be used to decrypt keys loaded from storage. + /// + /// The . + /// Certificates that can be used to decrypt key data. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder UnprotectKeysWithAnyCertificate(this IDataProtectionBuilder builder, params X509Certificate2[] certificates) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + builder.Services.Configure(o => + { + if (certificates != null) + { + foreach (var certificate in certificates) + { + o.AddKeyDecryptionCertificate(certificate); + } + } + }); + + return builder; + } + + /// + /// Configures keys to be encrypted with Windows DPAPI before being persisted to + /// storage. The encrypted key will only be decryptable by the current Windows user account. + /// + /// The . + /// A reference to the after this operation has completed. + /// + /// This API is only supported on Windows platforms. + /// + public static IDataProtectionBuilder ProtectKeysWithDpapi(this IDataProtectionBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + return builder.ProtectKeysWithDpapi(protectToLocalMachine: false); + } + + /// + /// Configures keys to be encrypted with Windows DPAPI before being persisted to + /// storage. + /// + /// The . + /// 'true' if the key should be decryptable by any + /// use on the local machine, 'false' if the key should only be decryptable by the current + /// Windows user account. + /// A reference to the after this operation has completed. + /// + /// This API is only supported on Windows platforms. + /// + public static IDataProtectionBuilder ProtectKeysWithDpapi(this IDataProtectionBuilder builder, bool protectToLocalMachine) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + builder.Services.AddSingleton>(services => + { + var loggerFactory = services.GetService() ?? NullLoggerFactory.Instance; + return new ConfigureOptions(options => + { + CryptoUtil.AssertPlatformIsWindows(); + options.XmlEncryptor = new DpapiXmlEncryptor(protectToLocalMachine, loggerFactory); + }); + }); + + return builder; + } + + /// + /// Configures keys to be encrypted with Windows CNG DPAPI before being persisted + /// to storage. The keys will be decryptable by the current Windows user account. + /// + /// The . + /// A reference to the after this operation has completed. + /// + /// See https://msdn.microsoft.com/en-us/library/windows/desktop/hh706794(v=vs.85).aspx + /// for more information on DPAPI-NG. This API is only supported on Windows 8 / Windows Server 2012 and higher. + /// + public static IDataProtectionBuilder ProtectKeysWithDpapiNG(this IDataProtectionBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + return builder.ProtectKeysWithDpapiNG( + protectionDescriptorRule: DpapiNGXmlEncryptor.GetDefaultProtectionDescriptorString(), + flags: DpapiNGProtectionDescriptorFlags.None); + } + + /// + /// Configures keys to be encrypted with Windows CNG DPAPI before being persisted to storage. + /// + /// The . + /// The descriptor rule string with which to protect the key material. + /// Flags that should be passed to the call to 'NCryptCreateProtectionDescriptor'. + /// The default value of this parameter is . + /// A reference to the after this operation has completed. + /// + /// See https://msdn.microsoft.com/en-us/library/windows/desktop/hh769091(v=vs.85).aspx + /// and https://msdn.microsoft.com/en-us/library/windows/desktop/hh706800(v=vs.85).aspx + /// for more information on valid values for the the + /// and arguments. + /// This API is only supported on Windows 8 / Windows Server 2012 and higher. + /// + public static IDataProtectionBuilder ProtectKeysWithDpapiNG(this IDataProtectionBuilder builder, string protectionDescriptorRule, DpapiNGProtectionDescriptorFlags flags) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (protectionDescriptorRule == null) + { + throw new ArgumentNullException(nameof(protectionDescriptorRule)); + } + + builder.Services.AddSingleton>(services => + { + var loggerFactory = services.GetService() ?? NullLoggerFactory.Instance; + return new ConfigureOptions(options => + { + CryptoUtil.AssertPlatformIsWindows8OrLater(); + options.XmlEncryptor = new DpapiNGXmlEncryptor(protectionDescriptorRule, flags, loggerFactory); + }); + }); + + return builder; + } + + /// + /// Sets the default lifetime of keys created by the data protection system. + /// + /// The . + /// The lifetime (time before expiration) for newly-created keys. + /// See for more information and + /// usage notes. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder SetDefaultKeyLifetime(this IDataProtectionBuilder builder, TimeSpan lifetime) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (lifetime < TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException(Resources.FormatLifetimeMustNotBeNegative(nameof(lifetime))); + } + + builder.Services.Configure(options => + { + options.NewKeyLifetime = lifetime; + }); + + return builder; + } + + /// + /// Configures the data protection system to use the specified cryptographic algorithms + /// by default when generating protected payloads. + /// + /// The . + /// Information about what cryptographic algorithms should be used. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder UseCryptographicAlgorithms(this IDataProtectionBuilder builder, AuthenticatedEncryptorConfiguration configuration) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + return UseCryptographicAlgorithmsCore(builder, configuration); + } + + /// + /// Configures the data protection system to use custom Windows CNG algorithms. + /// This API is intended for advanced scenarios where the developer cannot use the + /// algorithms specified in the and + /// enumerations. + /// + /// The . + /// Information about what cryptographic algorithms should be used. + /// A reference to the after this operation has completed. + /// + /// This API is only available on Windows. + /// + [EditorBrowsable(EditorBrowsableState.Advanced)] + public static IDataProtectionBuilder UseCustomCryptographicAlgorithms(this IDataProtectionBuilder builder, CngCbcAuthenticatedEncryptorConfiguration configuration) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + return UseCryptographicAlgorithmsCore(builder, configuration); + } + + /// + /// Configures the data protection system to use custom Windows CNG algorithms. + /// This API is intended for advanced scenarios where the developer cannot use the + /// algorithms specified in the and + /// enumerations. + /// + /// The . + /// Information about what cryptographic algorithms should be used. + /// A reference to the after this operation has completed. + /// + /// This API is only available on Windows. + /// + [EditorBrowsable(EditorBrowsableState.Advanced)] + public static IDataProtectionBuilder UseCustomCryptographicAlgorithms(this IDataProtectionBuilder builder, CngGcmAuthenticatedEncryptorConfiguration configuration) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + return UseCryptographicAlgorithmsCore(builder, configuration); + } + + /// + /// Configures the data protection system to use custom algorithms. + /// This API is intended for advanced scenarios where the developer cannot use the + /// algorithms specified in the and + /// enumerations. + /// + /// The . + /// Information about what cryptographic algorithms should be used. + /// A reference to the after this operation has completed. + [EditorBrowsable(EditorBrowsableState.Advanced)] + public static IDataProtectionBuilder UseCustomCryptographicAlgorithms(this IDataProtectionBuilder builder, ManagedAuthenticatedEncryptorConfiguration configuration) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + return UseCryptographicAlgorithmsCore(builder, configuration); + } + + private static IDataProtectionBuilder UseCryptographicAlgorithmsCore(IDataProtectionBuilder builder, AlgorithmConfiguration configuration) + { + ((IInternalAlgorithmConfiguration)configuration).Validate(); // perform self-test + + builder.Services.Configure(options => + { + options.AuthenticatedEncryptorConfiguration = configuration; + }); + + return builder; + } + + /// + /// Configures the data protection system to use the + /// for data protection services. + /// + /// The . + /// A reference to the after this operation has completed. + /// + /// If this option is used, payloads protected by the data protection system will + /// be permanently undecipherable after the application exits. + /// + public static IDataProtectionBuilder UseEphemeralDataProtectionProvider(this IDataProtectionBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + builder.Services.Replace(ServiceDescriptor.Singleton()); + + return builder; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionOptions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionOptions.cs new file mode 100644 index 0000000000..c8707da1c3 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionOptions.cs @@ -0,0 +1,25 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Provides global options for the Data Protection system. + /// + public class DataProtectionOptions + { + /// + /// An identifier that uniquely discriminates this application from all other + /// applications on the machine. The discriminator value is implicitly included + /// in all protected payloads generated by the data protection system to isolate + /// multiple logical applications that all happen to be using the same key material. + /// + /// + /// If two different applications need to share protected payloads, they should + /// ensure that this property is set to the same value across both applications. + /// + public string ApplicationDiscriminator { get; set; } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionServiceCollectionExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionServiceCollectionExtensions.cs new file mode 100644 index 0000000000..b112e9ac68 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionServiceCollectionExtensions.cs @@ -0,0 +1,106 @@ +// 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 Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection.Infrastructure; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// Extension methods for setting up data protection services in an . + /// + public static class DataProtectionServiceCollectionExtensions + { + /// + /// Adds data protection services to the specified . + /// + /// The to add services to. + public static IDataProtectionBuilder AddDataProtection(this IServiceCollection services) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + services.TryAddSingleton(); + services.AddOptions(); + AddDataProtectionServices(services); + + return new DataProtectionBuilder(services); + } + + /// + /// Adds data protection services to the specified . + /// + /// The to add services to. + /// An to configure the provided . + /// A reference to this instance after the operation has completed. + public static IDataProtectionBuilder AddDataProtection(this IServiceCollection services, Action setupAction) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + if (setupAction == null) + { + throw new ArgumentNullException(nameof(setupAction)); + } + + var builder = services.AddDataProtection(); + services.Configure(setupAction); + return builder; + } + + private static void AddDataProtectionServices(IServiceCollection services) + { + if (OSVersionUtil.IsWindows()) + { + services.TryAddSingleton(); + } + + services.TryAddEnumerable( + ServiceDescriptor.Singleton, KeyManagementOptionsSetup>()); + services.TryAddEnumerable( + ServiceDescriptor.Transient, DataProtectionOptionsSetup>()); + + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddEnumerable(ServiceDescriptor.Singleton()); + + // Internal services + services.TryAddSingleton(); + services.TryAddSingleton(); + + services.TryAddSingleton(s => + { + var dpOptions = s.GetRequiredService>(); + var keyRingProvider = s.GetRequiredService(); + var loggerFactory = s.GetService() ?? NullLoggerFactory.Instance; + + IDataProtectionProvider dataProtectionProvider = new KeyRingBasedDataProtectionProvider(keyRingProvider, loggerFactory); + + // Link the provider to the supplied discriminator + if (!string.IsNullOrEmpty(dpOptions.Value.ApplicationDiscriminator)) + { + dataProtectionProvider = dataProtectionProvider.CreateProtector(dpOptions.Value.ApplicationDiscriminator); + } + + return dataProtectionProvider; + }); + + services.TryAddSingleton(); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionUtilityExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionUtilityExtensions.cs new file mode 100644 index 0000000000..04152f3ed6 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/DataProtectionUtilityExtensions.cs @@ -0,0 +1,46 @@ +// 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.ComponentModel; +using Microsoft.AspNetCore.DataProtection.Infrastructure; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.DataProtection +{ + public static class DataProtectionUtilityExtensions + { + /// + /// Returns a unique identifier for this application. + /// + /// The application-level . + /// A unique application identifier, or null if is null + /// or cannot provide a unique application identifier. + /// + /// + /// The returned identifier should be stable for repeated runs of this same application on + /// this machine. Additionally, the identifier is only unique within the scope of a single + /// machine, e.g., two different applications on two different machines may return the same + /// value. + /// + /// + /// This identifier may contain security-sensitive information such as physical file paths, + /// configuration settings, or other machine-specific information. Callers should take + /// special care not to disclose this information to untrusted entities. + /// + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static string GetApplicationUniqueIdentifier(this IServiceProvider services) + { + string discriminator = null; + if (services != null) + { + discriminator = services.GetService()?.Discriminator; + } + + // Remove whitespace and homogenize empty -> null + discriminator = discriminator?.Trim(); + return (string.IsNullOrEmpty(discriminator)) ? null : discriminator; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/EphemeralDataProtectionProvider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/EphemeralDataProtectionProvider.cs new file mode 100644 index 0000000000..587b0ebfd4 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/EphemeralDataProtectionProvider.cs @@ -0,0 +1,124 @@ +// 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 Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// An that is transient. + /// + /// + /// Payloads generated by a given instance can only + /// be deciphered by that same instance. Once the instance is lost, all ciphertexts + /// generated by that instance are permanently undecipherable. + /// + public sealed class EphemeralDataProtectionProvider : IDataProtectionProvider + { + private readonly KeyRingBasedDataProtectionProvider _dataProtectionProvider; + + /// + /// Creates an ephemeral . + /// + public EphemeralDataProtectionProvider() + : this (NullLoggerFactory.Instance) + { } + + /// + /// Creates an ephemeral with logging. + /// + /// The . + public EphemeralDataProtectionProvider(ILoggerFactory loggerFactory) + { + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + + IKeyRingProvider keyringProvider; + if (OSVersionUtil.IsWindows()) + { + // Fastest implementation: AES-256-GCM [CNG] + keyringProvider = new EphemeralKeyRing(loggerFactory); + } + else + { + // Slowest implementation: AES-256-CBC + HMACSHA256 [Managed] + keyringProvider = new EphemeralKeyRing(loggerFactory); + } + + var logger = loggerFactory.CreateLogger(); + logger.UsingEphemeralDataProtectionProvider(); + + _dataProtectionProvider = new KeyRingBasedDataProtectionProvider(keyringProvider, loggerFactory); + } + + public IDataProtector CreateProtector(string purpose) + { + if (purpose == null) + { + throw new ArgumentNullException(nameof(purpose)); + } + + // just forward to the underlying provider + return _dataProtectionProvider.CreateProtector(purpose); + } + + private sealed class EphemeralKeyRing : IKeyRing, IKeyRingProvider + where T : AlgorithmConfiguration, new() + { + public EphemeralKeyRing(ILoggerFactory loggerFactory) + { + DefaultAuthenticatedEncryptor = GetDefaultEncryptor(loggerFactory); + } + + // Currently hardcoded to a 512-bit KDK. + private const int NUM_BYTES_IN_KDK = 512 / 8; + + public IAuthenticatedEncryptor DefaultAuthenticatedEncryptor { get; } + + public Guid DefaultKeyId { get; } = default(Guid); + + public IAuthenticatedEncryptor GetAuthenticatedEncryptorByKeyId(Guid keyId, out bool isRevoked) + { + isRevoked = false; + return (keyId == default(Guid)) ? DefaultAuthenticatedEncryptor : null; + } + + public IKeyRing GetCurrentKeyRing() + { + return this; + } + + private static IAuthenticatedEncryptor GetDefaultEncryptor(ILoggerFactory loggerFactory) + { + var configuration = new T(); + if (configuration is CngGcmAuthenticatedEncryptorConfiguration) + { + var descriptor = (CngGcmAuthenticatedEncryptorDescriptor)new T().CreateNewDescriptor(); + return new CngGcmAuthenticatedEncryptorFactory(loggerFactory) + .CreateAuthenticatedEncryptorInstance( + descriptor.MasterKey, + configuration as CngGcmAuthenticatedEncryptorConfiguration); + } + else if (configuration is ManagedAuthenticatedEncryptorConfiguration) + { + var descriptor = (ManagedAuthenticatedEncryptorDescriptor)new T().CreateNewDescriptor(); + return new ManagedAuthenticatedEncryptorFactory(loggerFactory) + .CreateAuthenticatedEncryptorInstance( + descriptor.MasterKey, + configuration as ManagedAuthenticatedEncryptorConfiguration); + } + + return null; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Error.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Error.cs new file mode 100644 index 0000000000..304f08e5c5 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Error.cs @@ -0,0 +1,95 @@ +// 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.Globalization; +using System.Security.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal static class Error + { + public static InvalidOperationException CertificateXmlEncryptor_CertificateNotFound(string thumbprint) + { + var message = Resources.FormatCertificateXmlEncryptor_CertificateNotFound(thumbprint); + return new InvalidOperationException(message); + } + + public static ArgumentException Common_ArgumentCannotBeNullOrEmpty(string parameterName) + { + return new ArgumentException(Resources.Common_ArgumentCannotBeNullOrEmpty, parameterName); + } + + public static ArgumentException Common_BufferIncorrectlySized(string parameterName, int actualSize, int expectedSize) + { + var message = Resources.FormatCommon_BufferIncorrectlySized(actualSize, expectedSize); + return new ArgumentException(message, parameterName); + } + + public static CryptographicException CryptCommon_GenericError(Exception inner = null) + { + return new CryptographicException(Resources.CryptCommon_GenericError, inner); + } + + public static CryptographicException CryptCommon_PayloadInvalid() + { + var message = Resources.CryptCommon_PayloadInvalid; + return new CryptographicException(message); + } + + public static InvalidOperationException Common_PropertyCannotBeNullOrEmpty(string propertyName) + { + var message = string.Format(CultureInfo.CurrentCulture, Resources.Common_PropertyCannotBeNullOrEmpty, propertyName); + return new InvalidOperationException(message); + } + + public static InvalidOperationException Common_PropertyMustBeNonNegative(string propertyName) + { + var message = string.Format(CultureInfo.CurrentCulture, Resources.Common_PropertyMustBeNonNegative, propertyName); + return new InvalidOperationException(message); + } + + public static CryptographicException Common_EncryptionFailed(Exception inner = null) + { + return new CryptographicException(Resources.Common_EncryptionFailed, inner); + } + + public static CryptographicException Common_KeyNotFound(Guid id) + { + var message = string.Format(CultureInfo.CurrentCulture, Resources.Common_KeyNotFound, id); + return new CryptographicException(message); + } + + public static CryptographicException Common_KeyRevoked(Guid id) + { + var message = string.Format(CultureInfo.CurrentCulture, Resources.Common_KeyRevoked, id); + return new CryptographicException(message); + } + + public static ArgumentOutOfRangeException Common_ValueMustBeNonNegative(string paramName) + { + return new ArgumentOutOfRangeException(paramName, Resources.Common_ValueMustBeNonNegative); + } + + public static CryptographicException DecryptionFailed(Exception inner) + { + return new CryptographicException(Resources.Common_DecryptionFailed, inner); + } + + public static CryptographicException ProtectionProvider_BadMagicHeader() + { + return new CryptographicException(Resources.ProtectionProvider_BadMagicHeader); + } + + public static CryptographicException ProtectionProvider_BadVersion() + { + return new CryptographicException(Resources.ProtectionProvider_BadVersion); + } + + public static InvalidOperationException XmlKeyManager_DuplicateKey(Guid keyId) + { + var message = string.Format(CultureInfo.CurrentCulture, Resources.XmlKeyManager_DuplicateKey, keyId); + return new InvalidOperationException(message); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/IDataProtectionBuilder.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/IDataProtectionBuilder.cs new file mode 100644 index 0000000000..95c7c61f50 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/IDataProtectionBuilder.cs @@ -0,0 +1,43 @@ +// 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.IO; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Provides access to configuration for the data protection system, which allows the + /// developer to configure default cryptographic algorithms, key storage locations, + /// and the mechanism by which keys are protected at rest. + /// + /// + /// + /// If the developer changes the at-rest key protection mechanism, it is intended that + /// he also change the key storage location, and vice versa. For instance, a call to + /// should generally be accompanied by + /// a call to , or exceptions may + /// occur at runtime due to the data protection system not knowing where to persist keys. + /// + /// + /// Similarly, when a developer modifies the default protected payload cryptographic + /// algorithms, it is intended that he also select an explitiy key storage location. + /// A call to + /// should therefore generally be paired with a call to , + /// for example. + /// + /// + /// When the default cryptographic algorithms or at-rest key protection mechanisms are + /// changed, they only affect new keys in the repository. The repository may + /// contain existing keys that use older algorithms or protection mechanisms. + /// + /// + public interface IDataProtectionBuilder + { + /// + /// Provides access to the passed to this object's constructor. + /// + IServiceCollection Services { get; } + } +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/IPersistedDataProtector.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/IPersistedDataProtector.cs new file mode 100644 index 0000000000..0e0310cd1d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/IPersistedDataProtector.cs @@ -0,0 +1,36 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// An interface that can provide data protection services for data which has been persisted + /// to long-term storage. + /// + public interface IPersistedDataProtector : IDataProtector + { + /// + /// Cryptographically unprotects a piece of data, optionally ignoring failures due to + /// revocation of the cryptographic keys used to protect the payload. + /// + /// The protected data to unprotect. + /// 'true' if the payload should be unprotected even + /// if the cryptographic key used to protect it has been revoked (due to potential compromise), + /// 'false' if revocation should fail the unprotect operation. + /// 'true' if the data should be reprotected before being + /// persisted back to long-term storage, 'false' otherwise. Migration might be requested + /// when the default protection key has changed, for instance. + /// 'true' if the cryptographic key used to protect this payload + /// has been revoked, 'false' otherwise. Payloads whose keys have been revoked should be + /// treated as suspect unless the application has separate assurance that the payload + /// has not been tampered with. + /// The plaintext form of the protected data. + /// + /// Implementations should throw CryptographicException if the protected data is + /// invalid or malformed. + /// + byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/IRegistryPolicyResolver.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/IRegistryPolicyResolver.cs new file mode 100644 index 0000000000..b188bf40f7 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/IRegistryPolicyResolver.cs @@ -0,0 +1,13 @@ +// 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. + +namespace Microsoft.AspNetCore.DataProtection +{ + // Single implementation of this interface is conditionally added to DI on Windows + // We have to use interface because some DI implementations would try to activate class + // even if it was not registered causing problems crossplat + internal interface IRegistryPolicyResolver + { + RegistryPolicy ResolvePolicy(); + } +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ISecret.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ISecret.cs new file mode 100644 index 0000000000..4010bc6445 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/ISecret.cs @@ -0,0 +1,27 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Represents a secret value. + /// + public interface ISecret : IDisposable + { + /// + /// The length (in bytes) of the secret value. + /// + int Length { get; } + + /// + /// Writes the secret value to the specified buffer. + /// + /// The buffer which should receive the secret value. + /// + /// The buffer size must exactly match the length of the secret value. + /// + void WriteSecretIntoBuffer(ArraySegment buffer); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DataProtectionBuilder.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DataProtectionBuilder.cs new file mode 100644 index 0000000000..bc8908c9c4 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DataProtectionBuilder.cs @@ -0,0 +1,30 @@ +// 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 Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.DataProtection.Internal +{ + /// + /// Default implementation of . + /// + public class DataProtectionBuilder : IDataProtectionBuilder + { + /// + /// Creates a new configuration object linked to a . + /// + public DataProtectionBuilder(IServiceCollection services) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + Services = services; + } + + /// + public IServiceCollection Services { get; } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DataProtectionOptionsSetup.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DataProtectionOptionsSetup.cs new file mode 100644 index 0000000000..d5e25b7586 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DataProtectionOptionsSetup.cs @@ -0,0 +1,23 @@ +// 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 Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.DataProtection.Internal +{ + internal class DataProtectionOptionsSetup : IConfigureOptions + { + private readonly IServiceProvider _services; + + public DataProtectionOptionsSetup(IServiceProvider provider) + { + _services = provider; + } + + public void Configure(DataProtectionOptions options) + { + options.ApplicationDiscriminator = _services.GetApplicationUniqueIdentifier(); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DataProtectionStartupFilter.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DataProtectionStartupFilter.cs new file mode 100644 index 0000000000..d9faa5b0f8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DataProtectionStartupFilter.cs @@ -0,0 +1,48 @@ +// 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 Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Microsoft.AspNetCore.DataProtection.Internal +{ + internal class DataProtectionStartupFilter : IStartupFilter + { + private readonly IKeyRingProvider _keyRingProvider; + private readonly ILogger _logger; + + public DataProtectionStartupFilter(IKeyRingProvider keyRingProvider) + : this(keyRingProvider, NullLoggerFactory.Instance) + { } + + public DataProtectionStartupFilter(IKeyRingProvider keyRingProvider, ILoggerFactory loggerFactory) + { + _keyRingProvider = keyRingProvider; + _logger = loggerFactory.CreateLogger(); + } + + public Action Configure(Action next) + { + try + { + // It doesn't look like much, but this preloads the key ring, + // which in turn may load data from remote stores like Redis or Azure. + var keyRing = _keyRingProvider.GetCurrentKeyRing(); + + _logger.KeyRingWasLoadedOnStartup(keyRing.DefaultKeyId); + } + catch (Exception ex) + { + // This should be non-fatal, so swallow, log, and allow server startup to continue. + // The KeyRingProvider may be able to try again on the first request. + _logger.KeyRingFailedToLoadOnStartup(ex); + } + + return next; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DockerUtils.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DockerUtils.cs new file mode 100644 index 0000000000..7a1ede17e0 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/DockerUtils.cs @@ -0,0 +1,99 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Microsoft.AspNetCore.DataProtection.Internal +{ + internal static class DockerUtils + { + private static Lazy _isDocker = new Lazy(IsProcessRunningInDocker); + + public static bool IsDocker => _isDocker.Value; + + public static bool IsVolumeMountedFolder(DirectoryInfo directory) + { + if (!IsDocker) + { + return false; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // we currently don't have a good way to detect mounted file systems within Windows ctonainers + return false; + } + + const string mountsFile = "/proc/self/mounts"; + if (!File.Exists(mountsFile)) + { + return false; + } + + var lines = File.ReadAllLines(mountsFile); + return IsDirectoryMounted(directory, lines); + } + + // internal for testing. Don't use directly + internal static bool IsDirectoryMounted(DirectoryInfo directory, IEnumerable fstab) + { + // Expected file format: http://man7.org/linux/man-pages/man5/fstab.5.html + foreach (var line in fstab) + { + if (line == null || line.Length == 0 || line[0] == '#') + { + // skip empty and commented-out lines + continue; + } + + var fields = line.Split(new[] { '\t', ' ' }); + + if (fields.Length < 2 // line had too few fields + || fields[1].Length <= 1 // fs_file empty or is the root directory '/' + || fields[1][0] != '/') // fs_file was not a file path + { + continue; + } + + // check if directory is a subdirectory of this location + var fs_file = new DirectoryInfo(fields[1].TrimEnd(Path.DirectorySeparatorChar)).FullName; + var dir = directory; + while (dir != null) + { + // filesystems on Linux are case sensitive + if (fs_file.Equals(dir.FullName.TrimEnd(Path.DirectorySeparatorChar), StringComparison.Ordinal)) + { + return true; + } + + dir = dir.Parent; + } + } + + return false; + } + + private static bool IsProcessRunningInDocker() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // we currently don't have a good way to detect if running in a Windows container + return false; + } + + const string procFile = "/proc/1/cgroup"; + if (!File.Exists(procFile)) + { + return false; + } + + var lines = File.ReadAllLines(procFile); + // typically the last line in the file is "1:name=openrc:/docker" + return lines.Reverse().Any(l => l.EndsWith("name=openrc:/docker", StringComparison.Ordinal)); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/HostingApplicationDiscriminator.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/HostingApplicationDiscriminator.cs new file mode 100644 index 0000000000..400d372418 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/HostingApplicationDiscriminator.cs @@ -0,0 +1,25 @@ +// 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 Microsoft.AspNetCore.DataProtection.Infrastructure; +using Microsoft.AspNetCore.Hosting; + +namespace Microsoft.AspNetCore.DataProtection.Internal +{ + internal class HostingApplicationDiscriminator : IApplicationDiscriminator + { + private readonly IHostingEnvironment _hosting; + + // the optional constructor for when IHostingEnvironment is not available from DI + public HostingApplicationDiscriminator() + { + } + + public HostingApplicationDiscriminator(IHostingEnvironment hosting) + { + _hosting = hosting; + } + + public string Discriminator => _hosting?.ContentRootPath; + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/IActivator.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/IActivator.cs new file mode 100644 index 0000000000..189e2ab303 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/IActivator.cs @@ -0,0 +1,20 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.Internal +{ + /// + /// An interface into that also supports + /// limited dependency injection (of ). + /// + public interface IActivator + { + /// + /// Creates an instance of and ensures + /// that it is assignable to . + /// + object CreateInstance(Type expectedBaseType, string implementationTypeName); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/KeyManagementOptionsSetup.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/KeyManagementOptionsSetup.cs new file mode 100644 index 0000000000..10707c9cab --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Internal/KeyManagementOptionsSetup.cs @@ -0,0 +1,78 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.DataProtection.Internal +{ + internal class KeyManagementOptionsSetup : IConfigureOptions + { + private readonly IRegistryPolicyResolver _registryPolicyResolver; + private readonly ILoggerFactory _loggerFactory; + + public KeyManagementOptionsSetup() + : this(NullLoggerFactory.Instance, registryPolicyResolver: null) + { + } + + public KeyManagementOptionsSetup(ILoggerFactory loggerFactory) + : this(loggerFactory, registryPolicyResolver: null) + { + } + + public KeyManagementOptionsSetup(IRegistryPolicyResolver registryPolicyResolver) + : this(NullLoggerFactory.Instance, registryPolicyResolver) + { + } + + public KeyManagementOptionsSetup(ILoggerFactory loggerFactory, IRegistryPolicyResolver registryPolicyResolver) + { + _loggerFactory = loggerFactory; + _registryPolicyResolver = registryPolicyResolver; + } + + public void Configure(KeyManagementOptions options) + { + RegistryPolicy context = null; + if (_registryPolicyResolver != null) + { + context = _registryPolicyResolver.ResolvePolicy(); + } + + if (context != null) + { + if (context.DefaultKeyLifetime.HasValue) + { + options.NewKeyLifetime = TimeSpan.FromDays(context.DefaultKeyLifetime.Value); + } + + options.AuthenticatedEncryptorConfiguration = context.EncryptorConfiguration; + + var escrowSinks = context.KeyEscrowSinks; + if (escrowSinks != null) + { + foreach (var escrowSink in escrowSinks) + { + options.KeyEscrowSinks.Add(escrowSink); + } + } + } + + if (options.AuthenticatedEncryptorConfiguration == null) + { + options.AuthenticatedEncryptorConfiguration = new AuthenticatedEncryptorConfiguration(); + } + + options.AuthenticatedEncryptorFactories.Add(new CngGcmAuthenticatedEncryptorFactory(_loggerFactory)); + options.AuthenticatedEncryptorFactories.Add(new CngCbcAuthenticatedEncryptorFactory(_loggerFactory)); + options.AuthenticatedEncryptorFactories.Add(new ManagedAuthenticatedEncryptorFactory(_loggerFactory)); + options.AuthenticatedEncryptorFactories.Add(new AuthenticatedEncryptorFactory(_loggerFactory)); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DefaultKeyResolver.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DefaultKeyResolver.cs new file mode 100644 index 0000000000..b4f686c9f3 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DefaultKeyResolver.cs @@ -0,0 +1,146 @@ +// 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.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// Implements policy for resolving the default key from a candidate keyring. + /// + internal sealed class DefaultKeyResolver : IDefaultKeyResolver + { + /// + /// The window of time before the key expires when a new key should be created + /// and persisted to the keyring to ensure uninterrupted service. + /// + /// + /// If the propagation time is 5 days and the current key expires within 5 days, + /// a new key will be generated. + /// + private readonly TimeSpan _keyPropagationWindow; + + private readonly ILogger _logger; + + /// + /// The maximum skew that is allowed between servers. + /// This is used to allow newly-created keys to be used across servers even though + /// their activation dates might be a few minutes into the future. + /// + /// + /// If the max skew is 5 minutes and the best matching candidate default key has + /// an activation date of less than 5 minutes in the future, we'll use it. + /// + private readonly TimeSpan _maxServerToServerClockSkew; + + public DefaultKeyResolver(IOptions keyManagementOptions) + : this(keyManagementOptions, NullLoggerFactory.Instance) + { } + + public DefaultKeyResolver(IOptions keyManagementOptions, ILoggerFactory loggerFactory) + { + _keyPropagationWindow = keyManagementOptions.Value.KeyPropagationWindow; + _maxServerToServerClockSkew = keyManagementOptions.Value.MaxServerClockSkew; + _logger = loggerFactory.CreateLogger(); + } + + private bool CanCreateAuthenticatedEncryptor(IKey key) + { + try + { + var encryptorInstance = key.CreateEncryptor(); + if (encryptorInstance == null) + { + CryptoUtil.Fail("CreateEncryptorInstance returned null."); + } + + return true; + } + catch (Exception ex) + { + _logger.KeyIsIneligibleToBeTheDefaultKeyBecauseItsMethodFailed(key.KeyId, nameof(IKey.CreateEncryptor), ex); + return false; + } + } + + private IKey FindDefaultKey(DateTimeOffset now, IEnumerable allKeys, out IKey fallbackKey, out bool callerShouldGenerateNewKey) + { + // find the preferred default key (allowing for server-to-server clock skew) + var preferredDefaultKey = (from key in allKeys + where key.ActivationDate <= now + _maxServerToServerClockSkew + orderby key.ActivationDate descending, key.KeyId ascending + select key).FirstOrDefault(); + + if (preferredDefaultKey != null) + { + _logger.ConsideringKeyWithExpirationDateAsDefaultKey(preferredDefaultKey.KeyId, preferredDefaultKey.ExpirationDate); + + // if the key has been revoked or is expired, it is no longer a candidate + if (preferredDefaultKey.IsRevoked || preferredDefaultKey.IsExpired(now) || !CanCreateAuthenticatedEncryptor(preferredDefaultKey)) + { + _logger.KeyIsNoLongerUnderConsiderationAsDefault(preferredDefaultKey.KeyId); + preferredDefaultKey = null; + } + } + + // Only the key that has been most recently activated is eligible to be the preferred default, + // and only if it hasn't expired or been revoked. This is intentional: generating a new key is + // an implicit signal that we should stop using older keys (even if they're not revoked), so + // activating a new key should permanently mark all older keys as non-preferred. + + if (preferredDefaultKey != null) + { + // Does *any* key in the key ring fulfill the requirement that its activation date is prior + // to the preferred default key's expiration date (allowing for skew) and that it will + // remain valid one propagation cycle from now? If so, the caller doesn't need to add a + // new key. + callerShouldGenerateNewKey = !allKeys.Any(key => + key.ActivationDate <= (preferredDefaultKey.ExpirationDate + _maxServerToServerClockSkew) + && !key.IsExpired(now + _keyPropagationWindow) + && !key.IsRevoked); + + if (callerShouldGenerateNewKey) + { + _logger.DefaultKeyExpirationImminentAndRepository(); + } + + fallbackKey = null; + return preferredDefaultKey; + } + + // If we got this far, the caller must generate a key now. + // We should locate a fallback key, which is a key that can be used to protect payloads if + // the caller is configured not to generate a new key. We should try to make sure the fallback + // key has propagated to all callers (so its creation date should be before the previous + // propagation period), and we cannot use revoked keys. The fallback key may be expired. + fallbackKey = (from key in (from key in allKeys + where key.CreationDate <= now - _keyPropagationWindow + orderby key.CreationDate descending + select key).Concat(from key in allKeys + orderby key.CreationDate ascending + select key) + where !key.IsRevoked && CanCreateAuthenticatedEncryptor(key) + select key).FirstOrDefault(); + + _logger.RepositoryContainsNoViableDefaultKey(); + + callerShouldGenerateNewKey = true; + return null; + } + + public DefaultKeyResolution ResolveDefaultKeyPolicy(DateTimeOffset now, IEnumerable allKeys) + { + var retVal = default(DefaultKeyResolution); + retVal.DefaultKey = FindDefaultKey(now, allKeys, out retVal.FallbackKey, out retVal.ShouldGenerateNewKey); + return retVal; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DeferredKey.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DeferredKey.cs new file mode 100644 index 0000000000..a21210aceb --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DeferredKey.cs @@ -0,0 +1,55 @@ +// 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.Collections.Generic; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// The basic implementation of , where the incoming XML element + /// hasn't yet been fully processed. + /// + internal sealed class DeferredKey : KeyBase + { + public DeferredKey( + Guid keyId, + DateTimeOffset creationDate, + DateTimeOffset activationDate, + DateTimeOffset expirationDate, + IInternalXmlKeyManager keyManager, + XElement keyElement, + IEnumerable encryptorFactories) + : base(keyId, + creationDate, + activationDate, + expirationDate, + new Lazy(GetLazyDescriptorDelegate(keyManager, keyElement)), + encryptorFactories) + { + } + + private static Func GetLazyDescriptorDelegate(IInternalXmlKeyManager keyManager, XElement keyElement) + { + // The element will be held around in memory for a potentially lengthy period + // of time. Since it might contain sensitive information, we should protect it. + var encryptedKeyElement = keyElement.ToSecret(); + + try + { + return () => keyManager.DeserializeDescriptorFromKeyElement(encryptedKeyElement.ToXElement()); + } + finally + { + // It's important that the lambda above doesn't capture 'descriptorElement'. Clearing the reference here + // helps us detect if we've done this by causing a null ref at runtime. + keyElement = null; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKey.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKey.cs new file mode 100644 index 0000000000..f590c01c1b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKey.cs @@ -0,0 +1,60 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// The basic interface for representing an authenticated encryption key. + /// + public interface IKey + { + /// + /// The date at which encryptions with this key can begin taking place. + /// + DateTimeOffset ActivationDate { get; } + + /// + /// The date on which this key was created. + /// + DateTimeOffset CreationDate { get; } + + /// + /// The date after which encryptions with this key may no longer take place. + /// + /// + /// An expired key may still be used to decrypt existing payloads. + /// + DateTimeOffset ExpirationDate { get; } + + /// + /// Returns a value stating whether this key was revoked. + /// + /// + /// A revoked key may still be used to decrypt existing payloads, but the payloads + /// must be treated as tampered unless the application has some other assurance + /// that the payloads are authentic. + /// + bool IsRevoked { get; } + + /// + /// The id of the key. + /// + Guid KeyId { get; } + + /// + /// Gets the instance associated with this key. + /// + IAuthenticatedEncryptorDescriptor Descriptor { get; } + + /// + /// Creates an instance that can be used to encrypt data + /// to and decrypt data from this key. + /// + /// An . + IAuthenticatedEncryptor CreateEncryptor(); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKeyEscrowSink.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKeyEscrowSink.cs new file mode 100644 index 0000000000..64b94e844e --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKeyEscrowSink.cs @@ -0,0 +1,27 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.Repositories; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// The basic interface for implementing a key escrow sink. + /// + /// + /// is distinct from in that + /// provides a write-only interface and instances handle unencrypted key material, + /// while provides a read+write interface and instances handle encrypted key material. + /// + public interface IKeyEscrowSink + { + /// + /// Stores the given key material to the escrow service. + /// + /// The id of the key being persisted to escrow. + /// The unencrypted XML element that comprises the key material. + void Store(Guid keyId, XElement element); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKeyManager.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKeyManager.cs new file mode 100644 index 0000000000..6debf4ac96 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKeyManager.cs @@ -0,0 +1,77 @@ +// 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.Collections.Generic; +using System.Threading; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// The basic interface for performing key management operations. + /// + /// + /// Instantiations of this interface are expected to be thread-safe. + /// + public interface IKeyManager + { + /// + /// Creates a new key with the specified activation and expiration dates and persists + /// the new key to the underlying repository. + /// + /// The date on which encryptions to this key may begin. + /// The date after which encryptions to this key may no longer take place. + /// The newly-created IKey instance. + IKey CreateNewKey(DateTimeOffset activationDate, DateTimeOffset expirationDate); + + /// + /// Fetches all keys from the underlying repository. + /// + /// The collection of all keys. + IReadOnlyCollection GetAllKeys(); + + /// + /// Retrieves a token that signals that callers who have cached the return value of + /// GetAllKeys should clear their caches. This could be in response to a call to + /// CreateNewKey or RevokeKey, or it could be in response to some other external notification. + /// Callers who are interested in observing this token should call this method before the + /// corresponding call to GetAllKeys. + /// + /// + /// The cache expiration token. When an expiration notification is triggered, any + /// tokens previously returned by this method will become canceled, and tokens returned by + /// future invocations of this method will themselves not trigger until the next expiration + /// event. + /// + /// + /// Implementations are free to return 'CancellationToken.None' from this method. + /// Since this token is never guaranteed to fire, callers should still manually + /// clear their caches at a regular interval. + /// + CancellationToken GetCacheExpirationToken(); + + /// + /// Revokes a specific key and persists the revocation to the underlying repository. + /// + /// The id of the key to revoke. + /// An optional human-readable reason for revocation. + /// + /// This method will not mutate existing IKey instances. After calling this method, + /// all existing IKey instances should be discarded, and GetAllKeys should be called again. + /// + void RevokeKey(Guid keyId, string reason = null); + + /// + /// Revokes all keys created before a specified date and persists the revocation to the + /// underlying repository. + /// + /// The revocation date. All keys with a creation date before + /// this value will be revoked. + /// An optional human-readable reason for revocation. + /// + /// This method will not mutate existing IKey instances. After calling this method, + /// all existing IKey instances should be discarded, and GetAllKeys should be called again. + /// + void RevokeAllKeys(DateTimeOffset revocationDate, string reason = null); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/CacheableKeyRing.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/CacheableKeyRing.cs new file mode 100644 index 0000000000..ff6fa87fce --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/CacheableKeyRing.cs @@ -0,0 +1,52 @@ +// 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.Collections.Generic; +using System.Threading; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal +{ + /// + /// Wraps both a keyring and its expiration policy. + /// + public sealed class CacheableKeyRing + { + private readonly CancellationToken _expirationToken; + + internal CacheableKeyRing(CancellationToken expirationToken, DateTimeOffset expirationTime, IKey defaultKey, IEnumerable allKeys) + : this(expirationToken, expirationTime, keyRing: new KeyRing(defaultKey, allKeys)) + { + } + + internal CacheableKeyRing(CancellationToken expirationToken, DateTimeOffset expirationTime, IKeyRing keyRing) + { + _expirationToken = expirationToken; + ExpirationTimeUtc = expirationTime.UtcDateTime; + KeyRing = keyRing; + } + + internal DateTime ExpirationTimeUtc { get; } + + internal IKeyRing KeyRing { get; } + + internal static bool IsValid(CacheableKeyRing keyRing, DateTime utcNow) + { + return keyRing != null + && !keyRing._expirationToken.IsCancellationRequested + && keyRing.ExpirationTimeUtc > utcNow; + } + + /// + /// Returns a new which is identical to 'this' but with a + /// lifetime extended 2 minutes from . The inner cancellation token + /// is also disconnected. + /// + internal CacheableKeyRing WithTemporaryExtendedLifetime(DateTimeOffset now) + { + var extension = TimeSpan.FromMinutes(2); + return new CacheableKeyRing(CancellationToken.None, now + extension, KeyRing); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/DefaultKeyResolution.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/DefaultKeyResolution.cs new file mode 100644 index 0000000000..1c4170607b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/DefaultKeyResolution.cs @@ -0,0 +1,36 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal +{ + public struct DefaultKeyResolution + { + /// + /// The default key, may be null if no key is a good default candidate. + /// + /// + /// If this property is non-null, its method will succeed + /// so is appropriate for use with deferred keys. + /// + public IKey DefaultKey; + + /// + /// The fallback key, which should be used only if the caller is configured not to + /// honor the property. This property may + /// be null if there is no viable fallback key. + /// + /// + /// If this property is non-null, its method will succeed + /// so is appropriate for use with deferred keys. + /// + public IKey FallbackKey; + + /// + /// 'true' if a new key should be persisted to the keyring, 'false' otherwise. + /// This value may be 'true' even if a valid default key was found. + /// + public bool ShouldGenerateNewKey; + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/ICacheableKeyRingProvider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/ICacheableKeyRingProvider.cs new file mode 100644 index 0000000000..367080f2b8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/ICacheableKeyRingProvider.cs @@ -0,0 +1,12 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal +{ + public interface ICacheableKeyRingProvider + { + CacheableKeyRing GetCacheableKeyRing(DateTimeOffset now); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IDefaultKeyResolver.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IDefaultKeyResolver.cs new file mode 100644 index 0000000000..f891d0d4fb --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IDefaultKeyResolver.cs @@ -0,0 +1,19 @@ +// 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.Collections.Generic; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal +{ + /// + /// Implements policy for resolving the default key from a candidate keyring. + /// + public interface IDefaultKeyResolver + { + /// + /// Locates the default key from the keyring. + /// + DefaultKeyResolution ResolveDefaultKeyPolicy(DateTimeOffset now, IEnumerable allKeys); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IInternalXmlKeyManager.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IInternalXmlKeyManager.cs new file mode 100644 index 0000000000..9ebaa4c63c --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IInternalXmlKeyManager.cs @@ -0,0 +1,18 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal +{ + public interface IInternalXmlKeyManager + { + IKey CreateNewKey(Guid keyId, DateTimeOffset creationDate, DateTimeOffset activationDate, DateTimeOffset expirationDate); + + IAuthenticatedEncryptorDescriptor DeserializeDescriptorFromKeyElement(XElement keyElement); + + void RevokeSingleKey(Guid keyId, DateTimeOffset revocationDate, string reason); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IKeyRing.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IKeyRing.cs new file mode 100644 index 0000000000..60ff02f2ed --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IKeyRing.cs @@ -0,0 +1,36 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal +{ + /// + /// The basic interface for accessing a read-only keyring. + /// + public interface IKeyRing + { + /// + /// The authenticated encryptor that shall be used for new encryption operations. + /// + /// + /// Activation of the encryptor instance is deferred until first access. + /// + IAuthenticatedEncryptor DefaultAuthenticatedEncryptor { get; } + + /// + /// The id of the key associated with . + /// + Guid DefaultKeyId { get; } + + /// + /// Returns an encryptor instance for the given key, or 'null' if the key with the + /// specified id cannot be found in the keyring. + /// + /// + /// Activation of the encryptor instance is deferred until first access. + /// + IAuthenticatedEncryptor GetAuthenticatedEncryptorByKeyId(Guid keyId, out bool isRevoked); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IKeyRingProvider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IKeyRingProvider.cs new file mode 100644 index 0000000000..3a507f1250 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/IKeyRingProvider.cs @@ -0,0 +1,10 @@ +// 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. + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal +{ + public interface IKeyRingProvider + { + IKeyRing GetCurrentKeyRing(); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Key.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Key.cs new file mode 100644 index 0000000000..84569a8e1b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Key.cs @@ -0,0 +1,33 @@ +// 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.Collections.Generic; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// The basic implementation of , where the + /// has already been created. + /// + internal sealed class Key : KeyBase + { + public Key( + Guid keyId, + DateTimeOffset creationDate, + DateTimeOffset activationDate, + DateTimeOffset expirationDate, + IAuthenticatedEncryptorDescriptor descriptor, + IEnumerable encryptorFactories) + : base(keyId, + creationDate, + activationDate, + expirationDate, + new Lazy(() => descriptor), + encryptorFactories) + { + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyBase.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyBase.cs new file mode 100644 index 0000000000..005a6ea9d5 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyBase.cs @@ -0,0 +1,78 @@ +// 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.Collections.Generic; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// The basic implementation of . + /// + internal abstract class KeyBase : IKey + { + private readonly Lazy _lazyDescriptor; + private readonly IEnumerable _encryptorFactories; + + private IAuthenticatedEncryptor _encryptor; + + public KeyBase( + Guid keyId, + DateTimeOffset creationDate, + DateTimeOffset activationDate, + DateTimeOffset expirationDate, + Lazy lazyDescriptor, + IEnumerable encryptorFactories) + { + KeyId = keyId; + CreationDate = creationDate; + ActivationDate = activationDate; + ExpirationDate = expirationDate; + _lazyDescriptor = lazyDescriptor; + _encryptorFactories = encryptorFactories; + } + + public DateTimeOffset ActivationDate { get; } + + public DateTimeOffset CreationDate { get; } + + public DateTimeOffset ExpirationDate { get; } + + public bool IsRevoked { get; private set; } + + public Guid KeyId { get; } + + public IAuthenticatedEncryptorDescriptor Descriptor + { + get + { + return _lazyDescriptor.Value; + } + } + + public IAuthenticatedEncryptor CreateEncryptor() + { + if (_encryptor == null) + { + foreach (var factory in _encryptorFactories) + { + var encryptor = factory.CreateEncryptorInstance(this); + if (encryptor != null) + { + _encryptor = encryptor; + break; + } + } + } + + return _encryptor; + } + + internal void SetRevoked() + { + IsRevoked = true; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyEscrowServiceProviderExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyEscrowServiceProviderExtensions.cs new file mode 100644 index 0000000000..85f1f62451 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyEscrowServiceProviderExtensions.cs @@ -0,0 +1,42 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + internal static class KeyEscrowServiceProviderExtensions + { + /// + /// Gets an aggregate from the underlying . + /// This method may return null if no sinks are registered. + /// + public static IKeyEscrowSink GetKeyEscrowSink(this IServiceProvider services) + { + var escrowSinks = services?.GetService>()?.ToList(); + return (escrowSinks != null && escrowSinks.Count > 0) ? new AggregateKeyEscrowSink(escrowSinks) : null; + } + + private sealed class AggregateKeyEscrowSink : IKeyEscrowSink + { + private readonly List _sinks; + + public AggregateKeyEscrowSink(List sinks) + { + _sinks = sinks; + } + + public void Store(Guid keyId, XElement element) + { + foreach (var sink in _sinks) + { + sink.Store(keyId, element); + } + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyExtensions.cs new file mode 100644 index 0000000000..5cd05bdb9b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyExtensions.cs @@ -0,0 +1,15 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + internal static class KeyExtensions + { + public static bool IsExpired(this IKey key, DateTimeOffset now) + { + return (key.ExpirationDate <= now); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyManagementOptions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyManagementOptions.cs new file mode 100644 index 0000000000..0680239f6b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyManagementOptions.cs @@ -0,0 +1,168 @@ +// 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.Collections.Generic; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Repositories; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// Options that control how an should behave. + /// + public class KeyManagementOptions + { + private static readonly TimeSpan _keyPropagationWindow = TimeSpan.FromDays(2); + private static readonly TimeSpan _keyRingRefreshPeriod = TimeSpan.FromHours(24); + private static readonly TimeSpan _maxServerClockSkew = TimeSpan.FromMinutes(5); + private TimeSpan _newKeyLifetime = TimeSpan.FromDays(90); + + public KeyManagementOptions() + { + } + + // copy ctor + internal KeyManagementOptions(KeyManagementOptions other) + { + if (other != null) + { + AutoGenerateKeys = other.AutoGenerateKeys; + _newKeyLifetime = other._newKeyLifetime; + XmlEncryptor = other.XmlEncryptor; + XmlRepository = other.XmlRepository; + AuthenticatedEncryptorConfiguration = other.AuthenticatedEncryptorConfiguration; + + foreach (var keyEscrowSink in other.KeyEscrowSinks) + { + KeyEscrowSinks.Add(keyEscrowSink); + } + + foreach (var encryptorFactory in other.AuthenticatedEncryptorFactories) + { + AuthenticatedEncryptorFactories.Add(encryptorFactory); + } + } + } + + /// + /// Specifies whether the data protection system should auto-generate keys. + /// + /// + /// If this value is 'false', the system will not generate new keys automatically. + /// The key ring must contain at least one active non-revoked key, otherwise calls + /// to may fail. The system may end up + /// protecting payloads to expired keys if this property is set to 'false'. + /// The default value is 'true'. + /// + public bool AutoGenerateKeys { get; set; } = true; + + /// + /// Specifies the period before key expiration in which a new key should be generated + /// so that it has time to propagate fully throughout the key ring. For example, if this + /// period is 72 hours, then a new key will be created and persisted to storage + /// approximately 72 hours before expiration. + /// + /// + /// This value is currently fixed at 48 hours. + /// + internal TimeSpan KeyPropagationWindow + { + get + { + // This value is not settable since there's a complex interaction between + // it and the key ring refresh period. + return _keyPropagationWindow; + } + } + + /// + /// Controls the auto-refresh period where the key ring provider will + /// flush its collection of cached keys and reread the collection from + /// backing storage. + /// + /// + /// This value is currently fixed at 24 hours. + /// + internal TimeSpan KeyRingRefreshPeriod + { + get + { + // This value is not settable since there's a complex interaction between + // it and the key expiration safety period. + return _keyRingRefreshPeriod; + } + } + + /// + /// Specifies the maximum clock skew allowed between servers when reading + /// keys from the key ring. The key ring may use a key which has not yet + /// been activated or which has expired if the key's valid lifetime is within + /// the allowed clock skew window. This value can be set to + /// if key activation and expiration times should be strictly honored by this server. + /// + /// + /// This value is currently fixed at 5 minutes. + /// + internal TimeSpan MaxServerClockSkew + { + get + { + return _maxServerClockSkew; + } + } + + /// + /// Controls the lifetime (number of days before expiration) + /// for newly-generated keys. + /// + /// + /// The lifetime cannot be less than one week. + /// The default value is 90 days. + /// + public TimeSpan NewKeyLifetime + { + get + { + return _newKeyLifetime; + } + set + { + if (value < TimeSpan.FromDays(7)) + { + throw new ArgumentOutOfRangeException(nameof(value), Resources.KeyManagementOptions_MinNewKeyLifetimeViolated); + } + _newKeyLifetime = value; + } + } + + /// + /// The instance that can be used to create + /// the instance. + /// + public AlgorithmConfiguration AuthenticatedEncryptorConfiguration { get; set; } + + /// + /// The list of to store the key material in. + /// + public IList KeyEscrowSinks { get; } = new List(); + + /// + /// The to use for storing and retrieving XML elements. + /// + public IXmlRepository XmlRepository { get; set; } + + /// + /// The to use for encrypting XML elements. + /// + public IXmlEncryptor XmlEncryptor { get; set; } + + /// + /// The list of that will be used for creating + /// s. + /// + public IList AuthenticatedEncryptorFactories { get; } = new List(); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRing.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRing.cs new file mode 100644 index 0000000000..2bbba031a6 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRing.cs @@ -0,0 +1,92 @@ +// 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.Collections.Generic; +using System.Threading; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// A basic implementation of . + /// + internal sealed class KeyRing : IKeyRing + { + private readonly KeyHolder _defaultKeyHolder; + private readonly Dictionary _keyIdToKeyHolderMap; + + public KeyRing(IKey defaultKey, IEnumerable allKeys) + { + _keyIdToKeyHolderMap = new Dictionary(); + foreach (IKey key in allKeys) + { + _keyIdToKeyHolderMap.Add(key.KeyId, new KeyHolder(key)); + } + + // It's possible under some circumstances that the default key won't be part of 'allKeys', + // such as if the key manager is forced to use the key it just generated even if such key + // wasn't in the underlying repository. In this case, we just add it now. + if (!_keyIdToKeyHolderMap.ContainsKey(defaultKey.KeyId)) + { + _keyIdToKeyHolderMap.Add(defaultKey.KeyId, new KeyHolder(defaultKey)); + } + + DefaultKeyId = defaultKey.KeyId; + _defaultKeyHolder = _keyIdToKeyHolderMap[DefaultKeyId]; + } + + public IAuthenticatedEncryptor DefaultAuthenticatedEncryptor + { + get + { + bool unused; + return _defaultKeyHolder.GetEncryptorInstance(out unused); + } + } + + public Guid DefaultKeyId { get; } + + public IAuthenticatedEncryptor GetAuthenticatedEncryptorByKeyId(Guid keyId, out bool isRevoked) + { + isRevoked = false; + KeyHolder holder; + _keyIdToKeyHolderMap.TryGetValue(keyId, out holder); + return holder?.GetEncryptorInstance(out isRevoked); + } + + // used for providing lazy activation of the authenticated encryptor instance + private sealed class KeyHolder + { + private readonly IKey _key; + private IAuthenticatedEncryptor _encryptor; + + internal KeyHolder(IKey key) + { + _key = key; + } + + internal IAuthenticatedEncryptor GetEncryptorInstance(out bool isRevoked) + { + // simple double-check lock pattern + // we can't use LazyInitializer because we don't have a simple value factory + IAuthenticatedEncryptor encryptor = Volatile.Read(ref _encryptor); + if (encryptor == null) + { + lock (this) + { + encryptor = Volatile.Read(ref _encryptor); + if (encryptor == null) + { + encryptor = _key.CreateEncryptor(); + Volatile.Write(ref _encryptor, encryptor); + } + } + } + isRevoked = _key.IsRevoked; + return encryptor; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingBasedDataProtectionProvider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingBasedDataProtectionProvider.cs new file mode 100644 index 0000000000..f7f785cc3b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingBasedDataProtectionProvider.cs @@ -0,0 +1,35 @@ +// 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 Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + internal unsafe sealed class KeyRingBasedDataProtectionProvider : IDataProtectionProvider + { + private readonly IKeyRingProvider _keyRingProvider; + private readonly ILogger _logger; + + public KeyRingBasedDataProtectionProvider(IKeyRingProvider keyRingProvider, ILoggerFactory loggerFactory) + { + _keyRingProvider = keyRingProvider; + _logger = loggerFactory.CreateLogger(); // note: for protector (not provider!) type + } + + public IDataProtector CreateProtector(string purpose) + { + if (purpose == null) + { + throw new ArgumentNullException(nameof(purpose)); + } + + return new KeyRingBasedDataProtector( + logger: _logger, + keyRingProvider: _keyRingProvider, + originalPurposes: null, + newPurpose: purpose); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs new file mode 100644 index 0000000000..e0157e66fe --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs @@ -0,0 +1,396 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + internal unsafe sealed class KeyRingBasedDataProtector : IDataProtector, IPersistedDataProtector + { + // This magic header identifies a v0 protected data blob. It's the high 28 bits of the SHA1 hash of + // "Microsoft.AspNet.DataProtection.KeyManagement.KeyRingBasedDataProtector" [US-ASCII], big-endian. + // The last nibble reserved for version information. There's also the nice property that "F0 C9" + // can never appear in a well-formed UTF8 sequence, so attempts to treat a protected payload as a + // UTF8-encoded string will fail, and devs can catch the mistake early. + private const uint MAGIC_HEADER_V0 = 0x09F0C9F0; + + private AdditionalAuthenticatedDataTemplate _aadTemplate; + private readonly IKeyRingProvider _keyRingProvider; + private readonly ILogger _logger; + + public KeyRingBasedDataProtector(IKeyRingProvider keyRingProvider, ILogger logger, string[] originalPurposes, string newPurpose) + { + Debug.Assert(keyRingProvider != null); + + Purposes = ConcatPurposes(originalPurposes, newPurpose); + _logger = logger; // can be null + _keyRingProvider = keyRingProvider; + _aadTemplate = new AdditionalAuthenticatedDataTemplate(Purposes); + } + + internal string[] Purposes { get; } + + private static string[] ConcatPurposes(string[] originalPurposes, string newPurpose) + { + if (originalPurposes != null && originalPurposes.Length > 0) + { + var newPurposes = new string[originalPurposes.Length + 1]; + Array.Copy(originalPurposes, 0, newPurposes, 0, originalPurposes.Length); + newPurposes[originalPurposes.Length] = newPurpose; + return newPurposes; + } + else + { + return new string[] { newPurpose }; + } + } + + public IDataProtector CreateProtector(string purpose) + { + if (purpose == null) + { + throw new ArgumentNullException(nameof(purpose)); + } + + return new KeyRingBasedDataProtector( + logger: _logger, + keyRingProvider: _keyRingProvider, + originalPurposes: Purposes, + newPurpose: purpose); + } + + private static string JoinPurposesForLog(IEnumerable purposes) + { + return "(" + String.Join(", ", purposes.Select(p => "'" + p + "'")) + ")"; + } + + // allows decrypting payloads whose keys have been revoked + public byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked) + { + // argument & state checking + if (protectedData == null) + { + throw new ArgumentNullException(nameof(protectedData)); + } + + UnprotectStatus status; + var retVal = UnprotectCore(protectedData, ignoreRevocationErrors, status: out status); + requiresMigration = (status != UnprotectStatus.Ok); + wasRevoked = (status == UnprotectStatus.DecryptionKeyWasRevoked); + return retVal; + } + + public byte[] Protect(byte[] plaintext) + { + if (plaintext == null) + { + throw new ArgumentNullException(nameof(plaintext)); + } + + try + { + // Perform the encryption operation using the current default encryptor. + var currentKeyRing = _keyRingProvider.GetCurrentKeyRing(); + var defaultKeyId = currentKeyRing.DefaultKeyId; + var defaultEncryptorInstance = currentKeyRing.DefaultAuthenticatedEncryptor; + CryptoUtil.Assert(defaultEncryptorInstance != null, "defaultEncryptorInstance != null"); + + if (_logger.IsDebugLevelEnabled()) + { + _logger.PerformingProtectOperationToKeyWithPurposes(defaultKeyId, JoinPurposesForLog(Purposes)); + } + + // We'll need to apply the default key id to the template if it hasn't already been applied. + // If the default key id has been updated since the last call to Protect, also write back the updated template. + var aad = _aadTemplate.GetAadForKey(defaultKeyId, isProtecting: true); + + // We allocate a 20-byte pre-buffer so that we can inject the magic header and key id into the return value. + var retVal = defaultEncryptorInstance.Encrypt( + plaintext: new ArraySegment(plaintext), + additionalAuthenticatedData: new ArraySegment(aad), + preBufferSize: (uint)(sizeof(uint) + sizeof(Guid)), + postBufferSize: 0); + CryptoUtil.Assert(retVal != null && retVal.Length >= sizeof(uint) + sizeof(Guid), "retVal != null && retVal.Length >= sizeof(uint) + sizeof(Guid)"); + + // At this point: retVal := { 000..000 || encryptorSpecificProtectedPayload }, + // where 000..000 is a placeholder for our magic header and key id. + + // Write out the magic header and key id + fixed (byte* pbRetVal = retVal) + { + WriteBigEndianInteger(pbRetVal, MAGIC_HEADER_V0); + Write32bitAlignedGuid(&pbRetVal[sizeof(uint)], defaultKeyId); + } + + // At this point, retVal := { magicHeader || keyId || encryptorSpecificProtectedPayload } + // And we're done! + return retVal; + } + catch (Exception ex) when (ex.RequiresHomogenization()) + { + // homogenize all errors to CryptographicException + throw Error.Common_EncryptionFailed(ex); + } + } + + // Helper function to read a GUID from a 32-bit alignment; useful on architectures where unaligned reads + // can result in weird behaviors at runtime. + private static Guid Read32bitAlignedGuid(void* ptr) + { + Debug.Assert((long)ptr % 4 == 0); + + Guid retVal; + ((int*)&retVal)[0] = ((int*)ptr)[0]; + ((int*)&retVal)[1] = ((int*)ptr)[1]; + ((int*)&retVal)[2] = ((int*)ptr)[2]; + ((int*)&retVal)[3] = ((int*)ptr)[3]; + return retVal; + } + + private static uint ReadBigEndian32BitInteger(byte* ptr) + { + return ((uint)ptr[0] << 24) + | ((uint)ptr[1] << 16) + | ((uint)ptr[2] << 8) + | ((uint)ptr[3]); + } + + private static bool TryGetVersionFromMagicHeader(uint magicHeader, out int version) + { + const uint MAGIC_HEADER_VERSION_MASK = 0xFU; + if ((magicHeader & ~MAGIC_HEADER_VERSION_MASK) == MAGIC_HEADER_V0) + { + version = (int)(magicHeader & MAGIC_HEADER_VERSION_MASK); + return true; + } + else + { + version = default(int); + return false; + } + } + + public byte[] Unprotect(byte[] protectedData) + { + if (protectedData == null) + { + throw new ArgumentNullException(nameof(protectedData)); + } + + // Argument checking will be done by the callee + bool requiresMigration, wasRevoked; // unused + return DangerousUnprotect(protectedData, + ignoreRevocationErrors: false, + requiresMigration: out requiresMigration, + wasRevoked: out wasRevoked); + } + + private byte[] UnprotectCore(byte[] protectedData, bool allowOperationsOnRevokedKeys, out UnprotectStatus status) + { + Debug.Assert(protectedData != null); + + try + { + // argument & state checking + if (protectedData.Length < sizeof(uint) /* magic header */ + sizeof(Guid) /* key id */) + { + // payload must contain at least the magic header and key id + throw Error.ProtectionProvider_BadMagicHeader(); + } + + // Need to check that protectedData := { magicHeader || keyId || encryptorSpecificProtectedPayload } + + // Parse the payload version number and key id. + uint magicHeaderFromPayload; + Guid keyIdFromPayload; + fixed (byte* pbInput = protectedData) + { + magicHeaderFromPayload = ReadBigEndian32BitInteger(pbInput); + keyIdFromPayload = Read32bitAlignedGuid(&pbInput[sizeof(uint)]); + } + + // Are the magic header and version information correct? + int payloadVersion; + if (!TryGetVersionFromMagicHeader(magicHeaderFromPayload, out payloadVersion)) + { + throw Error.ProtectionProvider_BadMagicHeader(); + } + else if (payloadVersion != 0) + { + throw Error.ProtectionProvider_BadVersion(); + } + + if (_logger.IsDebugLevelEnabled()) + { + _logger.PerformingUnprotectOperationToKeyWithPurposes(keyIdFromPayload, JoinPurposesForLog(Purposes)); + } + + // Find the correct encryptor in the keyring. + bool keyWasRevoked; + var currentKeyRing = _keyRingProvider.GetCurrentKeyRing(); + var requestedEncryptor = currentKeyRing.GetAuthenticatedEncryptorByKeyId(keyIdFromPayload, out keyWasRevoked); + if (requestedEncryptor == null) + { + _logger.KeyWasNotFoundInTheKeyRingUnprotectOperationCannotProceed(keyIdFromPayload); + throw Error.Common_KeyNotFound(keyIdFromPayload); + } + + // Do we need to notify the caller that he should reprotect the data? + status = UnprotectStatus.Ok; + if (keyIdFromPayload != currentKeyRing.DefaultKeyId) + { + status = UnprotectStatus.DefaultEncryptionKeyChanged; + } + + // Do we need to notify the caller that this key was revoked? + if (keyWasRevoked) + { + if (allowOperationsOnRevokedKeys) + { + _logger.KeyWasRevokedCallerRequestedUnprotectOperationProceedRegardless(keyIdFromPayload); + status = UnprotectStatus.DecryptionKeyWasRevoked; + } + else + { + _logger.KeyWasRevokedUnprotectOperationCannotProceed(keyIdFromPayload); + throw Error.Common_KeyRevoked(keyIdFromPayload); + } + } + + // Perform the decryption operation. + ArraySegment ciphertext = new ArraySegment(protectedData, sizeof(uint) + sizeof(Guid), protectedData.Length - (sizeof(uint) + sizeof(Guid))); // chop off magic header + encryptor id + ArraySegment additionalAuthenticatedData = new ArraySegment(_aadTemplate.GetAadForKey(keyIdFromPayload, isProtecting: false)); + + // At this point, cipherText := { encryptorSpecificPayload }, + // so all that's left is to invoke the decryption routine directly. + return requestedEncryptor.Decrypt(ciphertext, additionalAuthenticatedData) + ?? CryptoUtil.Fail("IAuthenticatedEncryptor.Decrypt returned null."); + } + catch (Exception ex) when (ex.RequiresHomogenization()) + { + // homogenize all failures to CryptographicException + throw Error.DecryptionFailed(ex); + } + } + + // Helper function to write a GUID to a 32-bit alignment; useful on ARM where unaligned reads + // can result in weird behaviors at runtime. + private static void Write32bitAlignedGuid(void* ptr, Guid value) + { + Debug.Assert((long)ptr % 4 == 0); + + ((int*)ptr)[0] = ((int*)&value)[0]; + ((int*)ptr)[1] = ((int*)&value)[1]; + ((int*)ptr)[2] = ((int*)&value)[2]; + ((int*)ptr)[3] = ((int*)&value)[3]; + } + + private static void WriteBigEndianInteger(byte* ptr, uint value) + { + ptr[0] = (byte)(value >> 24); + ptr[1] = (byte)(value >> 16); + ptr[2] = (byte)(value >> 8); + ptr[3] = (byte)(value); + } + + private struct AdditionalAuthenticatedDataTemplate + { + private byte[] _aadTemplate; + + public AdditionalAuthenticatedDataTemplate(IEnumerable purposes) + { + const int MEMORYSTREAM_DEFAULT_CAPACITY = 0x100; // matches MemoryStream.EnsureCapacity + var ms = new MemoryStream(MEMORYSTREAM_DEFAULT_CAPACITY); + + // additionalAuthenticatedData := { magicHeader (32-bit) || keyId || purposeCount (32-bit) || (purpose)* } + // purpose := { utf8ByteCount (7-bit encoded) || utf8Text } + + using (var writer = new PurposeBinaryWriter(ms)) + { + writer.WriteBigEndian(MAGIC_HEADER_V0); + Debug.Assert(ms.Position == sizeof(uint)); + var posPurposeCount = writer.Seek(sizeof(Guid), SeekOrigin.Current); // skip over where the key id will be stored; we'll fill it in later + writer.Seek(sizeof(uint), SeekOrigin.Current); // skip over where the purposeCount will be stored; we'll fill it in later + + uint purposeCount = 0; + foreach (string purpose in purposes) + { + Debug.Assert(purpose != null); + writer.Write(purpose); // prepends length as a 7-bit encoded integer + purposeCount++; + } + + // Once we have written all the purposes, go back and fill in 'purposeCount' + writer.Seek(checked((int)posPurposeCount), SeekOrigin.Begin); + writer.WriteBigEndian(purposeCount); + } + + _aadTemplate = ms.ToArray(); + } + + public byte[] GetAadForKey(Guid keyId, bool isProtecting) + { + // Multiple threads might be trying to read and write the _aadTemplate field + // simultaneously. We need to make sure all accesses to it are thread-safe. + var existingTemplate = Volatile.Read(ref _aadTemplate); + Debug.Assert(existingTemplate.Length >= sizeof(uint) /* MAGIC_HEADER */ + sizeof(Guid) /* keyId */); + + // If the template is already initialized to this key id, return it. + // The caller will not mutate it. + fixed (byte* pExistingTemplate = existingTemplate) + { + if (Read32bitAlignedGuid(&pExistingTemplate[sizeof(uint)]) == keyId) + { + return existingTemplate; + } + } + + // Clone since we're about to make modifications. + // If this is an encryption operation, we only ever encrypt to the default key, + // so we should replace the existing template. This could occur after the protector + // has already been created, such as when the underlying key ring has been modified. + byte[] newTemplate = (byte[])existingTemplate.Clone(); + fixed (byte* pNewTemplate = newTemplate) + { + Write32bitAlignedGuid(&pNewTemplate[sizeof(uint)], keyId); + if (isProtecting) + { + Volatile.Write(ref _aadTemplate, newTemplate); + } + return newTemplate; + } + } + + private sealed class PurposeBinaryWriter : BinaryWriter + { + public PurposeBinaryWriter(MemoryStream stream) : base(stream, EncodingUtil.SecureUtf8Encoding, leaveOpen: true) { } + + // Writes a big-endian 32-bit integer to the underlying stream. + public void WriteBigEndian(uint value) + { + var outStream = BaseStream; // property accessor also performs a flush + outStream.WriteByte((byte)(value >> 24)); + outStream.WriteByte((byte)(value >> 16)); + outStream.WriteByte((byte)(value >> 8)); + outStream.WriteByte((byte)(value)); + } + } + } + + private enum UnprotectStatus + { + Ok, + DefaultEncryptionKeyChanged, + DecryptionKeyWasRevoked + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingProvider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingProvider.cs new file mode 100644 index 0000000000..e407ae62dd --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingProvider.cs @@ -0,0 +1,257 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + internal sealed class KeyRingProvider : ICacheableKeyRingProvider, IKeyRingProvider + { + private CacheableKeyRing _cacheableKeyRing; + private readonly object _cacheableKeyRingLockObj = new object(); + private readonly IDefaultKeyResolver _defaultKeyResolver; + private readonly KeyManagementOptions _keyManagementOptions; + private readonly IKeyManager _keyManager; + private readonly ILogger _logger; + + public KeyRingProvider( + IKeyManager keyManager, + IOptions keyManagementOptions, + IDefaultKeyResolver defaultKeyResolver) + : this( + keyManager, + keyManagementOptions, + defaultKeyResolver, + NullLoggerFactory.Instance) + { + } + + public KeyRingProvider( + IKeyManager keyManager, + IOptions keyManagementOptions, + IDefaultKeyResolver defaultKeyResolver, + ILoggerFactory loggerFactory) + { + _keyManagementOptions = new KeyManagementOptions(keyManagementOptions.Value); // clone so new instance is immutable + _keyManager = keyManager; + CacheableKeyRingProvider = this; + _defaultKeyResolver = defaultKeyResolver; + _logger = loggerFactory.CreateLogger(); + } + + // for testing + internal ICacheableKeyRingProvider CacheableKeyRingProvider { get; set; } + + private CacheableKeyRing CreateCacheableKeyRingCore(DateTimeOffset now, IKey keyJustAdded) + { + // Refresh the list of all keys + var cacheExpirationToken = _keyManager.GetCacheExpirationToken(); + var allKeys = _keyManager.GetAllKeys(); + + // Fetch the current default key from the list of all keys + var defaultKeyPolicy = _defaultKeyResolver.ResolveDefaultKeyPolicy(now, allKeys); + if (!defaultKeyPolicy.ShouldGenerateNewKey) + { + CryptoUtil.Assert(defaultKeyPolicy.DefaultKey != null, "Expected to see a default key."); + return CreateCacheableKeyRingCoreStep2(now, cacheExpirationToken, defaultKeyPolicy.DefaultKey, allKeys); + } + + _logger.PolicyResolutionStatesThatANewKeyShouldBeAddedToTheKeyRing(); + + // We shouldn't call CreateKey more than once, else we risk stack diving. This code path shouldn't + // get hit unless there was an ineligible key with an activation date slightly later than the one we + // just added. If this does happen, then we'll just use whatever key we can instead of creating + // new keys endlessly, eventually falling back to the one we just added if all else fails. + if (keyJustAdded != null) + { + var keyToUse = defaultKeyPolicy.DefaultKey ?? defaultKeyPolicy.FallbackKey ?? keyJustAdded; + return CreateCacheableKeyRingCoreStep2(now, cacheExpirationToken, keyToUse, allKeys); + } + + // At this point, we know we need to generate a new key. + + // We have been asked to generate a new key, but auto-generation of keys has been disabled. + // We need to use the fallback key or fail. + if (!_keyManagementOptions.AutoGenerateKeys) + { + var keyToUse = defaultKeyPolicy.DefaultKey ?? defaultKeyPolicy.FallbackKey; + if (keyToUse == null) + { + _logger.KeyRingDoesNotContainValidDefaultKey(); + throw new InvalidOperationException(Resources.KeyRingProvider_NoDefaultKey_AutoGenerateDisabled); + } + else + { + _logger.UsingFallbackKeyWithExpirationAsDefaultKey(keyToUse.KeyId, keyToUse.ExpirationDate); + return CreateCacheableKeyRingCoreStep2(now, cacheExpirationToken, keyToUse, allKeys); + } + } + + if (defaultKeyPolicy.DefaultKey == null) + { + // The case where there's no default key is the easiest scenario, since it + // means that we need to create a new key with immediate activation. + var newKey = _keyManager.CreateNewKey(activationDate: now, expirationDate: now + _keyManagementOptions.NewKeyLifetime); + return CreateCacheableKeyRingCore(now, keyJustAdded: newKey); // recursively call + } + else + { + // If there is a default key, then the new key we generate should become active upon + // expiration of the default key. The new key lifetime is measured from the creation + // date (now), not the activation date. + var newKey = _keyManager.CreateNewKey(activationDate: defaultKeyPolicy.DefaultKey.ExpirationDate, expirationDate: now + _keyManagementOptions.NewKeyLifetime); + return CreateCacheableKeyRingCore(now, keyJustAdded: newKey); // recursively call + } + } + + private CacheableKeyRing CreateCacheableKeyRingCoreStep2(DateTimeOffset now, CancellationToken cacheExpirationToken, IKey defaultKey, IEnumerable allKeys) + { + Debug.Assert(defaultKey != null); + + // Invariant: our caller ensures that CreateEncryptorInstance succeeded at least once + Debug.Assert(defaultKey.CreateEncryptor() != null); + + _logger.UsingKeyAsDefaultKey(defaultKey.KeyId); + + var nextAutoRefreshTime = now + GetRefreshPeriodWithJitter(_keyManagementOptions.KeyRingRefreshPeriod); + + // The cached keyring should expire at the earliest of (default key expiration, next auto-refresh time). + // Since the refresh period and safety window are not user-settable, we can guarantee that there's at + // least one auto-refresh between the start of the safety window and the key's expiration date. + // This gives us an opportunity to update the key ring before expiration, and it prevents multiple + // servers in a cluster from trying to update the key ring simultaneously. Special case: if the default + // key's expiration date is in the past, then we know we're using a fallback key and should disregard + // its expiration date in favor of the next auto-refresh time. + return new CacheableKeyRing( + expirationToken: cacheExpirationToken, + expirationTime: (defaultKey.ExpirationDate <= now) ? nextAutoRefreshTime : Min(defaultKey.ExpirationDate, nextAutoRefreshTime), + defaultKey: defaultKey, + allKeys: allKeys); + } + + public IKeyRing GetCurrentKeyRing() + { + return GetCurrentKeyRingCore(DateTime.UtcNow); + } + + internal IKeyRing GetCurrentKeyRingCore(DateTime utcNow) + { + Debug.Assert(utcNow.Kind == DateTimeKind.Utc); + + // Can we return the cached keyring to the caller? + var existingCacheableKeyRing = Volatile.Read(ref _cacheableKeyRing); + if (CacheableKeyRing.IsValid(existingCacheableKeyRing, utcNow)) + { + return existingCacheableKeyRing.KeyRing; + } + + // The cached keyring hasn't been created or must be refreshed. We'll allow one thread to + // update the keyring, and all other threads will continue to use the existing cached + // keyring while the first thread performs the update. There is an exception: if there + // is no usable existing cached keyring, all callers must block until the keyring exists. + var acquiredLock = false; + try + { + Monitor.TryEnter(_cacheableKeyRingLockObj, (existingCacheableKeyRing != null) ? 0 : Timeout.Infinite, ref acquiredLock); + if (acquiredLock) + { + // This thread acquired the critical section and is responsible for updating the + // cached keyring. But first, let's make sure that somebody didn't sneak in before + // us and update the keyring on our behalf. + existingCacheableKeyRing = Volatile.Read(ref _cacheableKeyRing); + if (CacheableKeyRing.IsValid(existingCacheableKeyRing, utcNow)) + { + return existingCacheableKeyRing.KeyRing; + } + + if (existingCacheableKeyRing != null) + { + _logger.ExistingCachedKeyRingIsExpired(); + } + + // It's up to us to refresh the cached keyring. + // This call is performed *under lock*. + CacheableKeyRing newCacheableKeyRing; + + try + { + newCacheableKeyRing = CacheableKeyRingProvider.GetCacheableKeyRing(utcNow); + } + catch (Exception ex) + { + if (existingCacheableKeyRing != null) + { + _logger.ErrorOccurredWhileRefreshingKeyRing(ex); + } + else + { + _logger.ErrorOccurredWhileReadingKeyRing(ex); + } + + // Failures that occur while refreshing the keyring are most likely transient, perhaps due to a + // temporary network outage. Since we don't want every subsequent call to result in failure, we'll + // create a new keyring object whose expiration is now + some short period of time (currently 2 min), + // and after this period has elapsed the next caller will try refreshing. If we don't have an + // existing keyring (perhaps because this is the first call), then there's nothing to extend, so + // each subsequent caller will keep going down this code path until one succeeds. + if (existingCacheableKeyRing != null) + { + Volatile.Write(ref _cacheableKeyRing, existingCacheableKeyRing.WithTemporaryExtendedLifetime(utcNow)); + } + + // The immediate caller should fail so that he can report the error up his chain. This makes it more likely + // that an administrator can see the error and react to it as appropriate. The caller can retry the operation + // and will probably have success as long as he falls within the temporary extension mentioned above. + throw; + } + + Volatile.Write(ref _cacheableKeyRing, newCacheableKeyRing); + return newCacheableKeyRing.KeyRing; + } + else + { + // We didn't acquire the critical section. This should only occur if we passed + // zero for the Monitor.TryEnter timeout, which implies that we had an existing + // (but outdated) keyring that we can use as a fallback. + Debug.Assert(existingCacheableKeyRing != null); + return existingCacheableKeyRing.KeyRing; + } + } + finally + { + if (acquiredLock) + { + Monitor.Exit(_cacheableKeyRingLockObj); + } + } + } + + private static TimeSpan GetRefreshPeriodWithJitter(TimeSpan refreshPeriod) + { + // We'll fudge the refresh period up to -20% so that multiple applications don't try to + // hit a single repository simultaneously. For instance, if the refresh period is 1 hour, + // we'll return a value in the vicinity of 48 - 60 minutes. We use the Random class since + // we don't need a secure PRNG for this. + return TimeSpan.FromTicks((long)(refreshPeriod.Ticks * (1.0d - (new Random().NextDouble() / 5)))); + } + + private static DateTimeOffset Min(DateTimeOffset a, DateTimeOffset b) + { + return (a < b) ? a : b; + } + + CacheableKeyRing ICacheableKeyRingProvider.GetCacheableKeyRing(DateTimeOffset now) + { + // the entry point allows one recursive call + return CreateCacheableKeyRingCore(now, keyJustAdded: null); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/XmlKeyManager.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/XmlKeyManager.cs new file mode 100644 index 0000000000..06baad13ed --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/KeyManagement/XmlKeyManager.cs @@ -0,0 +1,564 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Xml; +using System.Xml.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.AspNetCore.DataProtection.Repositories; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Microsoft.Win32; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + /// + /// A key manager backed by an . + /// + public sealed class XmlKeyManager : IKeyManager, IInternalXmlKeyManager + { + // Used for serializing elements to persistent storage + internal static readonly XName KeyElementName = "key"; + internal static readonly XName IdAttributeName = "id"; + internal static readonly XName VersionAttributeName = "version"; + internal static readonly XName CreationDateElementName = "creationDate"; + internal static readonly XName ActivationDateElementName = "activationDate"; + internal static readonly XName ExpirationDateElementName = "expirationDate"; + internal static readonly XName DescriptorElementName = "descriptor"; + internal static readonly XName DeserializerTypeAttributeName = "deserializerType"; + internal static readonly XName RevocationElementName = "revocation"; + internal static readonly XName RevocationDateElementName = "revocationDate"; + internal static readonly XName ReasonElementName = "reason"; + + private const string RevokeAllKeysValue = "*"; + + private readonly IActivator _activator; + private readonly AlgorithmConfiguration _authenticatedEncryptorConfiguration; + private readonly IKeyEscrowSink _keyEscrowSink; + private readonly IInternalXmlKeyManager _internalKeyManager; + private readonly ILoggerFactory _loggerFactory; + private readonly ILogger _logger; + private readonly IEnumerable _encryptorFactories; + private readonly IDefaultKeyStorageDirectories _keyStorageDirectories; + + private CancellationTokenSource _cacheExpirationTokenSource; + + /// + /// Creates an . + /// + /// The instance that provides the configuration. + /// The . + public XmlKeyManager(IOptions keyManagementOptions, IActivator activator) + : this(keyManagementOptions, activator, NullLoggerFactory.Instance) + { } + + /// + /// Creates an . + /// + /// The instance that provides the configuration. + /// The . + /// The . + public XmlKeyManager(IOptions keyManagementOptions, IActivator activator, ILoggerFactory loggerFactory) + : this(keyManagementOptions, activator, loggerFactory, DefaultKeyStorageDirectories.Instance) + { } + + internal XmlKeyManager( + IOptions keyManagementOptions, + IActivator activator, + ILoggerFactory loggerFactory, + IDefaultKeyStorageDirectories keyStorageDirectories) + { + _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); + _logger = _loggerFactory.CreateLogger(); + _keyStorageDirectories = keyStorageDirectories ?? throw new ArgumentNullException(nameof(keyStorageDirectories)); + + KeyRepository = keyManagementOptions.Value.XmlRepository; + KeyEncryptor = keyManagementOptions.Value.XmlEncryptor; + if (KeyRepository == null) + { + if (KeyEncryptor != null) + { + throw new InvalidOperationException( + Resources.FormatXmlKeyManager_IXmlRepositoryNotFound(nameof(IXmlRepository), nameof(IXmlEncryptor))); + } + else + { + var keyRepositoryEncryptorPair = GetFallbackKeyRepositoryEncryptorPair(); + KeyRepository = keyRepositoryEncryptorPair.Key; + KeyEncryptor = keyRepositoryEncryptorPair.Value; + } + } + + _authenticatedEncryptorConfiguration = keyManagementOptions.Value.AuthenticatedEncryptorConfiguration; + + var escrowSinks = keyManagementOptions.Value.KeyEscrowSinks; + _keyEscrowSink = escrowSinks.Count > 0 ? new AggregateKeyEscrowSink(escrowSinks) : null; + _activator = activator; + TriggerAndResetCacheExpirationToken(suppressLogging: true); + _internalKeyManager = _internalKeyManager ?? this; + _encryptorFactories = keyManagementOptions.Value.AuthenticatedEncryptorFactories; + } + + // Internal for testing. + internal XmlKeyManager( + IOptions keyManagementOptions, + IActivator activator, + ILoggerFactory loggerFactory, + IInternalXmlKeyManager internalXmlKeyManager) + : this(keyManagementOptions, activator, loggerFactory) + { + _internalKeyManager = internalXmlKeyManager; + } + + internal IXmlEncryptor KeyEncryptor { get; } + + internal IXmlRepository KeyRepository { get; } + + public IKey CreateNewKey(DateTimeOffset activationDate, DateTimeOffset expirationDate) + { + return _internalKeyManager.CreateNewKey( + keyId: Guid.NewGuid(), + creationDate: DateTimeOffset.UtcNow, + activationDate: activationDate, + expirationDate: expirationDate); + } + + private static string DateTimeOffsetToFilenameSafeString(DateTimeOffset dateTime) + { + // similar to the XML format for dates, but with punctuation stripped + return dateTime.UtcDateTime.ToString("yyyyMMddTHHmmssFFFFFFFZ"); + } + + public IReadOnlyCollection GetAllKeys() + { + var allElements = KeyRepository.GetAllElements(); + + // We aggregate all the information we read into three buckets + Dictionary keyIdToKeyMap = new Dictionary(); + HashSet revokedKeyIds = null; + DateTimeOffset? mostRecentMassRevocationDate = null; + + foreach (var element in allElements) + { + if (element.Name == KeyElementName) + { + // ProcessKeyElement can return null in the case of failure, and if this happens we'll move on. + // Still need to throw if we see duplicate keys with the same id. + var key = ProcessKeyElement(element); + if (key != null) + { + if (keyIdToKeyMap.ContainsKey(key.KeyId)) + { + throw Error.XmlKeyManager_DuplicateKey(key.KeyId); + } + keyIdToKeyMap[key.KeyId] = key; + } + } + else if (element.Name == RevocationElementName) + { + var revocationInfo = ProcessRevocationElement(element); + if (revocationInfo is Guid) + { + // a single key was revoked + if (revokedKeyIds == null) + { + revokedKeyIds = new HashSet(); + } + revokedKeyIds.Add((Guid)revocationInfo); + } + else + { + // all keys as of a certain date were revoked + DateTimeOffset thisMassRevocationDate = (DateTimeOffset)revocationInfo; + if (!mostRecentMassRevocationDate.HasValue || mostRecentMassRevocationDate < thisMassRevocationDate) + { + mostRecentMassRevocationDate = thisMassRevocationDate; + } + } + } + else + { + // Skip unknown elements. + _logger.UnknownElementWithNameFoundInKeyringSkipping(element.Name); + } + } + + // Apply individual revocations + if (revokedKeyIds != null) + { + foreach (Guid revokedKeyId in revokedKeyIds) + { + KeyBase key; + keyIdToKeyMap.TryGetValue(revokedKeyId, out key); + if (key != null) + { + key.SetRevoked(); + _logger.MarkedKeyAsRevokedInTheKeyring(revokedKeyId); + } + else + { + _logger.TriedToProcessRevocationOfKeyButNoSuchKeyWasFound(revokedKeyId); + } + } + } + + // Apply mass revocations + if (mostRecentMassRevocationDate.HasValue) + { + foreach (var key in keyIdToKeyMap.Values) + { + // The contract of IKeyManager.RevokeAllKeys is that keys created *strictly before* the + // revocation date are revoked. The system clock isn't very granular, and if this were + // a less-than-or-equal check we could end up with the weird case where a revocation + // immediately followed by a key creation results in a newly-created revoked key (since + // the clock hasn't yet stepped). + if (key.CreationDate < mostRecentMassRevocationDate) + { + key.SetRevoked(); + _logger.MarkedKeyAsRevokedInTheKeyring(key.KeyId); + } + } + } + + // And we're finished! + return keyIdToKeyMap.Values.ToList().AsReadOnly(); + } + + public CancellationToken GetCacheExpirationToken() + { + return Interlocked.CompareExchange(ref _cacheExpirationTokenSource, null, null).Token; + } + + private KeyBase ProcessKeyElement(XElement keyElement) + { + Debug.Assert(keyElement.Name == KeyElementName); + + try + { + // Read metadata and prepare the key for deferred instantiation + Guid keyId = (Guid)keyElement.Attribute(IdAttributeName); + DateTimeOffset creationDate = (DateTimeOffset)keyElement.Element(CreationDateElementName); + DateTimeOffset activationDate = (DateTimeOffset)keyElement.Element(ActivationDateElementName); + DateTimeOffset expirationDate = (DateTimeOffset)keyElement.Element(ExpirationDateElementName); + + _logger.FoundKey(keyId); + + return new DeferredKey( + keyId: keyId, + creationDate: creationDate, + activationDate: activationDate, + expirationDate: expirationDate, + keyManager: this, + keyElement: keyElement, + encryptorFactories: _encryptorFactories); + } + catch (Exception ex) + { + WriteKeyDeserializationErrorToLog(ex, keyElement); + + // Don't include this key in the key ring + return null; + } + } + + // returns a Guid (for specific keys) or a DateTimeOffset (for all keys created on or before a specific date) + private object ProcessRevocationElement(XElement revocationElement) + { + Debug.Assert(revocationElement.Name == RevocationElementName); + + try + { + string keyIdAsString = (string)revocationElement.Element(KeyElementName).Attribute(IdAttributeName); + if (keyIdAsString == RevokeAllKeysValue) + { + // this is a mass revocation of all keys as of the specified revocation date + DateTimeOffset massRevocationDate = (DateTimeOffset)revocationElement.Element(RevocationDateElementName); + _logger.FoundRevocationOfAllKeysCreatedPriorTo(massRevocationDate); + return massRevocationDate; + } + else + { + // only one key is being revoked + var keyId = XmlConvert.ToGuid(keyIdAsString); + _logger.FoundRevocationOfKey(keyId); + return keyId; + } + } + catch (Exception ex) + { + // Any exceptions that occur are fatal - we don't want to continue if we cannot process + // revocation information. + _logger.ExceptionWhileProcessingRevocationElement(revocationElement, ex); + throw; + } + } + + public void RevokeAllKeys(DateTimeOffset revocationDate, string reason = null) + { + // + // ... + // + // + // ... + // + + _logger.RevokingAllKeysAsOfForReason(revocationDate, reason); + + var revocationElement = new XElement(RevocationElementName, + new XAttribute(VersionAttributeName, 1), + new XElement(RevocationDateElementName, revocationDate), + new XComment(" All keys created before the revocation date are revoked. "), + new XElement(KeyElementName, + new XAttribute(IdAttributeName, RevokeAllKeysValue)), + new XElement(ReasonElementName, reason)); + + // Persist it to the underlying repository and trigger the cancellation token + string friendlyName = "revocation-" + DateTimeOffsetToFilenameSafeString(revocationDate); + KeyRepository.StoreElement(revocationElement, friendlyName); + TriggerAndResetCacheExpirationToken(); + } + + public void RevokeKey(Guid keyId, string reason = null) + { + _internalKeyManager.RevokeSingleKey( + keyId: keyId, + revocationDate: DateTimeOffset.UtcNow, + reason: reason); + } + + private void TriggerAndResetCacheExpirationToken([CallerMemberName] string opName = null, bool suppressLogging = false) + { + if (!suppressLogging) + { + _logger.KeyCacheExpirationTokenTriggeredByOperation(opName); + } + + Interlocked.Exchange(ref _cacheExpirationTokenSource, new CancellationTokenSource())?.Cancel(); + } + + private void WriteKeyDeserializationErrorToLog(Exception error, XElement keyElement) + { + // Ideally we'd suppress the error since it might contain sensitive information, but it would be too difficult for + // an administrator to diagnose the issue if we hide this information. Instead we'll log the error to the error + // log and the raw element to the debug log. This works for our out-of-box XML decryptors since they don't + // include sensitive information in the exception message. + + // write sanitized element + _logger.ExceptionWhileProcessingKeyElement(keyElement.WithoutChildNodes(), error); + + // write full element + _logger.AnExceptionOccurredWhileProcessingElementDebug(keyElement, error); + + } + + IKey IInternalXmlKeyManager.CreateNewKey(Guid keyId, DateTimeOffset creationDate, DateTimeOffset activationDate, DateTimeOffset expirationDate) + { + // + // ... + // ... + // ... + // + // ... + // + // + + _logger.CreatingKey(keyId, creationDate, activationDate, expirationDate); + + var newDescriptor = _authenticatedEncryptorConfiguration.CreateNewDescriptor() + ?? CryptoUtil.Fail("CreateNewDescriptor returned null."); + var descriptorXmlInfo = newDescriptor.ExportToXml(); + + _logger.DescriptorDeserializerTypeForKeyIs(keyId, descriptorXmlInfo.DeserializerType.AssemblyQualifiedName); + + // build the element + var keyElement = new XElement(KeyElementName, + new XAttribute(IdAttributeName, keyId), + new XAttribute(VersionAttributeName, 1), + new XElement(CreationDateElementName, creationDate), + new XElement(ActivationDateElementName, activationDate), + new XElement(ExpirationDateElementName, expirationDate), + new XElement(DescriptorElementName, + new XAttribute(DeserializerTypeAttributeName, descriptorXmlInfo.DeserializerType.AssemblyQualifiedName), + descriptorXmlInfo.SerializedDescriptorElement)); + + // If key escrow policy is in effect, write the *unencrypted* key now. + if (_keyEscrowSink != null) + { + _logger.KeyEscrowSinkFoundWritingKeyToEscrow(keyId); + } + else + { + _logger.NoKeyEscrowSinkFoundNotWritingKeyToEscrow(keyId); + } + _keyEscrowSink?.Store(keyId, keyElement); + + // If an XML encryptor has been configured, protect secret key material now. + if (KeyEncryptor == null) + { + _logger.NoXMLEncryptorConfiguredKeyMayBePersistedToStorageInUnencryptedForm(keyId); + } + var possiblyEncryptedKeyElement = KeyEncryptor?.EncryptIfNecessary(keyElement) ?? keyElement; + + // Persist it to the underlying repository and trigger the cancellation token. + var friendlyName = string.Format(CultureInfo.InvariantCulture, "key-{0:D}", keyId); + KeyRepository.StoreElement(possiblyEncryptedKeyElement, friendlyName); + TriggerAndResetCacheExpirationToken(); + + // And we're done! + return new Key( + keyId: keyId, + creationDate: creationDate, + activationDate: activationDate, + expirationDate: expirationDate, + descriptor: newDescriptor, + encryptorFactories: _encryptorFactories); + } + + IAuthenticatedEncryptorDescriptor IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement) + { + try + { + // Figure out who will be deserializing this + var descriptorElement = keyElement.Element(DescriptorElementName); + string descriptorDeserializerTypeName = (string)descriptorElement.Attribute(DeserializerTypeAttributeName); + + // Decrypt the descriptor element and pass it to the descriptor for consumption + var unencryptedInputToDeserializer = descriptorElement.Elements().Single().DecryptElement(_activator); + var deserializerInstance = _activator.CreateInstance(descriptorDeserializerTypeName); + var descriptorInstance = deserializerInstance.ImportFromXml(unencryptedInputToDeserializer); + + return descriptorInstance ?? CryptoUtil.Fail("ImportFromXml returned null."); + } + catch (Exception ex) + { + WriteKeyDeserializationErrorToLog(ex, keyElement); + throw; + } + } + + void IInternalXmlKeyManager.RevokeSingleKey(Guid keyId, DateTimeOffset revocationDate, string reason) + { + // + // ... + // + // ... + // + + _logger.RevokingKeyForReason(keyId, revocationDate, reason); + + var revocationElement = new XElement(RevocationElementName, + new XAttribute(VersionAttributeName, 1), + new XElement(RevocationDateElementName, revocationDate), + new XElement(KeyElementName, + new XAttribute(IdAttributeName, keyId)), + new XElement(ReasonElementName, reason)); + + // Persist it to the underlying repository and trigger the cancellation token + var friendlyName = string.Format(CultureInfo.InvariantCulture, "revocation-{0:D}", keyId); + KeyRepository.StoreElement(revocationElement, friendlyName); + TriggerAndResetCacheExpirationToken(); + } + + internal KeyValuePair GetFallbackKeyRepositoryEncryptorPair() + { + IXmlRepository repository = null; + IXmlEncryptor encryptor = null; + + // If we're running in Azure Web Sites, the key repository goes in the %HOME% directory. + var azureWebSitesKeysFolder = _keyStorageDirectories.GetKeyStorageDirectoryForAzureWebSites(); + if (azureWebSitesKeysFolder != null) + { + _logger.UsingAzureAsKeyRepository(azureWebSitesKeysFolder.FullName); + + // Cloud DPAPI isn't yet available, so we don't encrypt keys at rest. + // This isn't all that different than what Azure Web Sites does today, and we can always add this later. + repository = new FileSystemXmlRepository(azureWebSitesKeysFolder, _loggerFactory); + } + else + { + // If the user profile is available, store keys in the user profile directory. + var localAppDataKeysFolder = _keyStorageDirectories.GetKeyStorageDirectory(); + if (localAppDataKeysFolder != null) + { + if (OSVersionUtil.IsWindows()) + { + // If the user profile is available, we can protect using DPAPI. + // Probe to see if protecting to local user is available, and use it as the default if so. + encryptor = new DpapiXmlEncryptor( + protectToLocalMachine: !DpapiSecretSerializerHelper.CanProtectToCurrentUserAccount(), + loggerFactory: _loggerFactory); + } + repository = new FileSystemXmlRepository(localAppDataKeysFolder, _loggerFactory); + + if (encryptor != null) + { + _logger.UsingProfileAsKeyRepositoryWithDPAPI(localAppDataKeysFolder.FullName); + } + else + { + _logger.UsingProfileAsKeyRepository(localAppDataKeysFolder.FullName); + } + } + else + { + // Use profile isn't available - can we use the HKLM registry? + RegistryKey regKeyStorageKey = null; + if (OSVersionUtil.IsWindows()) + { + regKeyStorageKey = RegistryXmlRepository.DefaultRegistryKey; + } + if (regKeyStorageKey != null) + { + // If the user profile isn't available, we can protect using DPAPI (to machine). + encryptor = new DpapiXmlEncryptor(protectToLocalMachine: true, loggerFactory: _loggerFactory); + repository = new RegistryXmlRepository(regKeyStorageKey, _loggerFactory); + + _logger.UsingRegistryAsKeyRepositoryWithDPAPI(regKeyStorageKey.Name); + } + else + { + // Final fallback - use an ephemeral repository since we don't know where else to go. + // This can only be used for development scenarios. + repository = new EphemeralXmlRepository(_loggerFactory); + + _logger.UsingEphemeralKeyRepository(); + } + } + } + + return new KeyValuePair(repository, encryptor); + } + + private sealed class AggregateKeyEscrowSink : IKeyEscrowSink + { + private readonly IList _sinks; + + public AggregateKeyEscrowSink(IList sinks) + { + _sinks = sinks; + } + + public void Store(Guid keyId, XElement element) + { + foreach (var sink in _sinks) + { + sink.Store(keyId, element); + } + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/LoggingExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/LoggingExtensions.cs new file mode 100644 index 0000000000..7792d48dbe --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/LoggingExtensions.cs @@ -0,0 +1,804 @@ +// 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.Runtime.CompilerServices; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Win32; + +namespace Microsoft.Extensions.Logging +{ + /// + /// Helpful extension methods on . + /// + internal static class LoggingExtensions + { + private static Action _usingFallbackKeyWithExpirationAsDefaultKey; + + private static Action _usingKeyAsDefaultKey; + + private static Action _openingCNGAlgorithmFromProviderWithHMAC; + + private static Action _openingCNGAlgorithmFromProviderWithChainingModeCBC; + + private static Action _performingUnprotectOperationToKeyWithPurposes; + + private static Action _keyWasNotFoundInTheKeyRingUnprotectOperationCannotProceed; + + private static Action _keyWasRevokedCallerRequestedUnprotectOperationProceedRegardless; + + private static Action _keyWasRevokedUnprotectOperationCannotProceed; + + private static Action _openingCNGAlgorithmFromProviderWithChainingModeGCM; + + private static Action _usingManagedKeyedHashAlgorithm; + + private static Action _usingManagedSymmetricAlgorithm; + + private static Action _keyIsIneligibleToBeTheDefaultKeyBecauseItsMethodFailed; + + private static Action _consideringKeyWithExpirationDateAsDefaultKey; + + private static Action _keyIsNoLongerUnderConsiderationAsDefault; + + private static Action _unknownElementWithNameFoundInKeyringSkipping; + + private static Action _markedKeyAsRevokedInTheKeyring; + + private static Action _triedToProcessRevocationOfKeyButNoSuchKeyWasFound; + + private static Action _foundKey; + + private static Action _foundRevocationOfAllKeysCreatedPriorTo; + + private static Action _foundRevocationOfKey; + + private static Action _exceptionWhileProcessingRevocationElement; + + private static Action _revokingAllKeysAsOfForReason; + + private static Action _keyCacheExpirationTokenTriggeredByOperation; + + private static Action _anExceptionOccurredWhileProcessingTheKeyElement; + + private static Action _anExceptionOccurredWhileProcessingTheKeyElementDebug; + + private static Action _encryptingToWindowsDPAPIForCurrentUserAccount; + + private static Action _encryptingToWindowsDPAPINGUsingProtectionDescriptorRule; + + private static Action _anErrorOccurredWhileEncryptingToX509CertificateWithThumbprint; + + private static Action _encryptingToX509CertificateWithThumbprint; + + private static Action _exceptionOccurredWhileTryingToResolveCertificateWithThumbprint; + + private static Action _performingProtectOperationToKeyWithPurposes; + + private static Action _creatingKey; + + private static Action _descriptorDeserializerTypeForKeyIs; + + private static Action _keyEscrowSinkFoundWritingKeyToEscrow; + + private static Action _noKeyEscrowSinkFoundNotWritingKeyToEscrow; + + private static Action _noXMLEncryptorConfiguredKeyMayBePersistedToStorageInUnencryptedForm; + + private static Action _revokingKeyForReason; + + private static Action _readingDataFromFile; + + private static Action _nameIsNotSafeFileName; + + private static Action _writingDataToFile; + + private static Action _readingDataFromRegistryKeyValue; + + private static Action _nameIsNotSafeRegistryValueName; + + private static Action _decryptingSecretElementUsingWindowsDPAPING; + + private static Action _exceptionOccurredTryingToDecryptElement; + + private static Action _encryptingUsingNullEncryptor; + + private static Action _usingEphemeralDataProtectionProvider; + + private static Action _existingCachedKeyRingIsExpiredRefreshing; + + private static Action _errorOccurredWhileRefreshingKeyRing; + + private static Action _errorOccurredWhileReadingKeyRing; + + private static Action _keyRingDoesNotContainValidDefaultKey; + + private static Action _usingInmemoryRepository; + + private static Action _decryptingSecretElementUsingWindowsDPAPI; + + private static Action _defaultKeyExpirationImminentAndRepository; + + private static Action _repositoryContainsNoViableDefaultKey; + + private static Action _errorOccurredWhileEncryptingToWindowsDPAPI; + + private static Action _encryptingToWindowsDPAPIForLocalMachineAccount; + + private static Action _errorOccurredWhileEncryptingToWindowsDPAPING; + + private static Action _policyResolutionStatesThatANewKeyShouldBeAddedToTheKeyRing; + + private static Action _keyRingWasLoadedOnStartup; + + private static Action _keyRingFailedToLoadOnStartup; + + private static Action _usingEphemeralKeyRepository; + + private static Action _usingRegistryAsKeyRepositoryWithDPAPI; + + private static Action _usingProfileAsKeyRepository; + + private static Action _usingProfileAsKeyRepositoryWithDPAPI; + + private static Action _usingAzureAsKeyRepository; + + private static Action _usingEphemeralFileSystemLocationInContainer; + + static LoggingExtensions() + { + _usingFallbackKeyWithExpirationAsDefaultKey = LoggerMessage.Define( + eventId: 1, + logLevel: LogLevel.Warning, + formatString: "Policy resolution states that a new key should be added to the key ring, but automatic generation of keys is disabled. Using fallback key {KeyId:B} with expiration {ExpirationDate:u} as default key."); + _usingKeyAsDefaultKey = LoggerMessage.Define( + eventId: 2, + logLevel: LogLevel.Debug, + formatString: "Using key {KeyId:B} as the default key."); + _openingCNGAlgorithmFromProviderWithHMAC = LoggerMessage.Define( + eventId: 3, + logLevel: LogLevel.Debug, + formatString: "Opening CNG algorithm '{HashAlgorithm}' from provider '{HashAlgorithmProvider}' with HMAC."); + _openingCNGAlgorithmFromProviderWithChainingModeCBC = LoggerMessage.Define( + eventId: 4, + logLevel: LogLevel.Debug, + formatString: "Opening CNG algorithm '{EncryptionAlgorithm}' from provider '{EncryptionAlgorithmProvider}' with chaining mode CBC."); + _performingUnprotectOperationToKeyWithPurposes = LoggerMessage.Define( + eventId: 5, + logLevel: LogLevel.Trace, + formatString: "Performing unprotect operation to key {KeyId:B} with purposes {Purposes}."); + _keyWasNotFoundInTheKeyRingUnprotectOperationCannotProceed = LoggerMessage.Define( + eventId: 6, + logLevel: LogLevel.Trace, + formatString: "Key {KeyId:B} was not found in the key ring. Unprotect operation cannot proceed."); + _keyWasRevokedCallerRequestedUnprotectOperationProceedRegardless = LoggerMessage.Define( + eventId: 7, + logLevel: LogLevel.Debug, + formatString: "Key {KeyId:B} was revoked. Caller requested unprotect operation proceed regardless."); + _keyWasRevokedUnprotectOperationCannotProceed = LoggerMessage.Define( + eventId: 8, + logLevel: LogLevel.Debug, + formatString: "Key {KeyId:B} was revoked. Unprotect operation cannot proceed."); + _openingCNGAlgorithmFromProviderWithChainingModeGCM = LoggerMessage.Define( + eventId: 9, + logLevel: LogLevel.Debug, + formatString: "Opening CNG algorithm '{EncryptionAlgorithm}' from provider '{EncryptionAlgorithmProvider}' with chaining mode GCM."); + _usingManagedKeyedHashAlgorithm = LoggerMessage.Define( + eventId: 10, + logLevel: LogLevel.Debug, + formatString: "Using managed keyed hash algorithm '{FullName}'."); + _usingManagedSymmetricAlgorithm = LoggerMessage.Define( + eventId: 11, + logLevel: LogLevel.Debug, + formatString: "Using managed symmetric algorithm '{FullName}'."); + _keyIsIneligibleToBeTheDefaultKeyBecauseItsMethodFailed = LoggerMessage.Define( + eventId: 12, + logLevel: LogLevel.Warning, + formatString: "Key {KeyId:B} is ineligible to be the default key because its {MethodName} method failed."); + _consideringKeyWithExpirationDateAsDefaultKey = LoggerMessage.Define( + eventId: 13, + logLevel: LogLevel.Debug, + formatString: "Considering key {KeyId:B} with expiration date {ExpirationDate:u} as default key."); + _keyIsNoLongerUnderConsiderationAsDefault = LoggerMessage.Define( + eventId: 14, + logLevel: LogLevel.Debug, + formatString: "Key {KeyId:B} is no longer under consideration as default key because it is expired, revoked, or cannot be deciphered."); + _unknownElementWithNameFoundInKeyringSkipping = LoggerMessage.Define( + eventId: 15, + logLevel: LogLevel.Warning, + formatString: "Unknown element with name '{Name}' found in keyring, skipping."); + _markedKeyAsRevokedInTheKeyring = LoggerMessage.Define( + eventId: 16, + logLevel: LogLevel.Debug, + formatString: "Marked key {KeyId:B} as revoked in the keyring."); + _triedToProcessRevocationOfKeyButNoSuchKeyWasFound = LoggerMessage.Define( + eventId: 17, + logLevel: LogLevel.Warning, + formatString: "Tried to process revocation of key {KeyId:B}, but no such key was found in keyring. Skipping."); + _foundKey = LoggerMessage.Define( + eventId: 18, + logLevel: LogLevel.Debug, + formatString: "Found key {KeyId:B}."); + _foundRevocationOfAllKeysCreatedPriorTo = LoggerMessage.Define( + eventId: 19, + logLevel: LogLevel.Debug, + formatString: "Found revocation of all keys created prior to {RevocationDate:u}."); + _foundRevocationOfKey = LoggerMessage.Define( + eventId: 20, + logLevel: LogLevel.Debug, + formatString: "Found revocation of key {KeyId:B}."); + _exceptionWhileProcessingRevocationElement = LoggerMessage.Define( + eventId: 21, + logLevel: LogLevel.Error, + formatString: "An exception occurred while processing the revocation element '{RevocationElement}'. Cannot continue keyring processing."); + _revokingAllKeysAsOfForReason = LoggerMessage.Define( + eventId: 22, + logLevel: LogLevel.Information, + formatString: "Revoking all keys as of {RevocationDate:u} for reason '{Reason}'."); + _keyCacheExpirationTokenTriggeredByOperation = LoggerMessage.Define( + eventId: 23, + logLevel: LogLevel.Debug, + formatString: "Key cache expiration token triggered by '{OperationName}' operation."); + _anExceptionOccurredWhileProcessingTheKeyElement = LoggerMessage.Define( + eventId: 24, + logLevel: LogLevel.Error, + formatString: "An exception occurred while processing the key element '{Element}'."); + _anExceptionOccurredWhileProcessingTheKeyElementDebug = LoggerMessage.Define( + eventId: 25, + logLevel: LogLevel.Trace, + formatString: "An exception occurred while processing the key element '{Element}'."); + _encryptingToWindowsDPAPIForCurrentUserAccount = LoggerMessage.Define( + eventId: 26, + logLevel: LogLevel.Debug, + formatString: "Encrypting to Windows DPAPI for current user account ({Name})."); + _encryptingToWindowsDPAPINGUsingProtectionDescriptorRule = LoggerMessage.Define( + eventId: 27, + logLevel: LogLevel.Debug, + formatString: "Encrypting to Windows DPAPI-NG using protection descriptor rule '{DescriptorRule}'."); + _anErrorOccurredWhileEncryptingToX509CertificateWithThumbprint = LoggerMessage.Define( + eventId: 28, + logLevel: LogLevel.Error, + formatString: "An error occurred while encrypting to X.509 certificate with thumbprint '{Thumbprint}'."); + _encryptingToX509CertificateWithThumbprint = LoggerMessage.Define( + eventId: 29, + logLevel: LogLevel.Debug, + formatString: "Encrypting to X.509 certificate with thumbprint '{Thumbprint}'."); + _exceptionOccurredWhileTryingToResolveCertificateWithThumbprint = LoggerMessage.Define( + eventId: 30, + logLevel: LogLevel.Error, + formatString: "An exception occurred while trying to resolve certificate with thumbprint '{Thumbprint}'."); + _performingProtectOperationToKeyWithPurposes = LoggerMessage.Define( + eventId: 31, + logLevel: LogLevel.Trace, + formatString: "Performing protect operation to key {KeyId:B} with purposes {Purposes}."); + _descriptorDeserializerTypeForKeyIs = LoggerMessage.Define( + eventId: 32, + logLevel: LogLevel.Debug, + formatString: "Descriptor deserializer type for key {KeyId:B} is '{AssemblyQualifiedName}'."); + _keyEscrowSinkFoundWritingKeyToEscrow = LoggerMessage.Define( + eventId: 33, + logLevel: LogLevel.Debug, + formatString: "Key escrow sink found. Writing key {KeyId:B} to escrow."); + _noKeyEscrowSinkFoundNotWritingKeyToEscrow = LoggerMessage.Define( + eventId: 34, + logLevel: LogLevel.Debug, + formatString: "No key escrow sink found. Not writing key {KeyId:B} to escrow."); + _noXMLEncryptorConfiguredKeyMayBePersistedToStorageInUnencryptedForm = LoggerMessage.Define( + eventId: 35, + logLevel: LogLevel.Warning, + formatString: "No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form."); + _revokingKeyForReason = LoggerMessage.Define( + eventId: 36, + logLevel: LogLevel.Information, + formatString: "Revoking key {KeyId:B} at {RevocationDate:u} for reason '{Reason}'."); + _readingDataFromFile = LoggerMessage.Define( + eventId: 37, + logLevel: LogLevel.Debug, + formatString: "Reading data from file '{FullPath}'."); + _nameIsNotSafeFileName = LoggerMessage.Define( + eventId: 38, + logLevel: LogLevel.Debug, + formatString: "The name '{FriendlyName}' is not a safe file name, using '{NewFriendlyName}' instead."); + _writingDataToFile = LoggerMessage.Define( + eventId: 39, + logLevel: LogLevel.Information, + formatString: "Writing data to file '{FileName}'."); + _readingDataFromRegistryKeyValue = LoggerMessage.Define( + eventId: 40, + logLevel: LogLevel.Debug, + formatString: "Reading data from registry key '{RegistryKeyName}', value '{Value}'."); + _nameIsNotSafeRegistryValueName = LoggerMessage.Define( + eventId: 41, + logLevel: LogLevel.Debug, + formatString: "The name '{FriendlyName}' is not a safe registry value name, using '{NewFriendlyName}' instead."); + _decryptingSecretElementUsingWindowsDPAPING = LoggerMessage.Define( + eventId: 42, + logLevel: LogLevel.Debug, + formatString: "Decrypting secret element using Windows DPAPI-NG with protection descriptor rule '{DescriptorRule}'."); + _exceptionOccurredTryingToDecryptElement = LoggerMessage.Define( + eventId: 43, + logLevel: LogLevel.Error, + formatString: "An exception occurred while trying to decrypt the element."); + _encryptingUsingNullEncryptor = LoggerMessage.Define( + eventId: 44, + logLevel: LogLevel.Warning, + formatString: "Encrypting using a null encryptor; secret information isn't being protected."); + _usingEphemeralDataProtectionProvider = LoggerMessage.Define( + eventId: 45, + logLevel: LogLevel.Warning, + formatString: "Using ephemeral data protection provider. Payloads will be undecipherable upon application shutdown."); + _existingCachedKeyRingIsExpiredRefreshing = LoggerMessage.Define( + eventId: 46, + logLevel: LogLevel.Debug, + formatString: "Existing cached key ring is expired. Refreshing."); + _errorOccurredWhileRefreshingKeyRing = LoggerMessage.Define( + eventId: 47, + logLevel: LogLevel.Error, + formatString: "An error occurred while refreshing the key ring. Will try again in 2 minutes."); + _errorOccurredWhileReadingKeyRing = LoggerMessage.Define( + eventId: 48, + logLevel: LogLevel.Error, + formatString: "An error occurred while reading the key ring."); + _keyRingDoesNotContainValidDefaultKey = LoggerMessage.Define( + eventId: 49, + logLevel: LogLevel.Error, + formatString: "The key ring does not contain a valid default key, and the key manager is configured with auto-generation of keys disabled."); + _usingInmemoryRepository = LoggerMessage.Define( + eventId: 50, + logLevel: LogLevel.Warning, + formatString: "Using an in-memory repository. Keys will not be persisted to storage."); + _decryptingSecretElementUsingWindowsDPAPI = LoggerMessage.Define( + eventId: 51, + logLevel: LogLevel.Debug, + formatString: "Decrypting secret element using Windows DPAPI."); + _defaultKeyExpirationImminentAndRepository = LoggerMessage.Define( + eventId: 52, + logLevel: LogLevel.Debug, + formatString: "Default key expiration imminent and repository contains no viable successor. Caller should generate a successor."); + _repositoryContainsNoViableDefaultKey = LoggerMessage.Define( + eventId: 53, + logLevel: LogLevel.Debug, + formatString: "Repository contains no viable default key. Caller should generate a key with immediate activation."); + _errorOccurredWhileEncryptingToWindowsDPAPI = LoggerMessage.Define( + eventId: 54, + logLevel: LogLevel.Error, + formatString: "An error occurred while encrypting to Windows DPAPI."); + _encryptingToWindowsDPAPIForLocalMachineAccount = LoggerMessage.Define( + eventId: 55, + logLevel: LogLevel.Debug, + formatString: "Encrypting to Windows DPAPI for local machine account."); + _errorOccurredWhileEncryptingToWindowsDPAPING = LoggerMessage.Define( + eventId: 56, + logLevel: LogLevel.Error, + formatString: "An error occurred while encrypting to Windows DPAPI-NG."); + _policyResolutionStatesThatANewKeyShouldBeAddedToTheKeyRing = LoggerMessage.Define( + eventId: 57, + logLevel: LogLevel.Debug, + formatString: "Policy resolution states that a new key should be added to the key ring."); + _creatingKey = LoggerMessage.Define( + eventId: 58, + logLevel: LogLevel.Information, + formatString: "Creating key {KeyId:B} with creation date {CreationDate:u}, activation date {ActivationDate:u}, and expiration date {ExpirationDate:u}."); + _usingEphemeralKeyRepository = LoggerMessage.Define( + eventId: 59, + logLevel: LogLevel.Warning, + formatString: "Neither user profile nor HKLM registry available. Using an ephemeral key repository. Protected data will be unavailable when application exits."); + _usingEphemeralFileSystemLocationInContainer = LoggerMessage.Define( + eventId: 60, + logLevel: LogLevel.Warning, + formatString: Resources.FileSystem_EphemeralKeysLocationInContainer); + + _usingRegistryAsKeyRepositoryWithDPAPI = LoggerMessage.Define( + eventId: 0, + logLevel: LogLevel.Information, + formatString: "User profile not available. Using '{Name}' as key repository and Windows DPAPI to encrypt keys at rest."); + _usingProfileAsKeyRepository = LoggerMessage.Define( + eventId: 0, + logLevel: LogLevel.Information, + formatString: "User profile is available. Using '{FullName}' as key repository; keys will not be encrypted at rest."); + _usingProfileAsKeyRepositoryWithDPAPI = LoggerMessage.Define( + eventId: 0, + logLevel: LogLevel.Information, + formatString: "User profile is available. Using '{FullName}' as key repository and Windows DPAPI to encrypt keys at rest."); + _usingAzureAsKeyRepository = LoggerMessage.Define( + eventId: 0, + logLevel: LogLevel.Information, + formatString: "Azure Web Sites environment detected. Using '{FullName}' as key repository; keys will not be encrypted at rest."); + _keyRingWasLoadedOnStartup = LoggerMessage.Define( + eventId: 0, + logLevel: LogLevel.Debug, + formatString: "Key ring with default key {KeyId:B} was loaded during application startup."); + _keyRingFailedToLoadOnStartup = LoggerMessage.Define( + eventId: 0, + logLevel: LogLevel.Information, + formatString: "Key ring failed to load during application startup."); + } + + /// + /// Returns a value stating whether the 'debug' log level is enabled. + /// Returns false if the logger instance is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsDebugLevelEnabled(this ILogger logger) + { + return IsLogLevelEnabledCore(logger, LogLevel.Debug); + } + + /// + /// Returns a value stating whether the 'error' log level is enabled. + /// Returns false if the logger instance is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsErrorLevelEnabled(this ILogger logger) + { + return IsLogLevelEnabledCore(logger, LogLevel.Error); + } + + /// + /// Returns a value stating whether the 'information' log level is enabled. + /// Returns false if the logger instance is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsInformationLevelEnabled(this ILogger logger) + { + return IsLogLevelEnabledCore(logger, LogLevel.Information); + } + + /// + /// Returns a value stating whether the 'trace' log level is enabled. + /// Returns false if the logger instance is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsTraceLevelEnabled(this ILogger logger) + { + return IsLogLevelEnabledCore(logger, LogLevel.Trace); + } + + /// + /// Returns a value stating whether the 'warning' log level is enabled. + /// Returns false if the logger instance is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsWarningLevelEnabled(this ILogger logger) + { + return IsLogLevelEnabledCore(logger, LogLevel.Warning); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsLogLevelEnabledCore(ILogger logger, LogLevel level) + { + return (logger != null && logger.IsEnabled(level)); + } + + public static void UsingFallbackKeyWithExpirationAsDefaultKey(this ILogger logger, Guid keyId, DateTimeOffset expirationDate) + { + _usingFallbackKeyWithExpirationAsDefaultKey(logger, keyId, expirationDate, null); + } + + public static void UsingKeyAsDefaultKey(this ILogger logger, Guid keyId) + { + _usingKeyAsDefaultKey(logger, keyId, null); + } + + public static void OpeningCNGAlgorithmFromProviderWithHMAC(this ILogger logger, string hashAlgorithm, string hashAlgorithmProvider) + { + _openingCNGAlgorithmFromProviderWithHMAC(logger, hashAlgorithm, hashAlgorithmProvider, null); + } + + public static void OpeningCNGAlgorithmFromProviderWithChainingModeCBC(this ILogger logger, string encryptionAlgorithm, string encryptionAlgorithmProvider) + { + _openingCNGAlgorithmFromProviderWithChainingModeCBC(logger, encryptionAlgorithm, encryptionAlgorithmProvider, null); + } + + public static void PerformingUnprotectOperationToKeyWithPurposes(this ILogger logger, Guid keyIdFromPayload, string p0) + { + _performingUnprotectOperationToKeyWithPurposes(logger, keyIdFromPayload, p0, null); + } + + public static void KeyWasNotFoundInTheKeyRingUnprotectOperationCannotProceed(this ILogger logger, Guid keyIdFromPayload) + { + _keyWasNotFoundInTheKeyRingUnprotectOperationCannotProceed(logger, keyIdFromPayload, null); + } + + public static void KeyWasRevokedCallerRequestedUnprotectOperationProceedRegardless(this ILogger logger, Guid keyIdFromPayload) + { + _keyWasRevokedCallerRequestedUnprotectOperationProceedRegardless(logger, keyIdFromPayload, null); + } + + public static void KeyWasRevokedUnprotectOperationCannotProceed(this ILogger logger, Guid keyIdFromPayload) + { + _keyWasRevokedUnprotectOperationCannotProceed(logger, keyIdFromPayload, null); + } + + public static void OpeningCNGAlgorithmFromProviderWithChainingModeGCM(this ILogger logger, string encryptionAlgorithm, string encryptionAlgorithmProvider) + { + _openingCNGAlgorithmFromProviderWithChainingModeGCM(logger, encryptionAlgorithm, encryptionAlgorithmProvider, null); + } + + public static void UsingManagedKeyedHashAlgorithm(this ILogger logger, string fullName) + { + _usingManagedKeyedHashAlgorithm(logger, fullName, null); + } + + public static void UsingManagedSymmetricAlgorithm(this ILogger logger, string fullName) + { + _usingManagedSymmetricAlgorithm(logger, fullName, null); + } + + public static void KeyIsIneligibleToBeTheDefaultKeyBecauseItsMethodFailed(this ILogger logger, Guid keyId, string p0, Exception exception) + { + _keyIsIneligibleToBeTheDefaultKeyBecauseItsMethodFailed(logger, keyId, p0, exception); + } + + public static void ConsideringKeyWithExpirationDateAsDefaultKey(this ILogger logger, Guid keyId, DateTimeOffset expirationDate) + { + _consideringKeyWithExpirationDateAsDefaultKey(logger, keyId, expirationDate, null); + } + + public static void KeyIsNoLongerUnderConsiderationAsDefault(this ILogger logger, Guid keyId) + { + _keyIsNoLongerUnderConsiderationAsDefault(logger, keyId, null); + } + + public static void UnknownElementWithNameFoundInKeyringSkipping(this ILogger logger, XName name) + { + _unknownElementWithNameFoundInKeyringSkipping(logger, name, null); + } + + public static void MarkedKeyAsRevokedInTheKeyring(this ILogger logger, Guid revokedKeyId) + { + _markedKeyAsRevokedInTheKeyring(logger, revokedKeyId, null); + } + + public static void TriedToProcessRevocationOfKeyButNoSuchKeyWasFound(this ILogger logger, Guid revokedKeyId) + { + _triedToProcessRevocationOfKeyButNoSuchKeyWasFound(logger, revokedKeyId, null); + } + + public static void FoundKey(this ILogger logger, Guid keyId) + { + _foundKey(logger, keyId, null); + } + + public static void FoundRevocationOfAllKeysCreatedPriorTo(this ILogger logger, DateTimeOffset massRevocationDate) + { + _foundRevocationOfAllKeysCreatedPriorTo(logger, massRevocationDate, null); + } + + public static void FoundRevocationOfKey(this ILogger logger, Guid keyId) + { + _foundRevocationOfKey(logger, keyId, null); + } + + public static void ExceptionWhileProcessingRevocationElement(this ILogger logger, XElement revocationElement, Exception exception) + { + _exceptionWhileProcessingRevocationElement(logger, revocationElement, exception); + } + + public static void RevokingAllKeysAsOfForReason(this ILogger logger, DateTimeOffset revocationDate, string reason) + { + _revokingAllKeysAsOfForReason(logger, revocationDate, reason, null); + } + + public static void KeyCacheExpirationTokenTriggeredByOperation(this ILogger logger, string opName) + { + _keyCacheExpirationTokenTriggeredByOperation(logger, opName, null); + } + + public static void ExceptionWhileProcessingKeyElement(this ILogger logger, XElement keyElement, Exception exception) + { + _anExceptionOccurredWhileProcessingTheKeyElement(logger, keyElement, exception); + } + + public static void AnExceptionOccurredWhileProcessingElementDebug(this ILogger logger, XElement keyElement, Exception exception) + { + _anExceptionOccurredWhileProcessingTheKeyElementDebug(logger, keyElement, exception); + } + + public static void EncryptingToWindowsDPAPIForCurrentUserAccount(this ILogger logger, string name) + { + _encryptingToWindowsDPAPIForCurrentUserAccount(logger, name, null); + } + + public static void AnErrorOccurredWhileEncryptingToX509CertificateWithThumbprint(this ILogger logger, string thumbprint, Exception exception) + { + _anErrorOccurredWhileEncryptingToX509CertificateWithThumbprint(logger, thumbprint, exception); + } + + public static void EncryptingToX509CertificateWithThumbprint(this ILogger logger, string thumbprint) + { + _encryptingToX509CertificateWithThumbprint(logger, thumbprint, null); + } + + public static void ExceptionWhileTryingToResolveCertificateWithThumbprint(this ILogger logger, string thumbprint, Exception exception) + { + _exceptionOccurredWhileTryingToResolveCertificateWithThumbprint(logger, thumbprint, exception); + } + + public static void PerformingProtectOperationToKeyWithPurposes(this ILogger logger, Guid defaultKeyId, string p0) + { + _performingProtectOperationToKeyWithPurposes(logger, defaultKeyId, p0, null); + } + + public static void DescriptorDeserializerTypeForKeyIs(this ILogger logger, Guid keyId, string assemblyQualifiedName) + { + _descriptorDeserializerTypeForKeyIs(logger, keyId, assemblyQualifiedName, null); + } + + public static void KeyEscrowSinkFoundWritingKeyToEscrow(this ILogger logger, Guid keyId) + { + _keyEscrowSinkFoundWritingKeyToEscrow(logger, keyId, null); + } + + public static void NoKeyEscrowSinkFoundNotWritingKeyToEscrow(this ILogger logger, Guid keyId) + { + _noKeyEscrowSinkFoundNotWritingKeyToEscrow(logger, keyId, null); + } + + public static void NoXMLEncryptorConfiguredKeyMayBePersistedToStorageInUnencryptedForm(this ILogger logger, Guid keyId) + { + _noXMLEncryptorConfiguredKeyMayBePersistedToStorageInUnencryptedForm(logger, keyId, null); + } + + public static void RevokingKeyForReason(this ILogger logger, Guid keyId, DateTimeOffset revocationDate, string reason) + { + _revokingKeyForReason(logger, keyId, revocationDate, reason, null); + } + + public static void ReadingDataFromFile(this ILogger logger, string fullPath) + { + _readingDataFromFile(logger, fullPath, null); + } + + public static void NameIsNotSafeFileName(this ILogger logger, string friendlyName, string newFriendlyName) + { + _nameIsNotSafeFileName(logger, friendlyName, newFriendlyName, null); + } + + public static void WritingDataToFile(this ILogger logger, string finalFilename) + { + _writingDataToFile(logger, finalFilename, null); + } + + public static void ReadingDataFromRegistryKeyValue(this ILogger logger, RegistryKey regKey, string valueName) + { + _readingDataFromRegistryKeyValue(logger, regKey, valueName, null); + } + + public static void NameIsNotSafeRegistryValueName(this ILogger logger, string friendlyName, string newFriendlyName) + { + _nameIsNotSafeRegistryValueName(logger, friendlyName, newFriendlyName, null); + } + + public static void DecryptingSecretElementUsingWindowsDPAPING(this ILogger logger, string protectionDescriptorRule) + { + _decryptingSecretElementUsingWindowsDPAPING(logger, protectionDescriptorRule, null); + } + + public static void EncryptingToWindowsDPAPINGUsingProtectionDescriptorRule(this ILogger logger, string protectionDescriptorRuleString) + { + _encryptingToWindowsDPAPINGUsingProtectionDescriptorRule(logger, protectionDescriptorRuleString, null); + } + + public static void ExceptionOccurredTryingToDecryptElement(this ILogger logger, Exception exception) + { + _exceptionOccurredTryingToDecryptElement(logger, exception); + } + + public static void EncryptingUsingNullEncryptor(this ILogger logger) + { + _encryptingUsingNullEncryptor(logger, null); + } + + public static void UsingEphemeralDataProtectionProvider(this ILogger logger) + { + _usingEphemeralDataProtectionProvider(logger, null); + } + + public static void ExistingCachedKeyRingIsExpired(this ILogger logger) + { + _existingCachedKeyRingIsExpiredRefreshing(logger, null); + } + + public static void ErrorOccurredWhileRefreshingKeyRing(this ILogger logger, Exception exception) + { + _errorOccurredWhileRefreshingKeyRing(logger, exception); + } + + public static void ErrorOccurredWhileReadingKeyRing(this ILogger logger, Exception exception) + { + _errorOccurredWhileReadingKeyRing(logger, exception); + } + + public static void KeyRingDoesNotContainValidDefaultKey(this ILogger logger) + { + _keyRingDoesNotContainValidDefaultKey(logger, null); + } + + public static void UsingInmemoryRepository(this ILogger logger) + { + _usingInmemoryRepository(logger, null); + } + + public static void DecryptingSecretElementUsingWindowsDPAPI(this ILogger logger) + { + _decryptingSecretElementUsingWindowsDPAPI(logger, null); + } + + public static void DefaultKeyExpirationImminentAndRepository(this ILogger logger) + { + _defaultKeyExpirationImminentAndRepository(logger, null); + } + + public static void RepositoryContainsNoViableDefaultKey(this ILogger logger) + { + _repositoryContainsNoViableDefaultKey(logger, null); + } + + public static void ErrorOccurredWhileEncryptingToWindowsDPAPI(this ILogger logger, Exception exception) + { + _errorOccurredWhileEncryptingToWindowsDPAPI(logger, exception); + } + + public static void EncryptingToWindowsDPAPIForLocalMachineAccount(this ILogger logger) + { + _encryptingToWindowsDPAPIForLocalMachineAccount(logger, null); + } + + public static void ErrorOccurredWhileEncryptingToWindowsDPAPING(this ILogger logger, Exception exception) + { + _errorOccurredWhileEncryptingToWindowsDPAPING(logger, exception); + } + + public static void PolicyResolutionStatesThatANewKeyShouldBeAddedToTheKeyRing(this ILogger logger) + { + _policyResolutionStatesThatANewKeyShouldBeAddedToTheKeyRing(logger, null); + } + + public static void CreatingKey(this ILogger logger, Guid keyId, DateTimeOffset creationDate, DateTimeOffset activationDate, DateTimeOffset expirationDate) + { + _creatingKey(logger, keyId, creationDate, activationDate, expirationDate, null); + } + + public static void UsingEphemeralKeyRepository(this ILogger logger) + { + _usingEphemeralKeyRepository(logger, null); + } + + public static void UsingRegistryAsKeyRepositoryWithDPAPI(this ILogger logger, string name) + { + _usingRegistryAsKeyRepositoryWithDPAPI(logger, name, null); + } + + public static void UsingProfileAsKeyRepository(this ILogger logger, string fullName) + { + _usingProfileAsKeyRepository(logger, fullName, null); + } + + public static void UsingProfileAsKeyRepositoryWithDPAPI(this ILogger logger, string fullName) + { + _usingProfileAsKeyRepositoryWithDPAPI(logger, fullName, null); + } + + public static void UsingAzureAsKeyRepository(this ILogger logger, string fullName) + { + _usingAzureAsKeyRepository(logger, fullName, null); + } + + public static void KeyRingWasLoadedOnStartup(this ILogger logger, Guid defaultKeyId) + { + _keyRingWasLoadedOnStartup(logger, defaultKeyId, null); + } + + public static void KeyRingFailedToLoadOnStartup(this ILogger logger, Exception innerException) + { + _keyRingFailedToLoadOnStartup(logger, innerException); + } + + public static void UsingEphemeralFileSystemLocationInContainer(this ILogger logger, string path) + { + _usingEphemeralFileSystemLocationInContainer(logger, path, null); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/LoggingServiceProviderExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/LoggingServiceProviderExtensions.cs new file mode 100644 index 0000000000..199f9fd35c --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/LoggingServiceProviderExtensions.cs @@ -0,0 +1,43 @@ +// 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 Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace System +{ + /// + /// Helpful logging-related extension methods on . + /// + internal static class LoggingServiceProviderExtensions + { + /// + /// Retrieves an instance of given the type name . + /// This is equivalent to . + /// + /// + /// An instance, or null if is null or the + /// cannot produce an . + /// + public static ILogger GetLogger(this IServiceProvider services) + { + return GetLogger(services, typeof(T)); + } + + /// + /// Retrieves an instance of given the type name . + /// This is equivalent to . + /// + /// + /// An instance, or null if is null or the + /// cannot produce an . + /// + public static ILogger GetLogger(this IServiceProvider services, Type type) + { + // Compiler won't allow us to use static types as the type parameter + // for the call to CreateLogger, so we'll duplicate its logic here. + return services?.GetService()?.CreateLogger(type.FullName); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/HashAlgorithmExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/HashAlgorithmExtensions.cs new file mode 100644 index 0000000000..af854158ec --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/HashAlgorithmExtensions.cs @@ -0,0 +1,19 @@ +// 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.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection.Managed +{ + internal static class HashAlgorithmExtensions + { + public static int GetDigestSizeInBytes(this HashAlgorithm hashAlgorithm) + { + var hashSizeInBits = hashAlgorithm.HashSize; + CryptoUtil.Assert(hashSizeInBits >= 0 && hashSizeInBits % 8 == 0, "hashSizeInBits >= 0 && hashSizeInBits % 8 == 0"); + return hashSizeInBits / 8; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/IManagedGenRandom.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/IManagedGenRandom.cs new file mode 100644 index 0000000000..1d08f1e7d8 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/IManagedGenRandom.cs @@ -0,0 +1,12 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.Managed +{ + internal interface IManagedGenRandom + { + byte[] GenRandom(int numBytes); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs new file mode 100644 index 0000000000..0d93955d75 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs @@ -0,0 +1,375 @@ +// 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.IO; +using System.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.SP800_108; + +namespace Microsoft.AspNetCore.DataProtection.Managed +{ + // An encryptor which does Encrypt(CBC) + HMAC using SymmetricAlgorithm and HashAlgorithm. + // The payloads produced by this encryptor should be compatible with the payloads + // produced by the CNG-based Encrypt(CBC) + HMAC authenticated encryptor. + internal unsafe sealed class ManagedAuthenticatedEncryptor : IAuthenticatedEncryptor, IDisposable + { + // Even when IVs are chosen randomly, CBC is susceptible to IV collisions within a single + // key. For a 64-bit block cipher (like 3DES), we'd expect a collision after 2^32 block + // encryption operations, which a high-traffic web server might perform in mere hours. + // AES and other 128-bit block ciphers are less susceptible to this due to the larger IV + // space, but unfortunately some organizations require older 64-bit block ciphers. To address + // the collision issue, we'll feed 128 bits of entropy to the KDF when performing subkey + // generation. This creates >= 192 bits total entropy for each operation, so we shouldn't + // expect a collision until >= 2^96 operations. Even 2^80 operations still maintains a <= 2^-32 + // probability of collision, and this is acceptable for the expected KDK lifetime. + private const int KEY_MODIFIER_SIZE_IN_BYTES = 128 / 8; + + private static readonly Func _kdkPrfFactory = key => new HMACSHA512(key); // currently hardcoded to SHA512 + + private readonly byte[] _contextHeader; + private readonly IManagedGenRandom _genRandom; + private readonly Secret _keyDerivationKey; + private readonly Func _symmetricAlgorithmFactory; + private readonly int _symmetricAlgorithmBlockSizeInBytes; + private readonly int _symmetricAlgorithmSubkeyLengthInBytes; + private readonly int _validationAlgorithmDigestLengthInBytes; + private readonly int _validationAlgorithmSubkeyLengthInBytes; + private readonly Func _validationAlgorithmFactory; + + public ManagedAuthenticatedEncryptor(Secret keyDerivationKey, Func symmetricAlgorithmFactory, int symmetricAlgorithmKeySizeInBytes, Func validationAlgorithmFactory, IManagedGenRandom genRandom = null) + { + _genRandom = genRandom ?? ManagedGenRandomImpl.Instance; + _keyDerivationKey = keyDerivationKey; + + // Validate that the symmetric algorithm has the properties we require + using (var symmetricAlgorithm = symmetricAlgorithmFactory()) + { + _symmetricAlgorithmFactory = symmetricAlgorithmFactory; + _symmetricAlgorithmBlockSizeInBytes = symmetricAlgorithm.GetBlockSizeInBytes(); + _symmetricAlgorithmSubkeyLengthInBytes = symmetricAlgorithmKeySizeInBytes; + } + + // Validate that the MAC algorithm has the properties we require + using (var validationAlgorithm = validationAlgorithmFactory()) + { + _validationAlgorithmFactory = validationAlgorithmFactory; + _validationAlgorithmDigestLengthInBytes = validationAlgorithm.GetDigestSizeInBytes(); + _validationAlgorithmSubkeyLengthInBytes = _validationAlgorithmDigestLengthInBytes; // for simplicity we'll generate MAC subkeys with a length equal to the digest length + } + + // Argument checking on the algorithms and lengths passed in to us + AlgorithmAssert.IsAllowableSymmetricAlgorithmBlockSize(checked((uint)_symmetricAlgorithmBlockSizeInBytes * 8)); + AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked((uint)_symmetricAlgorithmSubkeyLengthInBytes * 8)); + AlgorithmAssert.IsAllowableValidationAlgorithmDigestSize(checked((uint)_validationAlgorithmDigestLengthInBytes * 8)); + + _contextHeader = CreateContextHeader(); + } + + private byte[] CreateContextHeader() + { + var EMPTY_ARRAY = new byte[0]; + var EMPTY_ARRAY_SEGMENT = new ArraySegment(EMPTY_ARRAY); + + var retVal = new byte[checked( + 1 /* KDF alg */ + + 1 /* chaining mode */ + + sizeof(uint) /* sym alg key size */ + + sizeof(uint) /* sym alg block size */ + + sizeof(uint) /* hmac alg key size */ + + sizeof(uint) /* hmac alg digest size */ + + _symmetricAlgorithmBlockSizeInBytes /* ciphertext of encrypted empty string */ + + _validationAlgorithmDigestLengthInBytes /* digest of HMACed empty string */)]; + + var idx = 0; + + // First is the two-byte header + retVal[idx++] = 0; // 0x00 = SP800-108 CTR KDF w/ HMACSHA512 PRF + retVal[idx++] = 0; // 0x00 = CBC encryption + HMAC authentication + + // Next is information about the symmetric algorithm (key size followed by block size) + BitHelpers.WriteTo(retVal, ref idx, _symmetricAlgorithmSubkeyLengthInBytes); + BitHelpers.WriteTo(retVal, ref idx, _symmetricAlgorithmBlockSizeInBytes); + + // Next is information about the keyed hash algorithm (key size followed by digest size) + BitHelpers.WriteTo(retVal, ref idx, _validationAlgorithmSubkeyLengthInBytes); + BitHelpers.WriteTo(retVal, ref idx, _validationAlgorithmDigestLengthInBytes); + + // See the design document for an explanation of the following code. + var tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes + _validationAlgorithmSubkeyLengthInBytes]; + ManagedSP800_108_CTR_HMACSHA512.DeriveKeys( + kdk: EMPTY_ARRAY, + label: EMPTY_ARRAY_SEGMENT, + context: EMPTY_ARRAY_SEGMENT, + prfFactory: _kdkPrfFactory, + output: new ArraySegment(tempKeys)); + + // At this point, tempKeys := { K_E || K_H }. + + // Encrypt a zero-length input string with an all-zero IV and copy the ciphertext to the return buffer. + using (var symmetricAlg = CreateSymmetricAlgorithm()) + { + using (var cryptoTransform = symmetricAlg.CreateEncryptor( + rgbKey: new ArraySegment(tempKeys, 0, _symmetricAlgorithmSubkeyLengthInBytes).AsStandaloneArray(), + rgbIV: new byte[_symmetricAlgorithmBlockSizeInBytes])) + { + var ciphertext = cryptoTransform.TransformFinalBlock(EMPTY_ARRAY, 0, 0); + CryptoUtil.Assert(ciphertext != null && ciphertext.Length == _symmetricAlgorithmBlockSizeInBytes, "ciphertext != null && ciphertext.Length == _symmetricAlgorithmBlockSizeInBytes"); + Buffer.BlockCopy(ciphertext, 0, retVal, idx, ciphertext.Length); + } + } + + idx += _symmetricAlgorithmBlockSizeInBytes; + + // MAC a zero-length input string and copy the digest to the return buffer. + using (var hashAlg = CreateValidationAlgorithm(new ArraySegment(tempKeys, _symmetricAlgorithmSubkeyLengthInBytes, _validationAlgorithmSubkeyLengthInBytes).AsStandaloneArray())) + { + var digest = hashAlg.ComputeHash(EMPTY_ARRAY); + CryptoUtil.Assert(digest != null && digest.Length == _validationAlgorithmDigestLengthInBytes, "digest != null && digest.Length == _validationAlgorithmDigestLengthInBytes"); + Buffer.BlockCopy(digest, 0, retVal, idx, digest.Length); + } + + idx += _validationAlgorithmDigestLengthInBytes; + CryptoUtil.Assert(idx == retVal.Length, "idx == retVal.Length"); + + // retVal := { version || chainingMode || symAlgKeySize || symAlgBlockSize || macAlgKeySize || macAlgDigestSize || E("") || MAC("") }. + return retVal; + } + + private SymmetricAlgorithm CreateSymmetricAlgorithm() + { + var retVal = _symmetricAlgorithmFactory(); + CryptoUtil.Assert(retVal != null, "retVal != null"); + + retVal.Mode = CipherMode.CBC; + retVal.Padding = PaddingMode.PKCS7; + return retVal; + } + + private KeyedHashAlgorithm CreateValidationAlgorithm(byte[] key) + { + var retVal = _validationAlgorithmFactory(); + CryptoUtil.Assert(retVal != null, "retVal != null"); + + retVal.Key = key; + return retVal; + } + + public byte[] Decrypt(ArraySegment protectedPayload, ArraySegment additionalAuthenticatedData) + { + protectedPayload.Validate(); + additionalAuthenticatedData.Validate(); + + // Argument checking - input must at the absolute minimum contain a key modifier, IV, and MAC + if (protectedPayload.Count < checked(KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + _validationAlgorithmDigestLengthInBytes)) + { + throw Error.CryptCommon_PayloadInvalid(); + } + + // Assumption: protectedPayload := { keyModifier | IV | encryptedData | MAC(IV | encryptedPayload) } + + try + { + // Step 1: Extract the key modifier and IV from the payload. + + int keyModifierOffset; // position in protectedPayload.Array where key modifier begins + int ivOffset; // position in protectedPayload.Array where key modifier ends / IV begins + int ciphertextOffset; // position in protectedPayload.Array where IV ends / ciphertext begins + int macOffset; // position in protectedPayload.Array where ciphertext ends / MAC begins + int eofOffset; // position in protectedPayload.Array where MAC ends + + checked + { + keyModifierOffset = protectedPayload.Offset; + ivOffset = keyModifierOffset + KEY_MODIFIER_SIZE_IN_BYTES; + ciphertextOffset = ivOffset + _symmetricAlgorithmBlockSizeInBytes; + } + + ArraySegment keyModifier = new ArraySegment(protectedPayload.Array, keyModifierOffset, ivOffset - keyModifierOffset); + var iv = new byte[_symmetricAlgorithmBlockSizeInBytes]; + Buffer.BlockCopy(protectedPayload.Array, ivOffset, iv, 0, iv.Length); + + // Step 2: Decrypt the KDK and use it to restore the original encryption and MAC keys. + // We pin all unencrypted keys to limit their exposure via GC relocation. + + var decryptedKdk = new byte[_keyDerivationKey.Length]; + var decryptionSubkey = new byte[_symmetricAlgorithmSubkeyLengthInBytes]; + var validationSubkey = new byte[_validationAlgorithmSubkeyLengthInBytes]; + var derivedKeysBuffer = new byte[checked(decryptionSubkey.Length + validationSubkey.Length)]; + + fixed (byte* __unused__1 = decryptedKdk) + fixed (byte* __unused__2 = decryptionSubkey) + fixed (byte* __unused__3 = validationSubkey) + fixed (byte* __unused__4 = derivedKeysBuffer) + { + try + { + _keyDerivationKey.WriteSecretIntoBuffer(new ArraySegment(decryptedKdk)); + ManagedSP800_108_CTR_HMACSHA512.DeriveKeysWithContextHeader( + kdk: decryptedKdk, + label: additionalAuthenticatedData, + contextHeader: _contextHeader, + context: keyModifier, + prfFactory: _kdkPrfFactory, + output: new ArraySegment(derivedKeysBuffer)); + + Buffer.BlockCopy(derivedKeysBuffer, 0, decryptionSubkey, 0, decryptionSubkey.Length); + Buffer.BlockCopy(derivedKeysBuffer, decryptionSubkey.Length, validationSubkey, 0, validationSubkey.Length); + + // Step 3: Calculate the correct MAC for this payload. + // correctHash := MAC(IV || ciphertext) + byte[] correctHash; + + using (var hashAlgorithm = CreateValidationAlgorithm(validationSubkey)) + { + checked + { + eofOffset = protectedPayload.Offset + protectedPayload.Count; + macOffset = eofOffset - _validationAlgorithmDigestLengthInBytes; + } + + correctHash = hashAlgorithm.ComputeHash(protectedPayload.Array, ivOffset, macOffset - ivOffset); + } + + // Step 4: Validate the MAC provided as part of the payload. + + if (!CryptoUtil.TimeConstantBuffersAreEqual(correctHash, 0, correctHash.Length, protectedPayload.Array, macOffset, eofOffset - macOffset)) + { + throw Error.CryptCommon_PayloadInvalid(); // integrity check failure + } + + // Step 5: Decipher the ciphertext and return it to the caller. + + using (var symmetricAlgorithm = CreateSymmetricAlgorithm()) + using (var cryptoTransform = symmetricAlgorithm.CreateDecryptor(decryptionSubkey, iv)) + { + var outputStream = new MemoryStream(); + using (var cryptoStream = new CryptoStream(outputStream, cryptoTransform, CryptoStreamMode.Write)) + { + cryptoStream.Write(protectedPayload.Array, ciphertextOffset, macOffset - ciphertextOffset); + cryptoStream.FlushFinalBlock(); + + // At this point, outputStream := { plaintext }, and we're done! + return outputStream.ToArray(); + } + } + } + finally + { + // delete since these contain secret material + Array.Clear(decryptedKdk, 0, decryptedKdk.Length); + Array.Clear(decryptionSubkey, 0, decryptionSubkey.Length); + Array.Clear(validationSubkey, 0, validationSubkey.Length); + Array.Clear(derivedKeysBuffer, 0, derivedKeysBuffer.Length); + } + } + } + catch (Exception ex) when (ex.RequiresHomogenization()) + { + // Homogenize all exceptions to CryptographicException. + throw Error.CryptCommon_GenericError(ex); + } + } + + public void Dispose() + { + _keyDerivationKey.Dispose(); + } + + public byte[] Encrypt(ArraySegment plaintext, ArraySegment additionalAuthenticatedData) + { + plaintext.Validate(); + additionalAuthenticatedData.Validate(); + + try + { + var outputStream = new MemoryStream(); + + // Step 1: Generate a random key modifier and IV for this operation. + // Both will be equal to the block size of the block cipher algorithm. + + var keyModifier = _genRandom.GenRandom(KEY_MODIFIER_SIZE_IN_BYTES); + var iv = _genRandom.GenRandom(_symmetricAlgorithmBlockSizeInBytes); + + // Step 2: Copy the key modifier and the IV to the output stream since they'll act as a header. + + outputStream.Write(keyModifier, 0, keyModifier.Length); + outputStream.Write(iv, 0, iv.Length); + + // At this point, outputStream := { keyModifier || IV }. + + // Step 3: Decrypt the KDK, and use it to generate new encryption and HMAC keys. + // We pin all unencrypted keys to limit their exposure via GC relocation. + + var decryptedKdk = new byte[_keyDerivationKey.Length]; + var encryptionSubkey = new byte[_symmetricAlgorithmSubkeyLengthInBytes]; + var validationSubkey = new byte[_validationAlgorithmSubkeyLengthInBytes]; + var derivedKeysBuffer = new byte[checked(encryptionSubkey.Length + validationSubkey.Length)]; + + fixed (byte* __unused__1 = decryptedKdk) + fixed (byte* __unused__2 = encryptionSubkey) + fixed (byte* __unused__3 = validationSubkey) + fixed (byte* __unused__4 = derivedKeysBuffer) + { + try + { + _keyDerivationKey.WriteSecretIntoBuffer(new ArraySegment(decryptedKdk)); + ManagedSP800_108_CTR_HMACSHA512.DeriveKeysWithContextHeader( + kdk: decryptedKdk, + label: additionalAuthenticatedData, + contextHeader: _contextHeader, + context: new ArraySegment(keyModifier), + prfFactory: _kdkPrfFactory, + output: new ArraySegment(derivedKeysBuffer)); + + Buffer.BlockCopy(derivedKeysBuffer, 0, encryptionSubkey, 0, encryptionSubkey.Length); + Buffer.BlockCopy(derivedKeysBuffer, encryptionSubkey.Length, validationSubkey, 0, validationSubkey.Length); + + // Step 4: Perform the encryption operation. + + using (var symmetricAlgorithm = CreateSymmetricAlgorithm()) + using (var cryptoTransform = symmetricAlgorithm.CreateEncryptor(encryptionSubkey, iv)) + using (var cryptoStream = new CryptoStream(outputStream, cryptoTransform, CryptoStreamMode.Write)) + { + cryptoStream.Write(plaintext.Array, plaintext.Offset, plaintext.Count); + cryptoStream.FlushFinalBlock(); + + // At this point, outputStream := { keyModifier || IV || ciphertext } + + // Step 5: Calculate the digest over the IV and ciphertext. + // We don't need to calculate the digest over the key modifier since that + // value has already been mixed into the KDF used to generate the MAC key. + + using (var validationAlgorithm = CreateValidationAlgorithm(validationSubkey)) + { + // As an optimization, avoid duplicating the underlying buffer + var underlyingBuffer = outputStream.GetBuffer(); + + var mac = validationAlgorithm.ComputeHash(underlyingBuffer, KEY_MODIFIER_SIZE_IN_BYTES, checked((int)outputStream.Length - KEY_MODIFIER_SIZE_IN_BYTES)); + outputStream.Write(mac, 0, mac.Length); + + // At this point, outputStream := { keyModifier || IV || ciphertext || MAC(IV || ciphertext) } + // And we're done! + return outputStream.ToArray(); + } + } + } + finally + { + // delete since these contain secret material + Array.Clear(decryptedKdk, 0, decryptedKdk.Length); + Array.Clear(encryptionSubkey, 0, encryptionSubkey.Length); + Array.Clear(validationSubkey, 0, validationSubkey.Length); + Array.Clear(derivedKeysBuffer, 0, derivedKeysBuffer.Length); + } + } + } + catch (Exception ex) when (ex.RequiresHomogenization()) + { + // Homogenize all exceptions to CryptographicException. + throw Error.CryptCommon_GenericError(ex); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/ManagedGenRandomImpl.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/ManagedGenRandomImpl.cs new file mode 100644 index 0000000000..d334f36672 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/ManagedGenRandomImpl.cs @@ -0,0 +1,25 @@ +// 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.Security.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection.Managed +{ + internal unsafe sealed class ManagedGenRandomImpl : IManagedGenRandom + { + private static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create(); + public static readonly ManagedGenRandomImpl Instance = new ManagedGenRandomImpl(); + + private ManagedGenRandomImpl() + { + } + + public byte[] GenRandom(int numBytes) + { + var bytes = new byte[numBytes]; + _rng.GetBytes(bytes); + return bytes; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/SymmetricAlgorithmExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/SymmetricAlgorithmExtensions.cs new file mode 100644 index 0000000000..d411ce26c0 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Managed/SymmetricAlgorithmExtensions.cs @@ -0,0 +1,19 @@ +// 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.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection.Managed +{ + internal static class SymmetricAlgorithmExtensions + { + public static int GetBlockSizeInBytes(this SymmetricAlgorithm symmetricAlgorithm) + { + var blockSizeInBits = symmetricAlgorithm.BlockSize; + CryptoUtil.Assert(blockSizeInBits >= 0 && blockSizeInBits % 8 == 0, "blockSizeInBits >= 0 && blockSizeInBits % 8 == 0"); + return blockSizeInBits / 8; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/MemoryProtection.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/MemoryProtection.cs new file mode 100644 index 0000000000..be87e3cde5 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/MemoryProtection.cs @@ -0,0 +1,42 @@ +// 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.Runtime.InteropServices; +using Microsoft.AspNetCore.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Wrappers around CryptProtectMemory / CryptUnprotectMemory. + /// + internal unsafe static class MemoryProtection + { + // from dpapi.h + private const uint CRYPTPROTECTMEMORY_SAME_PROCESS = 0x00; + + public static void CryptProtectMemory(SafeHandle pBuffer, uint byteCount) + { + if (!UnsafeNativeMethods.CryptProtectMemory(pBuffer, byteCount, CRYPTPROTECTMEMORY_SAME_PROCESS)) + { + UnsafeNativeMethods.ThrowExceptionForLastCrypt32Error(); + } + } + + public static void CryptUnprotectMemory(byte* pBuffer, uint byteCount) + { + if (!UnsafeNativeMethods.CryptUnprotectMemory(pBuffer, byteCount, CRYPTPROTECTMEMORY_SAME_PROCESS)) + { + UnsafeNativeMethods.ThrowExceptionForLastCrypt32Error(); + } + } + + public static void CryptUnprotectMemory(SafeHandle pBuffer, uint byteCount) + { + if (!UnsafeNativeMethods.CryptUnprotectMemory(pBuffer, byteCount, CRYPTPROTECTMEMORY_SAME_PROCESS)) + { + UnsafeNativeMethods.ThrowExceptionForLastCrypt32Error(); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Microsoft.AspNetCore.DataProtection.csproj b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Microsoft.AspNetCore.DataProtection.csproj new file mode 100644 index 0000000000..3d3d87f25b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Microsoft.AspNetCore.DataProtection.csproj @@ -0,0 +1,31 @@ + + + + ASP.NET Core logic to protect and unprotect data, similar to DPAPI. + netstandard2.0 + $(NoWarn);CS1591 + true + true + aspnetcore;dataprotection + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Properties/AssemblyInfo.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..614112bd73 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Properties/AssemblyInfo.cs @@ -0,0 +1,9 @@ +// 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.Runtime.CompilerServices; + +// for unit testing +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.DataProtection.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.DataProtection.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Properties/Resources.Designer.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..c570287f84 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Properties/Resources.Designer.cs @@ -0,0 +1,394 @@ +// +namespace Microsoft.AspNetCore.DataProtection +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.AspNetCore.DataProtection.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// An error occurred during a cryptographic operation. + /// + internal static string CryptCommon_GenericError + { + get => GetString("CryptCommon_GenericError"); + } + + /// + /// An error occurred during a cryptographic operation. + /// + internal static string FormatCryptCommon_GenericError() + => GetString("CryptCommon_GenericError"); + + /// + /// The provided buffer is of length {0} byte(s). It must instead be exactly {1} byte(s) in length. + /// + internal static string Common_BufferIncorrectlySized + { + get => GetString("Common_BufferIncorrectlySized"); + } + + /// + /// The provided buffer is of length {0} byte(s). It must instead be exactly {1} byte(s) in length. + /// + internal static string FormatCommon_BufferIncorrectlySized(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("Common_BufferIncorrectlySized"), p0, p1); + + /// + /// The payload was invalid. + /// + internal static string CryptCommon_PayloadInvalid + { + get => GetString("CryptCommon_PayloadInvalid"); + } + + /// + /// The payload was invalid. + /// + internal static string FormatCryptCommon_PayloadInvalid() + => GetString("CryptCommon_PayloadInvalid"); + + /// + /// Property {0} cannot be null or empty. + /// + internal static string Common_PropertyCannotBeNullOrEmpty + { + get => GetString("Common_PropertyCannotBeNullOrEmpty"); + } + + /// + /// Property {0} cannot be null or empty. + /// + internal static string FormatCommon_PropertyCannotBeNullOrEmpty(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("Common_PropertyCannotBeNullOrEmpty"), p0); + + /// + /// The provided payload could not be decrypted. Refer to the inner exception for more information. + /// + internal static string Common_DecryptionFailed + { + get => GetString("Common_DecryptionFailed"); + } + + /// + /// The provided payload could not be decrypted. Refer to the inner exception for more information. + /// + internal static string FormatCommon_DecryptionFailed() + => GetString("Common_DecryptionFailed"); + + /// + /// An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information. + /// + internal static string Common_EncryptionFailed + { + get => GetString("Common_EncryptionFailed"); + } + + /// + /// An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information. + /// + internal static string FormatCommon_EncryptionFailed() + => GetString("Common_EncryptionFailed"); + + /// + /// The key {0:B} was not found in the key ring. + /// + internal static string Common_KeyNotFound + { + get => GetString("Common_KeyNotFound"); + } + + /// + /// The key {0:B} was not found in the key ring. + /// + internal static string FormatCommon_KeyNotFound() + => GetString("Common_KeyNotFound"); + + /// + /// The key {0:B} has been revoked. + /// + internal static string Common_KeyRevoked + { + get => GetString("Common_KeyRevoked"); + } + + /// + /// The key {0:B} has been revoked. + /// + internal static string FormatCommon_KeyRevoked() + => GetString("Common_KeyRevoked"); + + /// + /// The provided payload cannot be decrypted because it was not protected with this protection provider. + /// + internal static string ProtectionProvider_BadMagicHeader + { + get => GetString("ProtectionProvider_BadMagicHeader"); + } + + /// + /// The provided payload cannot be decrypted because it was not protected with this protection provider. + /// + internal static string FormatProtectionProvider_BadMagicHeader() + => GetString("ProtectionProvider_BadMagicHeader"); + + /// + /// The provided payload cannot be decrypted because it was protected with a newer version of the protection provider. + /// + internal static string ProtectionProvider_BadVersion + { + get => GetString("ProtectionProvider_BadVersion"); + } + + /// + /// The provided payload cannot be decrypted because it was protected with a newer version of the protection provider. + /// + internal static string FormatProtectionProvider_BadVersion() + => GetString("ProtectionProvider_BadVersion"); + + /// + /// Value must be non-negative. + /// + internal static string Common_ValueMustBeNonNegative + { + get => GetString("Common_ValueMustBeNonNegative"); + } + + /// + /// Value must be non-negative. + /// + internal static string FormatCommon_ValueMustBeNonNegative() + => GetString("Common_ValueMustBeNonNegative"); + + /// + /// The type '{1}' is not assignable to '{0}'. + /// + internal static string TypeExtensions_BadCast + { + get => GetString("TypeExtensions_BadCast"); + } + + /// + /// The type '{1}' is not assignable to '{0}'. + /// + internal static string FormatTypeExtensions_BadCast(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("TypeExtensions_BadCast"), p0, p1); + + /// + /// The new key lifetime must be at least one week. + /// + internal static string KeyManagementOptions_MinNewKeyLifetimeViolated + { + get => GetString("KeyManagementOptions_MinNewKeyLifetimeViolated"); + } + + /// + /// The new key lifetime must be at least one week. + /// + internal static string FormatKeyManagementOptions_MinNewKeyLifetimeViolated() + => GetString("KeyManagementOptions_MinNewKeyLifetimeViolated"); + + /// + /// The key {0:B} already exists in the keyring. + /// + internal static string XmlKeyManager_DuplicateKey + { + get => GetString("XmlKeyManager_DuplicateKey"); + } + + /// + /// The key {0:B} already exists in the keyring. + /// + internal static string FormatXmlKeyManager_DuplicateKey() + => GetString("XmlKeyManager_DuplicateKey"); + + /// + /// Argument cannot be null or empty. + /// + internal static string Common_ArgumentCannotBeNullOrEmpty + { + get => GetString("Common_ArgumentCannotBeNullOrEmpty"); + } + + /// + /// Argument cannot be null or empty. + /// + internal static string FormatCommon_ArgumentCannotBeNullOrEmpty() + => GetString("Common_ArgumentCannotBeNullOrEmpty"); + + /// + /// Property {0} must have a non-negative value. + /// + internal static string Common_PropertyMustBeNonNegative + { + get => GetString("Common_PropertyMustBeNonNegative"); + } + + /// + /// Property {0} must have a non-negative value. + /// + internal static string FormatCommon_PropertyMustBeNonNegative(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("Common_PropertyMustBeNonNegative"), p0); + + /// + /// GCM algorithms require the Windows platform. + /// + internal static string Platform_WindowsRequiredForGcm + { + get => GetString("Platform_WindowsRequiredForGcm"); + } + + /// + /// GCM algorithms require the Windows platform. + /// + internal static string FormatPlatform_WindowsRequiredForGcm() + => GetString("Platform_WindowsRequiredForGcm"); + + /// + /// A certificate with the thumbprint '{0}' could not be found. + /// + internal static string CertificateXmlEncryptor_CertificateNotFound + { + get => GetString("CertificateXmlEncryptor_CertificateNotFound"); + } + + /// + /// A certificate with the thumbprint '{0}' could not be found. + /// + internal static string FormatCertificateXmlEncryptor_CertificateNotFound(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("CertificateXmlEncryptor_CertificateNotFound"), p0); + + /// + /// Decrypting EncryptedXml-encapsulated payloads is not yet supported on Core CLR. + /// + internal static string EncryptedXmlDecryptor_DoesNotWorkOnCoreClr + { + get => GetString("EncryptedXmlDecryptor_DoesNotWorkOnCoreClr"); + } + + /// + /// Decrypting EncryptedXml-encapsulated payloads is not yet supported on Core CLR. + /// + internal static string FormatEncryptedXmlDecryptor_DoesNotWorkOnCoreClr() + => GetString("EncryptedXmlDecryptor_DoesNotWorkOnCoreClr"); + + /// + /// The symmetric algorithm block size of {0} bits is invalid. The block size must be between 64 and 2048 bits, inclusive, and it must be a multiple of 8 bits. + /// + internal static string AlgorithmAssert_BadBlockSize + { + get => GetString("AlgorithmAssert_BadBlockSize"); + } + + /// + /// The symmetric algorithm block size of {0} bits is invalid. The block size must be between 64 and 2048 bits, inclusive, and it must be a multiple of 8 bits. + /// + internal static string FormatAlgorithmAssert_BadBlockSize(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("AlgorithmAssert_BadBlockSize"), p0); + + /// + /// The validation algorithm digest size of {0} bits is invalid. The digest size must be between 128 and 2048 bits, inclusive, and it must be a multiple of 8 bits. + /// + internal static string AlgorithmAssert_BadDigestSize + { + get => GetString("AlgorithmAssert_BadDigestSize"); + } + + /// + /// The validation algorithm digest size of {0} bits is invalid. The digest size must be between 128 and 2048 bits, inclusive, and it must be a multiple of 8 bits. + /// + internal static string FormatAlgorithmAssert_BadDigestSize(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("AlgorithmAssert_BadDigestSize"), p0); + + /// + /// The symmetric algorithm key size of {0} bits is invalid. The key size must be between 128 and 2048 bits, inclusive, and it must be a multiple of 8 bits. + /// + internal static string AlgorithmAssert_BadKeySize + { + get => GetString("AlgorithmAssert_BadKeySize"); + } + + /// + /// The symmetric algorithm key size of {0} bits is invalid. The key size must be between 128 and 2048 bits, inclusive, and it must be a multiple of 8 bits. + /// + internal static string FormatAlgorithmAssert_BadKeySize(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("AlgorithmAssert_BadKeySize"), p0); + + /// + /// The key ring does not contain a valid default protection key. The data protection system cannot create a new key because auto-generation of keys is disabled. + /// + internal static string KeyRingProvider_NoDefaultKey_AutoGenerateDisabled + { + get => GetString("KeyRingProvider_NoDefaultKey_AutoGenerateDisabled"); + } + + /// + /// The key ring does not contain a valid default protection key. The data protection system cannot create a new key because auto-generation of keys is disabled. + /// + internal static string FormatKeyRingProvider_NoDefaultKey_AutoGenerateDisabled() + => GetString("KeyRingProvider_NoDefaultKey_AutoGenerateDisabled"); + + /// + /// {0} must not be negative + /// + internal static string LifetimeMustNotBeNegative + { + get => GetString("LifetimeMustNotBeNegative"); + } + + /// + /// {0} must not be negative + /// + internal static string FormatLifetimeMustNotBeNegative(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("LifetimeMustNotBeNegative"), p0); + + /// + /// The '{0}' instance could not be found. When an '{1}' instance is set, a corresponding '{0}' instance must also be set. + /// + internal static string XmlKeyManager_IXmlRepositoryNotFound + { + get => GetString("XmlKeyManager_IXmlRepositoryNotFound"); + } + + /// + /// The '{0}' instance could not be found. When an '{1}' instance is set, a corresponding '{0}' instance must also be set. + /// + internal static string FormatXmlKeyManager_IXmlRepositoryNotFound(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("XmlKeyManager_IXmlRepositoryNotFound"), p0, p1); + + /// + /// Storing keys in a directory '{path}' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. + /// + internal static string FileSystem_EphemeralKeysLocationInContainer + { + get => GetString("FileSystem_EphemeralKeysLocationInContainer"); + } + + /// + /// Storing keys in a directory '{path}' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. + /// + internal static string FormatFileSystem_EphemeralKeysLocationInContainer(object path) + => string.Format(CultureInfo.CurrentCulture, GetString("FileSystem_EphemeralKeysLocationInContainer", "path"), path); + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/RegistryPolicy.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/RegistryPolicy.cs new file mode 100644 index 0000000000..5617ce78f6 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/RegistryPolicy.cs @@ -0,0 +1,28 @@ +// 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.Collections.Generic; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal class RegistryPolicy + { + public RegistryPolicy( + AlgorithmConfiguration configuration, + IEnumerable keyEscrowSinks, + int? defaultKeyLifetime) + { + EncryptorConfiguration = configuration; + KeyEscrowSinks = keyEscrowSinks; + DefaultKeyLifetime = defaultKeyLifetime; + } + + public AlgorithmConfiguration EncryptorConfiguration { get; } + + public IEnumerable KeyEscrowSinks { get; } + + public int? DefaultKeyLifetime { get; } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/RegistryPolicyResolver.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/RegistryPolicyResolver.cs new file mode 100644 index 0000000000..d3357fa34d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/RegistryPolicyResolver.cs @@ -0,0 +1,140 @@ +// 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.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Win32; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// A type which allows reading policy from the system registry. + /// + internal sealed class RegistryPolicyResolver: IRegistryPolicyResolver + { + private readonly Func _getPolicyRegKey; + private readonly IActivator _activator; + + public RegistryPolicyResolver(IActivator activator) + { + _getPolicyRegKey = () => Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\DotNetPackages\Microsoft.AspNetCore.DataProtection"); + _activator = activator; + } + + internal RegistryPolicyResolver(RegistryKey policyRegKey, IActivator activator) + { + _getPolicyRegKey = () => policyRegKey; + _activator = activator; + } + + // populates an options object from values stored in the registry + private static void PopulateOptions(object options, RegistryKey key) + { + foreach (PropertyInfo propInfo in options.GetType().GetProperties()) + { + if (propInfo.IsDefined(typeof(ApplyPolicyAttribute))) + { + var valueFromRegistry = key.GetValue(propInfo.Name); + if (valueFromRegistry != null) + { + if (propInfo.PropertyType == typeof(string)) + { + propInfo.SetValue(options, Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)); + } + else if (propInfo.PropertyType == typeof(int)) + { + propInfo.SetValue(options, Convert.ToInt32(valueFromRegistry, CultureInfo.InvariantCulture)); + } + else if (propInfo.PropertyType == typeof(Type)) + { + propInfo.SetValue(options, Type.GetType(Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture), throwOnError: true)); + } + else + { + throw CryptoUtil.Fail("Unexpected type on property: " + propInfo.Name); + } + } + } + } + } + + private static List ReadKeyEscrowSinks(RegistryKey key) + { + var sinks = new List(); + + // The format of this key is "type1; type2; ...". + // We call Type.GetType to perform an eager check that the type exists. + var sinksFromRegistry = (string)key.GetValue("KeyEscrowSinks"); + if (sinksFromRegistry != null) + { + foreach (string sinkFromRegistry in sinksFromRegistry.Split(';')) + { + var candidate = sinkFromRegistry.Trim(); + if (!String.IsNullOrEmpty(candidate)) + { + typeof(IKeyEscrowSink).AssertIsAssignableFrom(Type.GetType(candidate, throwOnError: true)); + sinks.Add(candidate); + } + } + } + + return sinks; + } + + public RegistryPolicy ResolvePolicy() + { + using (var registryKey = _getPolicyRegKey()) + { + return ResolvePolicyCore(registryKey); // fully evaluate enumeration while the reg key is open + } + } + + private RegistryPolicy ResolvePolicyCore(RegistryKey policyRegKey) + { + if (policyRegKey == null) + { + return null; + } + + // Read the encryption options type: CNG-CBC, CNG-GCM, Managed + AlgorithmConfiguration configuration = null; + + var encryptionType = (string)policyRegKey.GetValue("EncryptionType"); + if (String.Equals(encryptionType, "CNG-CBC", StringComparison.OrdinalIgnoreCase)) + { + configuration = new CngCbcAuthenticatedEncryptorConfiguration(); + } + else if (String.Equals(encryptionType, "CNG-GCM", StringComparison.OrdinalIgnoreCase)) + { + configuration = new CngGcmAuthenticatedEncryptorConfiguration(); + } + else if (String.Equals(encryptionType, "Managed", StringComparison.OrdinalIgnoreCase)) + { + configuration = new ManagedAuthenticatedEncryptorConfiguration(); + } + else if (!String.IsNullOrEmpty(encryptionType)) + { + throw CryptoUtil.Fail("Unrecognized EncryptionType: " + encryptionType); + } + if (configuration != null) + { + PopulateOptions(configuration, policyRegKey); + } + + // Read ancillary data + + var defaultKeyLifetime = (int?)policyRegKey.GetValue("DefaultKeyLifetime"); + + var keyEscrowSinks = ReadKeyEscrowSinks(policyRegKey).Select(item => _activator.CreateInstance(item)); + + return new RegistryPolicy(configuration, keyEscrowSinks, defaultKeyLifetime); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/DefaultKeyStorageDirectories.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/DefaultKeyStorageDirectories.cs new file mode 100644 index 0000000000..a0717263fb --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/DefaultKeyStorageDirectories.cs @@ -0,0 +1,112 @@ +// 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.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.AspNetCore.DataProtection.Repositories +{ + internal sealed class DefaultKeyStorageDirectories : IDefaultKeyStorageDirectories + { + private static readonly Lazy _defaultDirectoryLazy = new Lazy(GetKeyStorageDirectoryImpl); + + private DefaultKeyStorageDirectories() + { + } + + public static IDefaultKeyStorageDirectories Instance { get; } = new DefaultKeyStorageDirectories(); + + /// + /// The default key storage directory. + /// On Windows, this currently corresponds to "Environment.SpecialFolder.LocalApplication/ASP.NET/DataProtection-Keys". + /// On Linux and macOS, this currently corresponds to "$HOME/.aspnet/DataProtection-Keys". + /// + /// + /// This property can return null if no suitable default key storage directory can + /// be found, such as the case when the user profile is unavailable. + /// + public DirectoryInfo GetKeyStorageDirectory() => _defaultDirectoryLazy.Value; + + private static DirectoryInfo GetKeyStorageDirectoryImpl() + { + DirectoryInfo retVal; + + // Environment.GetFolderPath returns null if the user profile isn't loaded. + var localAppDataFromSystemPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + var localAppDataFromEnvPath = Environment.GetEnvironmentVariable("LOCALAPPDATA"); + var userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE"); + var homePath = Environment.GetEnvironmentVariable("HOME"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !string.IsNullOrEmpty(localAppDataFromSystemPath)) + { + // To preserve backwards-compatibility with 1.x, Environment.SpecialFolder.LocalApplicationData + // cannot take precedence over $LOCALAPPDATA and $HOME/.aspnet on non-Windows platforms + retVal = GetKeyStorageDirectoryFromBaseAppDataPath(localAppDataFromSystemPath); + } + else if (localAppDataFromEnvPath != null) + { + retVal = GetKeyStorageDirectoryFromBaseAppDataPath(localAppDataFromEnvPath); + } + else if (userProfilePath != null) + { + retVal = GetKeyStorageDirectoryFromBaseAppDataPath(Path.Combine(userProfilePath, "AppData", "Local")); + } + else if (homePath != null) + { + // If LOCALAPPDATA and USERPROFILE are not present but HOME is, + // it's a good guess that this is a *NIX machine. Use *NIX conventions for a folder name. + retVal = new DirectoryInfo(Path.Combine(homePath, ".aspnet", DataProtectionKeysFolderName)); + } + else if (!string.IsNullOrEmpty(localAppDataFromSystemPath)) + { + // Starting in 2.x, non-Windows platforms may use Environment.SpecialFolder.LocalApplicationData + // but only after checking for $LOCALAPPDATA, $USERPROFILE, and $HOME. + retVal = GetKeyStorageDirectoryFromBaseAppDataPath(localAppDataFromSystemPath); + } + else + { + return null; + } + + Debug.Assert(retVal != null); + + try + { + retVal.Create(); // throws if we don't have access, e.g., user profile not loaded + return retVal; + } + catch + { + return null; + } + } + + public DirectoryInfo GetKeyStorageDirectoryForAzureWebSites() + { + // Azure Web Sites needs to be treated specially, as we need to store the keys in a + // correct persisted location. We use the existence of the %WEBSITE_INSTANCE_ID% env + // variable to determine if we're running in this environment, and if so we then use + // the %HOME% variable to build up our base key storage path. + if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID"))) + { + var homeEnvVar = Environment.GetEnvironmentVariable("HOME"); + if (!String.IsNullOrEmpty(homeEnvVar)) + { + return GetKeyStorageDirectoryFromBaseAppDataPath(homeEnvVar); + } + } + + // nope + return null; + } + + private const string DataProtectionKeysFolderName = "DataProtection-Keys"; + + private static DirectoryInfo GetKeyStorageDirectoryFromBaseAppDataPath(string basePath) + { + return new DirectoryInfo(Path.Combine(basePath, "ASP.NET", DataProtectionKeysFolderName)); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/EphemeralXmlRepository.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/EphemeralXmlRepository.cs new file mode 100644 index 0000000000..17c7156b8d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/EphemeralXmlRepository.cs @@ -0,0 +1,60 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.Repositories +{ + /// + /// An ephemeral XML repository backed by process memory. This class must not be used for + /// anything other than dev scenarios as the keys will not be persisted to storage. + /// + internal class EphemeralXmlRepository : IXmlRepository + { + private readonly List _storedElements = new List(); + + public EphemeralXmlRepository(ILoggerFactory loggerFactory) + { + var logger = loggerFactory.CreateLogger(); + logger.UsingInmemoryRepository(); + } + + public virtual IReadOnlyCollection GetAllElements() + { + // force complete enumeration under lock for thread safety + lock (_storedElements) + { + return GetAllElementsCore().ToList().AsReadOnly(); + } + } + + private IEnumerable GetAllElementsCore() + { + // this method must be called under lock + foreach (XElement element in _storedElements) + { + yield return new XElement(element); // makes a deep copy so caller doesn't inadvertently modify it + } + } + + public virtual void StoreElement(XElement element, string friendlyName) + { + if (element == null) + { + throw new ArgumentNullException(nameof(element)); + } + + var cloned = new XElement(element); // makes a deep copy so caller doesn't inadvertently modify it + + // under lock for thread safety + lock (_storedElements) + { + _storedElements.Add(cloned); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/FileSystemXmlRepository.cs new file mode 100644 index 0000000000..7ceede33d1 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/FileSystemXmlRepository.cs @@ -0,0 +1,155 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.Repositories +{ + /// + /// An XML repository backed by a file system. + /// + public class FileSystemXmlRepository : IXmlRepository + { + private readonly ILogger _logger; + + /// + /// Creates a with keys stored at the given directory. + /// + /// The directory in which to persist key material. + /// The . + public FileSystemXmlRepository(DirectoryInfo directory, ILoggerFactory loggerFactory) + { + Directory = directory ?? throw new ArgumentNullException(nameof(directory)); + + _logger = loggerFactory.CreateLogger(); + + try + { + if (DockerUtils.IsDocker && !DockerUtils.IsVolumeMountedFolder(Directory)) + { + // warn users that keys may be lost when running in docker without a volume mounted folder + _logger.UsingEphemeralFileSystemLocationInContainer(Directory.FullName); + } + } + catch (Exception ex) + { + // Treat exceptions as non-fatal when attempting to detect docker. + // These might occur if fstab is an unrecognized format, or if there are other unusual + // file IO errors. + _logger.LogTrace(ex, "Failure occurred while attempting to detect docker."); + } + } + + /// + /// The default key storage directory. + /// On Windows, this currently corresponds to "Environment.SpecialFolder.LocalApplication/ASP.NET/DataProtection-Keys". + /// On Linux and macOS, this currently corresponds to "$HOME/.aspnet/DataProtection-Keys". + /// + /// + /// This property can return null if no suitable default key storage directory can + /// be found, such as the case when the user profile is unavailable. + /// + public static DirectoryInfo DefaultKeyStorageDirectory => DefaultKeyStorageDirectories.Instance.GetKeyStorageDirectory(); + + /// + /// The directory into which key material will be written. + /// + public DirectoryInfo Directory { get; } + + public virtual IReadOnlyCollection GetAllElements() + { + // forces complete enumeration + return GetAllElementsCore().ToList().AsReadOnly(); + } + + private IEnumerable GetAllElementsCore() + { + Directory.Create(); // won't throw if the directory already exists + + // Find all files matching the pattern "*.xml". + // Note: Inability to read any file is considered a fatal error (since the file may contain + // revocation information), and we'll fail the entire operation rather than return a partial + // set of elements. If a file contains well-formed XML but its contents are meaningless, we + // won't fail that operation here. The caller is responsible for failing as appropriate given + // that scenario. + foreach (var fileSystemInfo in Directory.EnumerateFileSystemInfos("*.xml", SearchOption.TopDirectoryOnly)) + { + yield return ReadElementFromFile(fileSystemInfo.FullName); + } + } + + private static bool IsSafeFilename(string filename) + { + // Must be non-empty and contain only a-zA-Z0-9, hyphen, and underscore. + return (!String.IsNullOrEmpty(filename) && filename.All(c => + c == '-' + || c == '_' + || ('0' <= c && c <= '9') + || ('A' <= c && c <= 'Z') + || ('a' <= c && c <= 'z'))); + } + + private XElement ReadElementFromFile(string fullPath) + { + _logger.ReadingDataFromFile(fullPath); + + using (var fileStream = File.OpenRead(fullPath)) + { + return XElement.Load(fileStream); + } + } + + public virtual void StoreElement(XElement element, string friendlyName) + { + if (element == null) + { + throw new ArgumentNullException(nameof(element)); + } + + if (!IsSafeFilename(friendlyName)) + { + var newFriendlyName = Guid.NewGuid().ToString(); + _logger.NameIsNotSafeFileName(friendlyName, newFriendlyName); + friendlyName = newFriendlyName; + } + + StoreElementCore(element, friendlyName); + } + + private void StoreElementCore(XElement element, string filename) + { + // We're first going to write the file to a temporary location. This way, another consumer + // won't try reading the file in the middle of us writing it. Additionally, if our process + // crashes mid-write, we won't end up with a corrupt .xml file. + + Directory.Create(); // won't throw if the directory already exists + var tempFilename = Path.Combine(Directory.FullName, Guid.NewGuid().ToString() + ".tmp"); + var finalFilename = Path.Combine(Directory.FullName, filename + ".xml"); + + try + { + using (var tempFileStream = File.OpenWrite(tempFilename)) + { + element.Save(tempFileStream); + } + + // Once the file has been fully written, perform the rename. + // Renames are atomic operations on the file systems we support. + _logger.WritingDataToFile(finalFilename); + + // Use File.Copy because File.Move on NFS shares has issues in .NET Core 2.0 + File.Copy(tempFilename, finalFilename); + } + finally + { + File.Delete(tempFilename); // won't throw if the file doesn't exist + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/IDefaultKeyStorageDirectory.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/IDefaultKeyStorageDirectory.cs new file mode 100644 index 0000000000..e7e1410e79 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/IDefaultKeyStorageDirectory.cs @@ -0,0 +1,17 @@ +// 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.IO; + +namespace Microsoft.AspNetCore.DataProtection.Repositories +{ + /// + /// This interface enables overridding the default storage location of keys on disk + /// + internal interface IDefaultKeyStorageDirectories + { + DirectoryInfo GetKeyStorageDirectory(); + + DirectoryInfo GetKeyStorageDirectoryForAzureWebSites(); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/IXmlRepository.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/IXmlRepository.cs new file mode 100644 index 0000000000..d62422d55e --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/IXmlRepository.cs @@ -0,0 +1,37 @@ +// 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.Collections.Generic; +using System.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.Repositories +{ + /// + /// The basic interface for storing and retrieving XML elements. + /// + public interface IXmlRepository + { + /// + /// Gets all top-level XML elements in the repository. + /// + /// + /// All top-level elements in the repository. + /// + IReadOnlyCollection GetAllElements(); + + /// + /// Adds a top-level XML element to the repository. + /// + /// The element to add. + /// An optional name to be associated with the XML element. + /// For instance, if this repository stores XML files on disk, the friendly name may + /// be used as part of the file name. Repository implementations are not required to + /// observe this parameter even if it has been provided by the caller. + /// + /// The 'friendlyName' parameter must be unique if specified. For instance, it could + /// be the id of the key being stored. + /// + void StoreElement(XElement element, string friendlyName); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/RegistryXmlRepository.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/RegistryXmlRepository.cs new file mode 100644 index 0000000000..7692d1ccb5 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Repositories/RegistryXmlRepository.cs @@ -0,0 +1,160 @@ +// 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.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Security.Principal; +using System.Xml.Linq; +using Microsoft.Extensions.Logging; +using Microsoft.Win32; + +namespace Microsoft.AspNetCore.DataProtection.Repositories +{ + /// + /// An XML repository backed by the Windows registry. + /// + public class RegistryXmlRepository : IXmlRepository + { + private static readonly Lazy _defaultRegistryKeyLazy = new Lazy(GetDefaultHklmStorageKey); + + private readonly ILogger _logger; + + /// + /// Creates a with keys stored in the given registry key. + /// + /// The registry key in which to persist key material. + /// The . + public RegistryXmlRepository(RegistryKey registryKey, ILoggerFactory loggerFactory) + { + if (registryKey == null) + { + throw new ArgumentNullException(nameof(registryKey)); + } + + RegistryKey = registryKey; + _logger = loggerFactory.CreateLogger(); + } + + /// + /// The default key storage directory, which currently corresponds to + /// "HKLM\SOFTWARE\Microsoft\ASP.NET\4.0.30319.0\AutoGenKeys\{SID}". + /// + /// + /// This property can return null if no suitable default registry key can + /// be found, such as the case when this application is not hosted inside IIS. + /// + public static RegistryKey DefaultRegistryKey => _defaultRegistryKeyLazy.Value; + + /// + /// The registry key into which key material will be written. + /// + public RegistryKey RegistryKey { get; } + + public virtual IReadOnlyCollection GetAllElements() + { + // forces complete enumeration + return GetAllElementsCore().ToList().AsReadOnly(); + } + + private IEnumerable GetAllElementsCore() + { + // Note: Inability to parse any value is considered a fatal error (since the value may contain + // revocation information), and we'll fail the entire operation rather than return a partial + // set of elements. If a file contains well-formed XML but its contents are meaningless, we + // won't fail that operation here. The caller is responsible for failing as appropriate given + // that scenario. + + foreach (string valueName in RegistryKey.GetValueNames()) + { + var element = ReadElementFromRegKey(RegistryKey, valueName); + if (element != null) + { + yield return element; + } + } + } + + private static RegistryKey GetDefaultHklmStorageKey() + { + try + { + var registryView = IntPtr.Size == 4 ? RegistryView.Registry32 : RegistryView.Registry64; + // Try reading the auto-generated machine key from HKLM + using (var hklmBaseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView)) + { + // Even though this is in HKLM, WAS ensures that applications hosted in IIS are properly isolated. + // See APP_POOL::EnsureSharedMachineKeyStorage in WAS source for more info. + // The version number will need to change if IIS hosts Core CLR directly. + var aspnetAutoGenKeysBaseKeyName = string.Format( + CultureInfo.InvariantCulture, + @"SOFTWARE\Microsoft\ASP.NET\4.0.30319.0\AutoGenKeys\{0}", + WindowsIdentity.GetCurrent().User.Value); + + var aspnetBaseKey = hklmBaseKey.OpenSubKey(aspnetAutoGenKeysBaseKeyName, writable: true); + if (aspnetBaseKey != null) + { + using (aspnetBaseKey) + { + // We'll create a 'DataProtection' subkey under the auto-gen keys base + return aspnetBaseKey.OpenSubKey("DataProtection", writable: true) + ?? aspnetBaseKey.CreateSubKey("DataProtection"); + } + } + return null; // couldn't find the auto-generated machine key + } + } + catch + { + // swallow all errors; they're not fatal + return null; + } + } + + private static bool IsSafeRegistryValueName(string filename) + { + // Must be non-empty and contain only a-zA-Z0-9, hyphen, and underscore. + return (!String.IsNullOrEmpty(filename) && filename.All(c => + c == '-' + || c == '_' + || ('0' <= c && c <= '9') + || ('A' <= c && c <= 'Z') + || ('a' <= c && c <= 'z'))); + } + + private XElement ReadElementFromRegKey(RegistryKey regKey, string valueName) + { + _logger.ReadingDataFromRegistryKeyValue(regKey, valueName); + + var data = regKey.GetValue(valueName) as string; + return (!String.IsNullOrEmpty(data)) ? XElement.Parse(data) : null; + } + + public virtual void StoreElement(XElement element, string friendlyName) + { + if (element == null) + { + throw new ArgumentNullException(nameof(element)); + } + + if (!IsSafeRegistryValueName(friendlyName)) + { + var newFriendlyName = Guid.NewGuid().ToString(); + _logger.NameIsNotSafeRegistryValueName(friendlyName, newFriendlyName); + friendlyName = newFriendlyName; + } + + StoreElementCore(element, friendlyName); + } + + private void StoreElementCore(XElement element, string valueName) + { + // Technically calls to RegSetValue* and RegGetValue* are atomic, so we don't have to worry about + // another thread trying to read this value while we're writing it. There's still a small risk of + // data corruption if power is lost while the registry file is being flushed to the file system, + // but the window for that should be small enough that we shouldn't have to worry about it. + RegistryKey.SetValue(valueName, element.ToString(), RegistryValueKind.String); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Resources.resx b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Resources.resx new file mode 100644 index 0000000000..9540aa54fa --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Resources.resx @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + An error occurred during a cryptographic operation. + + + The provided buffer is of length {0} byte(s). It must instead be exactly {1} byte(s) in length. + + + The payload was invalid. + + + Property {0} cannot be null or empty. + + + The provided payload could not be decrypted. Refer to the inner exception for more information. + + + An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information. + + + The key {0:B} was not found in the key ring. + + + The key {0:B} has been revoked. + + + The provided payload cannot be decrypted because it was not protected with this protection provider. + + + The provided payload cannot be decrypted because it was protected with a newer version of the protection provider. + + + Value must be non-negative. + + + The type '{1}' is not assignable to '{0}'. + + + The new key lifetime must be at least one week. + + + The key {0:B} already exists in the keyring. + + + Argument cannot be null or empty. + + + Property {0} must have a non-negative value. + + + GCM algorithms require the Windows platform. + + + A certificate with the thumbprint '{0}' could not be found. + + + Decrypting EncryptedXml-encapsulated payloads is not yet supported on Core CLR. + + + The symmetric algorithm block size of {0} bits is invalid. The block size must be between 64 and 2048 bits, inclusive, and it must be a multiple of 8 bits. + + + The validation algorithm digest size of {0} bits is invalid. The digest size must be between 128 and 2048 bits, inclusive, and it must be a multiple of 8 bits. + + + The symmetric algorithm key size of {0} bits is invalid. The key size must be between 128 and 2048 bits, inclusive, and it must be a multiple of 8 bits. + + + The key ring does not contain a valid default protection key. The data protection system cannot create a new key because auto-generation of keys is disabled. + + + {0} must not be negative + + + The '{0}' instance could not be found. When an '{1}' instance is set, a corresponding '{0}' instance must also be set. + + + Storing keys in a directory '{path}' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. + + \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/ISP800_108_CTR_HMACSHA512Provider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/ISP800_108_CTR_HMACSHA512Provider.cs new file mode 100644 index 0000000000..f7e6aecdb1 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/ISP800_108_CTR_HMACSHA512Provider.cs @@ -0,0 +1,12 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.SP800_108 +{ + internal unsafe interface ISP800_108_CTR_HMACSHA512Provider : IDisposable + { + void DeriveKey(byte* pbLabel, uint cbLabel, byte* pbContext, uint cbContext, byte* pbDerivedKey, uint cbDerivedKey); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/ManagedSP800_108_CTR_HMACSHA512.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/ManagedSP800_108_CTR_HMACSHA512.cs new file mode 100644 index 0000000000..57e8f0472c --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/ManagedSP800_108_CTR_HMACSHA512.cs @@ -0,0 +1,66 @@ +// 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.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.Managed; + +namespace Microsoft.AspNetCore.DataProtection.SP800_108 +{ + internal static class ManagedSP800_108_CTR_HMACSHA512 + { + public static void DeriveKeys(byte[] kdk, ArraySegment label, ArraySegment context, Func prfFactory, ArraySegment output) + { + // make copies so we can mutate these local vars + var outputOffset = output.Offset; + var outputCount = output.Count; + + using (var prf = prfFactory(kdk)) + { + // See SP800-108, Sec. 5.1 for the format of the input to the PRF routine. + var prfInput = new byte[checked(sizeof(uint) /* [i]_2 */ + label.Count + 1 /* 0x00 */ + context.Count + sizeof(uint) /* [K]_2 */)]; + + // Copy [L]_2 to prfInput since it's stable over all iterations + uint outputSizeInBits = (uint)checked((int)outputCount * 8); + prfInput[prfInput.Length - 4] = (byte)(outputSizeInBits >> 24); + prfInput[prfInput.Length - 3] = (byte)(outputSizeInBits >> 16); + prfInput[prfInput.Length - 2] = (byte)(outputSizeInBits >> 8); + prfInput[prfInput.Length - 1] = (byte)(outputSizeInBits); + + // Copy label and context to prfInput since they're stable over all iterations + Buffer.BlockCopy(label.Array, label.Offset, prfInput, sizeof(uint), label.Count); + Buffer.BlockCopy(context.Array, context.Offset, prfInput, sizeof(int) + label.Count + 1, context.Count); + + var prfOutputSizeInBytes = prf.GetDigestSizeInBytes(); + for (uint i = 1; outputCount > 0; i++) + { + // Copy [i]_2 to prfInput since it mutates with each iteration + prfInput[0] = (byte)(i >> 24); + prfInput[1] = (byte)(i >> 16); + prfInput[2] = (byte)(i >> 8); + prfInput[3] = (byte)(i); + + // Run the PRF and copy the results to the output buffer + var prfOutput = prf.ComputeHash(prfInput); + CryptoUtil.Assert(prfOutputSizeInBytes == prfOutput.Length, "prfOutputSizeInBytes == prfOutput.Length"); + var numBytesToCopyThisIteration = Math.Min(prfOutputSizeInBytes, outputCount); + Buffer.BlockCopy(prfOutput, 0, output.Array, outputOffset, numBytesToCopyThisIteration); + Array.Clear(prfOutput, 0, prfOutput.Length); // contains key material, so delete it + + // adjust offsets + outputOffset += numBytesToCopyThisIteration; + outputCount -= numBytesToCopyThisIteration; + } + } + } + + public static void DeriveKeysWithContextHeader(byte[] kdk, ArraySegment label, byte[] contextHeader, ArraySegment context, Func prfFactory, ArraySegment output) + { + var combinedContext = new byte[checked(contextHeader.Length + context.Count)]; + Buffer.BlockCopy(contextHeader, 0, combinedContext, 0, contextHeader.Length); + Buffer.BlockCopy(context.Array, context.Offset, combinedContext, contextHeader.Length, context.Count); + DeriveKeys(kdk, label, new ArraySegment(combinedContext), prfFactory, output); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Extensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Extensions.cs new file mode 100644 index 0000000000..adb084a0c9 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Extensions.cs @@ -0,0 +1,37 @@ +// 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 Microsoft.AspNetCore.Cryptography; + +namespace Microsoft.AspNetCore.DataProtection.SP800_108 +{ + internal unsafe static class SP800_108_CTR_HMACSHA512Extensions + { + public static void DeriveKeyWithContextHeader(this ISP800_108_CTR_HMACSHA512Provider provider, byte* pbLabel, uint cbLabel, byte[] contextHeader, byte* pbContext, uint cbContext, byte* pbDerivedKey, uint cbDerivedKey) + { + var cbCombinedContext = checked((uint)contextHeader.Length + cbContext); + + // Try allocating the combined context on the stack to avoid temporary managed objects; only fall back to heap if buffers are too large. + byte[] heapAllocatedCombinedContext = (cbCombinedContext > Constants.MAX_STACKALLOC_BYTES) ? new byte[cbCombinedContext] : null; + fixed (byte* pbHeapAllocatedCombinedContext = heapAllocatedCombinedContext) + { + byte* pbCombinedContext = pbHeapAllocatedCombinedContext; + if (pbCombinedContext == null) + { + byte* pbStackAllocatedCombinedContext = stackalloc byte[(int)cbCombinedContext]; // will be released when frame pops + pbCombinedContext = pbStackAllocatedCombinedContext; + } + + fixed (byte* pbContextHeader = contextHeader) + { + UnsafeBufferUtil.BlockCopy(from: pbContextHeader, to: pbCombinedContext, byteCount: contextHeader.Length); + } + UnsafeBufferUtil.BlockCopy(from: pbContext, to: &pbCombinedContext[contextHeader.Length], byteCount: cbContext); + + // At this point, combinedContext := { contextHeader || context } + provider.DeriveKey(pbLabel, cbLabel, pbCombinedContext, cbCombinedContext, pbDerivedKey, cbDerivedKey); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Util.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Util.cs new file mode 100644 index 0000000000..c28af6f0a3 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Util.cs @@ -0,0 +1,64 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; + +namespace Microsoft.AspNetCore.DataProtection.SP800_108 +{ + /// + /// Provides an implementation of the SP800-108-CTR-HMACSHA512 key derivation function. + /// This class assumes at least Windows 7 / Server 2008 R2. + /// + /// + /// More info at http://csrc.nist.gov/publications/nistpubs/800-108/sp800-108.pdf, Sec. 5.1. + /// + internal unsafe static class SP800_108_CTR_HMACSHA512Util + { + // Creates a provider with an empty key. + public static ISP800_108_CTR_HMACSHA512Provider CreateEmptyProvider() + { + byte dummy; + return CreateProvider(pbKdk: &dummy, cbKdk: 0); + } + + // Creates a provider from the given key. + public static ISP800_108_CTR_HMACSHA512Provider CreateProvider(byte* pbKdk, uint cbKdk) + { + if (OSVersionUtil.IsWindows8OrLater()) + { + return new Win8SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk); + } + else + { + return new Win7SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk); + } + } + + // Creates a provider from the given secret. + public static ISP800_108_CTR_HMACSHA512Provider CreateProvider(Secret kdk) + { + var secretLengthInBytes = checked((uint)kdk.Length); + if (secretLengthInBytes == 0) + { + return CreateEmptyProvider(); + } + else + { + fixed (byte* pbPlaintextSecret = new byte[secretLengthInBytes]) + { + try + { + kdk.WriteSecretIntoBuffer(pbPlaintextSecret, checked((int)secretLengthInBytes)); + return CreateProvider(pbPlaintextSecret, secretLengthInBytes); + } + finally + { + UnsafeBufferUtil.SecureZeroMemory(pbPlaintextSecret, secretLengthInBytes); + } + } + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/Win7SP800_108_CTR_HMACSHA512Provider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/Win7SP800_108_CTR_HMACSHA512Provider.cs new file mode 100644 index 0000000000..a2143ff872 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/Win7SP800_108_CTR_HMACSHA512Provider.cs @@ -0,0 +1,80 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; + +namespace Microsoft.AspNetCore.DataProtection.SP800_108 +{ + internal unsafe sealed class Win7SP800_108_CTR_HMACSHA512Provider : ISP800_108_CTR_HMACSHA512Provider + { + private readonly BCryptHashHandle _hashHandle; + + public Win7SP800_108_CTR_HMACSHA512Provider(byte* pbKdk, uint cbKdk) + { + _hashHandle = CachedAlgorithmHandles.HMAC_SHA512.CreateHmac(pbKdk, cbKdk); + } + + public void DeriveKey(byte* pbLabel, uint cbLabel, byte* pbContext, uint cbContext, byte* pbDerivedKey, uint cbDerivedKey) + { + const uint SHA512_DIGEST_SIZE_IN_BYTES = 512 / 8; + byte* pbHashDigest = stackalloc byte[(int)SHA512_DIGEST_SIZE_IN_BYTES]; + + // NOTE: pbDerivedKey and cbDerivedKey are modified as data is copied to the output buffer. + + // this will be zero-inited + var tempInputBuffer = new byte[checked( + sizeof(int) /* [i] */ + + cbLabel /* Label */ + + 1 /* 0x00 */ + + cbContext /* Context */ + + sizeof(int) /* [L] */)]; + + fixed (byte* pbTempInputBuffer = tempInputBuffer) + { + // Step 1: Calculate all necessary offsets into the temp input & output buffer. + byte* pbTempInputCounter = pbTempInputBuffer; + byte* pbTempInputLabel = &pbTempInputCounter[sizeof(int)]; + byte* pbTempInputContext = &pbTempInputLabel[cbLabel + 1 /* 0x00 */]; + byte* pbTempInputBitlengthIndicator = &pbTempInputContext[cbContext]; + + // Step 2: Copy Label and Context into the temp input buffer. + UnsafeBufferUtil.BlockCopy(from: pbLabel, to: pbTempInputLabel, byteCount: cbLabel); + UnsafeBufferUtil.BlockCopy(from: pbContext, to: pbTempInputContext, byteCount: cbContext); + + // Step 3: copy [L] into last part of data to be hashed, big-endian + BitHelpers.WriteTo(pbTempInputBitlengthIndicator, checked(cbDerivedKey * 8)); + + // Step 4: iterate until all desired bytes have been generated + for (uint i = 1; cbDerivedKey > 0; i++) + { + // Step 4a: Copy [i] into the first part of data to be hashed, big-endian + BitHelpers.WriteTo(pbTempInputCounter, i); + + // Step 4b: Hash. Win7 doesn't allow reusing hash algorithm objects after the final hash + // has been computed, so we'll just keep calling DuplicateHash on the original + // hash handle. This offers a slight performance increase over allocating a new hash + // handle for each iteration. We don't need to mess with any of this on Win8 since on + // that platform we use BCryptKeyDerivation directly, which offers superior performance. + using (var hashHandle = _hashHandle.DuplicateHash()) + { + hashHandle.HashData(pbTempInputBuffer, (uint)tempInputBuffer.Length, pbHashDigest, SHA512_DIGEST_SIZE_IN_BYTES); + } + + // Step 4c: Copy bytes from the temporary buffer to the output buffer. + uint numBytesToCopy = Math.Min(cbDerivedKey, SHA512_DIGEST_SIZE_IN_BYTES); + UnsafeBufferUtil.BlockCopy(from: pbHashDigest, to: pbDerivedKey, byteCount: numBytesToCopy); + pbDerivedKey += numBytesToCopy; + cbDerivedKey -= numBytesToCopy; + } + } + } + + public void Dispose() + { + _hashHandle.Dispose(); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/Win8SP800_108_CTR_HMACSHA512Provider.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/Win8SP800_108_CTR_HMACSHA512Provider.cs new file mode 100644 index 0000000000..be7fe7c917 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SP800_108/Win8SP800_108_CTR_HMACSHA512Provider.cs @@ -0,0 +1,108 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; + +namespace Microsoft.AspNetCore.DataProtection.SP800_108 +{ + internal unsafe sealed class Win8SP800_108_CTR_HMACSHA512Provider : ISP800_108_CTR_HMACSHA512Provider + { + private readonly BCryptKeyHandle _keyHandle; + + public Win8SP800_108_CTR_HMACSHA512Provider(byte* pbKdk, uint cbKdk) + { + _keyHandle = ImportKey(pbKdk, cbKdk); + } + + public void DeriveKey(byte* pbLabel, uint cbLabel, byte* pbContext, uint cbContext, byte* pbDerivedKey, uint cbDerivedKey) + { + const int SHA512_ALG_CHAR_COUNT = 7; + char* pszHashAlgorithm = stackalloc char[SHA512_ALG_CHAR_COUNT /* includes terminating null */]; + pszHashAlgorithm[0] = 'S'; + pszHashAlgorithm[1] = 'H'; + pszHashAlgorithm[2] = 'A'; + pszHashAlgorithm[3] = '5'; + pszHashAlgorithm[4] = '1'; + pszHashAlgorithm[5] = '2'; + pszHashAlgorithm[6] = (char)0; + + // First, build the buffers necessary to pass (label, context, PRF algorithm) into the KDF + BCryptBuffer* pBuffers = stackalloc BCryptBuffer[3]; + + pBuffers[0].BufferType = BCryptKeyDerivationBufferType.KDF_LABEL; + pBuffers[0].pvBuffer = (IntPtr)pbLabel; + pBuffers[0].cbBuffer = cbLabel; + + pBuffers[1].BufferType = BCryptKeyDerivationBufferType.KDF_CONTEXT; + pBuffers[1].pvBuffer = (IntPtr)pbContext; + pBuffers[1].cbBuffer = cbContext; + + pBuffers[2].BufferType = BCryptKeyDerivationBufferType.KDF_HASH_ALGORITHM; + pBuffers[2].pvBuffer = (IntPtr)pszHashAlgorithm; + pBuffers[2].cbBuffer = checked(SHA512_ALG_CHAR_COUNT * sizeof(char)); + + // Add the header which points to the buffers + var bufferDesc = default(BCryptBufferDesc); + BCryptBufferDesc.Initialize(ref bufferDesc); + bufferDesc.cBuffers = 3; + bufferDesc.pBuffers = pBuffers; + + // Finally, invoke the KDF + uint numBytesDerived; + var ntstatus = UnsafeNativeMethods.BCryptKeyDerivation( + hKey: _keyHandle, + pParameterList: &bufferDesc, + pbDerivedKey: pbDerivedKey, + cbDerivedKey: cbDerivedKey, + pcbResult: out numBytesDerived, + dwFlags: 0); + UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); + + // Final sanity checks before returning control to caller. + CryptoUtil.Assert(numBytesDerived == cbDerivedKey, "numBytesDerived == cbDerivedKey"); + } + + public void Dispose() + { + _keyHandle.Dispose(); + } + + private static BCryptKeyHandle ImportKey(byte* pbKdk, uint cbKdk) + { + // The MS implementation of SP800_108_CTR_HMAC has a limit on the size of the key it can accept. + // If the incoming key is too long, we'll hash it using SHA512 to bring it back to a manageable + // length. This transform is appropriate since SP800_108_CTR_HMAC is just a glorified HMAC under + // the covers, and the HMAC algorithm allows hashing the key using the underlying PRF if the key + // is greater than the PRF's block length. + + const uint SHA512_BLOCK_SIZE_IN_BYTES = 1024 / 8; + const uint SHA512_DIGEST_SIZE_IN_BYTES = 512 / 8; + + if (cbKdk > SHA512_BLOCK_SIZE_IN_BYTES) + { + // Hash key. + byte* pbHashedKey = stackalloc byte[(int)SHA512_DIGEST_SIZE_IN_BYTES]; + try + { + using (var hashHandle = CachedAlgorithmHandles.SHA512.CreateHash()) + { + hashHandle.HashData(pbKdk, cbKdk, pbHashedKey, SHA512_DIGEST_SIZE_IN_BYTES); + } + return CachedAlgorithmHandles.SP800_108_CTR_HMAC.GenerateSymmetricKey(pbHashedKey, SHA512_DIGEST_SIZE_IN_BYTES); + } + finally + { + UnsafeBufferUtil.SecureZeroMemory(pbHashedKey, SHA512_DIGEST_SIZE_IN_BYTES); + } + } + else + { + // Use key directly. + return CachedAlgorithmHandles.SP800_108_CTR_HMAC.GenerateSymmetricKey(pbKdk, cbKdk); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Secret.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Secret.cs new file mode 100644 index 0000000000..05c1c212bd --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/Secret.cs @@ -0,0 +1,284 @@ +// 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 Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Microsoft.AspNetCore.DataProtection.Managed; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Represents a secret value stored in memory. + /// + public unsafe sealed class Secret : IDisposable, ISecret + { + // from wincrypt.h + private const uint CRYPTPROTECTMEMORY_BLOCK_SIZE = 16; + + private readonly SecureLocalAllocHandle _localAllocHandle; + private readonly uint _plaintextLength; + + /// + /// Creates a new Secret from the provided input value, where the input value + /// is specified as an array segment. + /// + public Secret(ArraySegment value) + { + value.Validate(); + + _localAllocHandle = Protect(value); + _plaintextLength = (uint)value.Count; + } + + /// + /// Creates a new Secret from the provided input value, where the input value + /// is specified as an array. + /// + public Secret(byte[] value) + : this(new ArraySegment(value)) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + } + + /// + /// Creates a new Secret from the provided input value, where the input value + /// is specified as a pointer to unmanaged memory. + /// + public Secret(byte* secret, int secretLength) + { + if (secret == null) + { + throw new ArgumentNullException(nameof(secret)); + } + if (secretLength < 0) + { + throw Error.Common_ValueMustBeNonNegative(nameof(secretLength)); + } + + _localAllocHandle = Protect(secret, (uint)secretLength); + _plaintextLength = (uint)secretLength; + } + + /// + /// Creates a new Secret from another secret object. + /// + public Secret(ISecret secret) + { + if (secret == null) + { + throw new ArgumentNullException(nameof(secret)); + } + + var other = secret as Secret; + if (other != null) + { + // Fast-track: simple deep copy scenario. + this._localAllocHandle = other._localAllocHandle.Duplicate(); + this._plaintextLength = other._plaintextLength; + } + else + { + // Copy the secret to a temporary managed buffer, then protect the buffer. + // We pin the temp buffer and zero it out when we're finished to limit exposure of the secret. + var tempPlaintextBuffer = new byte[secret.Length]; + fixed (byte* pbTempPlaintextBuffer = tempPlaintextBuffer) + { + try + { + secret.WriteSecretIntoBuffer(new ArraySegment(tempPlaintextBuffer)); + _localAllocHandle = Protect(pbTempPlaintextBuffer, (uint)tempPlaintextBuffer.Length); + _plaintextLength = (uint)tempPlaintextBuffer.Length; + } + finally + { + UnsafeBufferUtil.SecureZeroMemory(pbTempPlaintextBuffer, tempPlaintextBuffer.Length); + } + } + } + } + + /// + /// The length (in bytes) of the secret value. + /// + public int Length + { + get + { + return (int)_plaintextLength; // ctor guarantees the length fits into a signed int + } + } + + /// + /// Wipes the secret from memory. + /// + public void Dispose() + { + _localAllocHandle.Dispose(); + } + + private static SecureLocalAllocHandle Protect(ArraySegment plaintext) + { + fixed (byte* pbPlaintextArray = plaintext.Array) + { + return Protect(&pbPlaintextArray[plaintext.Offset], (uint)plaintext.Count); + } + } + + private static SecureLocalAllocHandle Protect(byte* pbPlaintext, uint cbPlaintext) + { + // If we're not running on a platform that supports CryptProtectMemory, + // shove the plaintext directly into a LocalAlloc handle. Ideally we'd + // mark this memory page as non-pageable, but this is fraught with peril. + if (!OSVersionUtil.IsWindows()) + { + var handle = SecureLocalAllocHandle.Allocate((IntPtr)checked((int)cbPlaintext)); + UnsafeBufferUtil.BlockCopy(from: pbPlaintext, to: handle, byteCount: cbPlaintext); + return handle; + } + + // We need to make sure we're a multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE. + var numTotalBytesToAllocate = cbPlaintext; + var numBytesPaddingRequired = CRYPTPROTECTMEMORY_BLOCK_SIZE - (numTotalBytesToAllocate % CRYPTPROTECTMEMORY_BLOCK_SIZE); + if (numBytesPaddingRequired == CRYPTPROTECTMEMORY_BLOCK_SIZE) + { + numBytesPaddingRequired = 0; // we're already a proper multiple of the block size + } + checked { numTotalBytesToAllocate += numBytesPaddingRequired; } + CryptoUtil.Assert(numTotalBytesToAllocate % CRYPTPROTECTMEMORY_BLOCK_SIZE == 0, "numTotalBytesToAllocate % CRYPTPROTECTMEMORY_BLOCK_SIZE == 0"); + + // Allocate and copy plaintext data; padding is uninitialized / undefined. + var encryptedMemoryHandle = SecureLocalAllocHandle.Allocate((IntPtr)numTotalBytesToAllocate); + UnsafeBufferUtil.BlockCopy(from: pbPlaintext, to: encryptedMemoryHandle, byteCount: cbPlaintext); + + // Finally, CryptProtectMemory the whole mess. + if (numTotalBytesToAllocate != 0) + { + MemoryProtection.CryptProtectMemory(encryptedMemoryHandle, byteCount: numTotalBytesToAllocate); + } + return encryptedMemoryHandle; + } + + /// + /// Returns a Secret comprised entirely of random bytes retrieved from + /// a cryptographically secure RNG. + /// + public static Secret Random(int numBytes) + { + if (numBytes < 0) + { + throw Error.Common_ValueMustBeNonNegative(nameof(numBytes)); + } + + if (numBytes == 0) + { + byte dummy; + return new Secret(&dummy, 0); + } + else + { + // Don't use CNG if we're not on Windows. + if (!OSVersionUtil.IsWindows()) + { + return new Secret(ManagedGenRandomImpl.Instance.GenRandom(numBytes)); + } + + var bytes = new byte[numBytes]; + fixed (byte* pbBytes = bytes) + { + try + { + BCryptUtil.GenRandom(pbBytes, (uint)numBytes); + return new Secret(pbBytes, numBytes); + } + finally + { + UnsafeBufferUtil.SecureZeroMemory(pbBytes, numBytes); + } + } + } + } + + private void UnprotectInto(byte* pbBuffer) + { + // If we're not running on a platform that supports CryptProtectMemory, + // the handle contains plaintext bytes. + if (!OSVersionUtil.IsWindows()) + { + UnsafeBufferUtil.BlockCopy(from: _localAllocHandle, to: pbBuffer, byteCount: _plaintextLength); + return; + } + + if (_plaintextLength % CRYPTPROTECTMEMORY_BLOCK_SIZE == 0) + { + // Case 1: Secret length is an exact multiple of the block size. Copy directly to the buffer and decrypt there. + UnsafeBufferUtil.BlockCopy(from: _localAllocHandle, to: pbBuffer, byteCount: _plaintextLength); + MemoryProtection.CryptUnprotectMemory(pbBuffer, _plaintextLength); + } + else + { + // Case 2: Secret length is not a multiple of the block size. We'll need to duplicate the data and + // perform the decryption in the duplicate buffer, then copy the plaintext data over. + using (var duplicateHandle = _localAllocHandle.Duplicate()) + { + MemoryProtection.CryptUnprotectMemory(duplicateHandle, checked((uint)duplicateHandle.Length)); + UnsafeBufferUtil.BlockCopy(from: duplicateHandle, to: pbBuffer, byteCount: _plaintextLength); + } + } + } + + /// + /// Writes the secret value to the specified buffer. + /// + /// + /// The buffer size must exactly match the length of the secret value. + /// + public void WriteSecretIntoBuffer(ArraySegment buffer) + { + // Parameter checking + buffer.Validate(); + if (buffer.Count != Length) + { + throw Error.Common_BufferIncorrectlySized(nameof(buffer), actualSize: buffer.Count, expectedSize: Length); + } + + // only unprotect if the secret is zero-length, as CLR doesn't like pinning zero-length buffers + if (Length != 0) + { + fixed (byte* pbBufferArray = buffer.Array) + { + UnprotectInto(&pbBufferArray[buffer.Offset]); + } + } + } + + /// + /// Writes the secret value to the specified buffer. + /// + /// The buffer into which to write the secret value. + /// The size (in bytes) of the provided buffer. + /// + /// The 'bufferLength' parameter must exactly match the length of the secret value. + /// + public void WriteSecretIntoBuffer(byte* buffer, int bufferLength) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + if (bufferLength != Length) + { + throw Error.Common_BufferIncorrectlySized(nameof(bufferLength), actualSize: bufferLength, expectedSize: Length); + } + + if (Length != 0) + { + UnprotectInto(buffer); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SimpleActivator.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SimpleActivator.cs new file mode 100644 index 0000000000..54eac601bb --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/SimpleActivator.cs @@ -0,0 +1,56 @@ +// 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.Reflection; +using Microsoft.AspNetCore.DataProtection.Internal; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// A simplified default implementation of that understands + /// how to call ctors which take . + /// + internal class SimpleActivator : IActivator + { + /// + /// A default whose wrapped is null. + /// + internal static readonly SimpleActivator DefaultWithoutServices = new SimpleActivator(null); + + private readonly IServiceProvider _services; + + public SimpleActivator(IServiceProvider services) + { + _services = services; + } + + public virtual object CreateInstance(Type expectedBaseType, string implementationTypeName) + { + // Would the assignment even work? + var implementationType = Type.GetType(implementationTypeName, throwOnError: true); + expectedBaseType.AssertIsAssignableFrom(implementationType); + + // If no IServiceProvider was specified, prefer .ctor() [if it exists] + if (_services == null) + { + var ctorParameterless = implementationType.GetConstructor(Type.EmptyTypes); + if (ctorParameterless != null) + { + return Activator.CreateInstance(implementationType); + } + } + + // If an IServiceProvider was specified or if .ctor() doesn't exist, prefer .ctor(IServiceProvider) [if it exists] + var ctorWhichTakesServiceProvider = implementationType.GetConstructor(new Type[] { typeof(IServiceProvider) }); + if (ctorWhichTakesServiceProvider != null) + { + return ctorWhichTakesServiceProvider.Invoke(new[] { _services }); + } + + // Finally, prefer .ctor() as an ultimate fallback. + // This will throw if the ctor cannot be called. + return Activator.CreateInstance(implementationType); + } + } +} \ No newline at end of file diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/TypeExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/TypeExtensions.cs new file mode 100644 index 0000000000..0e35c06a6b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/TypeExtensions.cs @@ -0,0 +1,30 @@ +// 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.Reflection; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Helpful extension methods on . + /// + internal static class TypeExtensions + { + /// + /// Throws if + /// is not assignable to . + /// + public static void AssertIsAssignableFrom(this Type expectedBaseType, Type implementationType) + { + if (!expectedBaseType.IsAssignableFrom(implementationType)) + { + // It might seem a bit weird to throw an InvalidCastException explicitly rather than + // to let the CLR generate one, but searching through NetFX there is indeed precedent + // for this pattern when the caller knows ahead of time the operation will fail. + throw new InvalidCastException(Resources.FormatTypeExtensions_BadCast( + expectedBaseType.AssemblyQualifiedName, implementationType.AssemblyQualifiedName)); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/TypeForwardingActivator.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/TypeForwardingActivator.cs new file mode 100644 index 0000000000..bf3113eada --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/TypeForwardingActivator.cs @@ -0,0 +1,69 @@ +// 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.Text.RegularExpressions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal class TypeForwardingActivator : SimpleActivator + { + private const string OldNamespace = "Microsoft.AspNet.DataProtection"; + private const string CurrentNamespace = "Microsoft.AspNetCore.DataProtection"; + private readonly ILogger _logger; + private static readonly Regex _versionPattern = new Regex(@",\s?Version=[0-9]+(\.[0-9]+){0,3}", RegexOptions.Compiled, TimeSpan.FromSeconds(2)); + + public TypeForwardingActivator(IServiceProvider services) + : this(services, NullLoggerFactory.Instance) + { + } + + public TypeForwardingActivator(IServiceProvider services, ILoggerFactory loggerFactory) + : base(services) + { + _logger = loggerFactory.CreateLogger(typeof(TypeForwardingActivator)); + } + + public override object CreateInstance(Type expectedBaseType, string originalTypeName) + => CreateInstance(expectedBaseType, originalTypeName, out var _); + + // for testing + internal object CreateInstance(Type expectedBaseType, string originalTypeName, out bool forwarded) + { + var forwardedTypeName = originalTypeName; + var candidate = false; + if (originalTypeName.Contains(OldNamespace)) + { + candidate = true; + forwardedTypeName = originalTypeName.Replace(OldNamespace, CurrentNamespace); + } + + if (candidate || forwardedTypeName.StartsWith(CurrentNamespace + ".", StringComparison.Ordinal)) + { + candidate = true; + forwardedTypeName = RemoveVersionFromAssemblyName(forwardedTypeName); + } + + if (candidate) + { + var type = Type.GetType(forwardedTypeName, false); + if (type != null) + { + _logger.LogDebug("Forwarded activator type request from {FromType} to {ToType}", + originalTypeName, + forwardedTypeName); + forwarded = true; + return base.CreateInstance(expectedBaseType, forwardedTypeName); + } + } + + forwarded = false; + return base.CreateInstance(expectedBaseType, originalTypeName); + } + + protected string RemoveVersionFromAssemblyName(string forwardedTypeName) + => _versionPattern.Replace(forwardedTypeName, ""); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlConstants.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlConstants.cs new file mode 100644 index 0000000000..9908e8e138 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlConstants.cs @@ -0,0 +1,39 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Contains XLinq constants. + /// + internal static class XmlConstants + { + /// + /// The root namespace used for all DataProtection-specific XML elements and attributes. + /// + private static readonly XNamespace RootNamespace = XNamespace.Get("http://schemas.asp.net/2015/03/dataProtection"); + + /// + /// Represents the type of decryptor that can be used when reading 'encryptedSecret' elements. + /// + internal static readonly XName DecryptorTypeAttributeName = "decryptorType"; + + /// + /// Elements with this attribute will be read with the specified deserializer type. + /// + internal static readonly XName DeserializerTypeAttributeName = "deserializerType"; + + /// + /// Elements with this name will be automatically decrypted when read by the XML key manager. + /// + internal static readonly XName EncryptedSecretElementName = RootNamespace.GetName("encryptedSecret"); + + /// + /// Elements where this attribute has a value of 'true' should be encrypted before storage. + /// + internal static readonly XName RequiresEncryptionAttributeName = RootNamespace.GetName("requiresEncryption"); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/CertificateResolver.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/CertificateResolver.cs new file mode 100644 index 0000000000..36ff53a6f3 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/CertificateResolver.cs @@ -0,0 +1,63 @@ +// 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.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// A default implementation of that looks in the current user + /// and local machine certificate stores. + /// + public class CertificateResolver : ICertificateResolver + { + /// + /// Locates an given its thumbprint. + /// + /// The thumbprint (as a hex string) of the certificate to resolve. + /// The resolved , or null if the certificate cannot be found. + public virtual X509Certificate2 ResolveCertificate(string thumbprint) + { + if (thumbprint == null) + { + throw new ArgumentNullException(nameof(thumbprint)); + } + + if (String.IsNullOrEmpty(thumbprint)) + { + throw Error.Common_ArgumentCannotBeNullOrEmpty(nameof(thumbprint)); + } + + return GetCertificateFromStore(StoreLocation.CurrentUser, thumbprint) + ?? GetCertificateFromStore(StoreLocation.LocalMachine, thumbprint); + } + + private static X509Certificate2 GetCertificateFromStore(StoreLocation location, string thumbprint) + { + var store = new X509Store(location); + try + { + store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); + var matchingCerts = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, validOnly: true); + return (matchingCerts != null && matchingCerts.Count > 0) + ? matchingCerts[0] + : null; + } + catch (CryptographicException) + { + // Suppress first-chance exceptions when opening the store. + // For example, LocalMachine\My is not supported on Linux yet and will throw on Open(), + // but there isn't a good way to detect this without attempting to open the store. + // See https://github.com/dotnet/corefx/issues/3690. + return null; + } + finally + { + store.Close(); + } + } + } +} + diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/CertificateXmlEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/CertificateXmlEncryptor.cs new file mode 100644 index 0000000000..ee1342df94 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/CertificateXmlEncryptor.cs @@ -0,0 +1,147 @@ +// 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.Security.Cryptography.X509Certificates; +using System.Security.Cryptography.Xml; +using System.Xml; +using System.Xml.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// An that can perform XML encryption by using an X.509 certificate. + /// + public sealed class CertificateXmlEncryptor : IInternalCertificateXmlEncryptor, IXmlEncryptor + { + private readonly Func _certFactory; + private readonly IInternalCertificateXmlEncryptor _encryptor; + private readonly ILogger _logger; + + /// + /// Creates a given a certificate's thumbprint, an + /// that can be used to resolve the certificate, and + /// an . + /// + public CertificateXmlEncryptor(string thumbprint, ICertificateResolver certificateResolver, ILoggerFactory loggerFactory) + : this(loggerFactory, encryptor: null) + { + if (thumbprint == null) + { + throw new ArgumentNullException(nameof(thumbprint)); + } + + if (certificateResolver == null) + { + throw new ArgumentNullException(nameof(certificateResolver)); + } + + _certFactory = CreateCertFactory(thumbprint, certificateResolver); + } + + /// + /// Creates a given an instance + /// and an . + /// + public CertificateXmlEncryptor(X509Certificate2 certificate, ILoggerFactory loggerFactory) + : this(loggerFactory, encryptor: null) + { + if (certificate == null) + { + throw new ArgumentNullException(nameof(certificate)); + } + + _certFactory = () => certificate; + } + + internal CertificateXmlEncryptor(ILoggerFactory loggerFactory, IInternalCertificateXmlEncryptor encryptor) + { + _encryptor = encryptor ?? this; + _logger = loggerFactory.CreateLogger(); + } + + /// + /// Encrypts the specified with an X.509 certificate. + /// + /// The plaintext to encrypt. + /// + /// An that contains the encrypted value of + /// along with information about how to + /// decrypt it. + /// + public EncryptedXmlInfo Encrypt(XElement plaintextElement) + { + if (plaintextElement == null) + { + throw new ArgumentNullException(nameof(plaintextElement)); + } + + // + // ... + // + + var encryptedElement = EncryptElement(plaintextElement); + return new EncryptedXmlInfo(encryptedElement, typeof(EncryptedXmlDecryptor)); + } + + private XElement EncryptElement(XElement plaintextElement) + { + // EncryptedXml works with XmlDocument, not XLinq. When we perform the conversion + // we'll wrap the incoming element in a dummy element since encrypted XML + // doesn't handle encrypting the root element all that well. + var xmlDocument = new XmlDocument(); + xmlDocument.Load(new XElement("root", plaintextElement).CreateReader()); + var elementToEncrypt = (XmlElement)xmlDocument.DocumentElement.FirstChild; + + // Perform the encryption and update the document in-place. + var encryptedXml = new EncryptedXml(xmlDocument); + var encryptedData = _encryptor.PerformEncryption(encryptedXml, elementToEncrypt); + EncryptedXml.ReplaceElement(elementToEncrypt, encryptedData, content: false); + + // Strip the element back off and convert the XmlDocument to an XElement. + return XElement.Load(xmlDocument.DocumentElement.FirstChild.CreateNavigator().ReadSubtree()); + } + + private Func CreateCertFactory(string thumbprint, ICertificateResolver resolver) + { + return () => + { + try + { + var cert = resolver.ResolveCertificate(thumbprint); + if (cert == null) + { + throw Error.CertificateXmlEncryptor_CertificateNotFound(thumbprint); + } + return cert; + } + catch (Exception ex) + { + _logger.ExceptionWhileTryingToResolveCertificateWithThumbprint(thumbprint, ex); + + throw; + } + }; + } + + EncryptedData IInternalCertificateXmlEncryptor.PerformEncryption(EncryptedXml encryptedXml, XmlElement elementToEncrypt) + { + var cert = _certFactory() + ?? CryptoUtil.Fail("Cert factory returned null."); + + _logger.EncryptingToX509CertificateWithThumbprint(cert.Thumbprint); + + try + { + return encryptedXml.Encrypt(elementToEncrypt, cert); + } + catch (Exception ex) + { + _logger.AnErrorOccurredWhileEncryptingToX509CertificateWithThumbprint(cert.Thumbprint, ex); + throw; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiNGProtectionDescriptorFlags.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiNGProtectionDescriptorFlags.cs new file mode 100644 index 0000000000..e0d3fafe62 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiNGProtectionDescriptorFlags.cs @@ -0,0 +1,35 @@ +// 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; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// Flags used to control the creation of protection descriptors. + /// + /// + /// These values correspond to the 'dwFlags' parameter on NCryptCreateProtectionDescriptor. + /// See https://msdn.microsoft.com/en-us/library/windows/desktop/hh706800(v=vs.85).aspx for more information. + /// + [Flags] + public enum DpapiNGProtectionDescriptorFlags + { + /// + /// No special handling is necessary. + /// + None = 0, + + /// + /// The provided descriptor is a reference to a full descriptor stored + /// in the system registry. + /// + NamedDescriptor = 0x00000001, + + /// + /// When combined with , uses the HKLM registry + /// instead of the HKCU registry when locating the full descriptor. + /// + MachineKey = 0x00000020, + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiNGXmlDecryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiNGXmlDecryptor.cs new file mode 100644 index 0000000000..653beffad1 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiNGXmlDecryptor.cs @@ -0,0 +1,91 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// An that decrypts XML elements that were encrypted with . + /// + /// + /// This API is only supported on Windows 8 / Windows Server 2012 and higher. + /// + public sealed class DpapiNGXmlDecryptor : IXmlDecryptor + { + private readonly ILogger _logger; + + /// + /// Creates a new instance of a . + /// + public DpapiNGXmlDecryptor() + : this(services: null) + { + } + + /// + /// Creates a new instance of a . + /// + /// An optional to provide ancillary services. + public DpapiNGXmlDecryptor(IServiceProvider services) + { + CryptoUtil.AssertPlatformIsWindows8OrLater(); + + _logger = services.GetLogger(); + } + + /// + /// Decrypts the specified XML element. + /// + /// An encrypted XML element. + /// The decrypted form of . + public XElement Decrypt(XElement encryptedElement) + { + if (encryptedElement == null) + { + throw new ArgumentNullException(nameof(encryptedElement)); + } + + try + { + // + // + // + // {base64} + // + + var protectedSecret = Convert.FromBase64String((string)encryptedElement.Element("value")); + if (_logger.IsDebugLevelEnabled()) + { + string protectionDescriptorRule; + try + { + protectionDescriptorRule = DpapiSecretSerializerHelper.GetRuleFromDpapiNGProtectedPayload(protectedSecret); + } + catch + { + // swallow all errors - it's just a log + protectionDescriptorRule = null; + } + _logger.DecryptingSecretElementUsingWindowsDPAPING(protectionDescriptorRule); + } + + using (var secret = DpapiSecretSerializerHelper.UnprotectWithDpapiNG(protectedSecret)) + { + return secret.ToXElement(); + } + } + catch (Exception ex) + { + // It's OK for us to log the error, as we control the exception, and it doesn't contain + // sensitive information. + _logger?.ExceptionOccurredTryingToDecryptElement(ex); + throw; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiNGXmlEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiNGXmlEncryptor.cs new file mode 100644 index 0000000000..f5162496bb --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiNGXmlEncryptor.cs @@ -0,0 +1,114 @@ +// 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.Globalization; +using System.Security.Principal; +using System.Xml.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// A class that can encrypt XML elements using Windows DPAPI:NG. + /// + /// + /// This API is only supported on Windows 8 / Windows Server 2012 and higher. + /// + public sealed class DpapiNGXmlEncryptor : IXmlEncryptor + { + private readonly ILogger _logger; + private readonly NCryptDescriptorHandle _protectionDescriptorHandle; + + /// + /// Creates a new instance of a . + /// + /// The rule string from which to create the protection descriptor. + /// Flags controlling the creation of the protection descriptor. + /// The . + public DpapiNGXmlEncryptor(string protectionDescriptorRule, DpapiNGProtectionDescriptorFlags flags, ILoggerFactory loggerFactory) + { + if (protectionDescriptorRule == null) + { + throw new ArgumentNullException(nameof(protectionDescriptorRule)); + } + + CryptoUtil.AssertPlatformIsWindows8OrLater(); + + var ntstatus = UnsafeNativeMethods.NCryptCreateProtectionDescriptor(protectionDescriptorRule, (uint)flags, out _protectionDescriptorHandle); + UnsafeNativeMethods.ThrowExceptionForNCryptStatus(ntstatus); + CryptoUtil.AssertSafeHandleIsValid(_protectionDescriptorHandle); + + _logger = loggerFactory.CreateLogger(); + } + + /// + /// Encrypts the specified . + /// + /// The plaintext to encrypt. + /// + /// An that contains the encrypted value of + /// along with information about how to + /// decrypt it. + /// + public EncryptedXmlInfo Encrypt(XElement plaintextElement) + { + if (plaintextElement == null) + { + throw new ArgumentNullException(nameof(plaintextElement)); + } + + var protectionDescriptorRuleString = _protectionDescriptorHandle.GetProtectionDescriptorRuleString(); + _logger.EncryptingToWindowsDPAPINGUsingProtectionDescriptorRule(protectionDescriptorRuleString); + + // Convert the XML element to a binary secret so that it can be run through DPAPI + byte[] cngDpapiEncryptedData; + try + { + using (var plaintextElementAsSecret = plaintextElement.ToSecret()) + { + cngDpapiEncryptedData = DpapiSecretSerializerHelper.ProtectWithDpapiNG(plaintextElementAsSecret, _protectionDescriptorHandle); + } + } + catch (Exception ex) + { + _logger.ErrorOccurredWhileEncryptingToWindowsDPAPING(ex); + throw; + } + + // + // + // + // {base64} + // + + var element = new XElement("encryptedKey", + new XComment(" This key is encrypted with Windows DPAPI-NG. "), + new XComment(" Rule: " + protectionDescriptorRuleString + " "), + new XElement("value", + Convert.ToBase64String(cngDpapiEncryptedData))); + + return new EncryptedXmlInfo(element, typeof(DpapiNGXmlDecryptor)); + } + + /// + /// Creates a rule string tied to the current Windows user and which is transferrable + /// across machines (backed up in AD). + /// + internal static string GetDefaultProtectionDescriptorString() + { + CryptoUtil.AssertPlatformIsWindows8OrLater(); + + // Creates a SID=... protection descriptor string for the current user. + // Reminder: DPAPI:NG provides only encryption, not authentication. + using (var currentIdentity = WindowsIdentity.GetCurrent()) + { + // use the SID to create an SDDL string + return string.Format(CultureInfo.InvariantCulture, "SID={0}", currentIdentity.User.Value); + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiXmlDecryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiXmlDecryptor.cs new file mode 100644 index 0000000000..6241263350 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiXmlDecryptor.cs @@ -0,0 +1,74 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// An that decrypts XML elements that were encrypted with . + /// + public sealed class DpapiXmlDecryptor : IXmlDecryptor + { + private readonly ILogger _logger; + + /// + /// Creates a new instance of a . + /// + public DpapiXmlDecryptor() + : this(services: null) + { + } + + /// + /// Creates a new instance of a . + /// + /// An optional to provide ancillary services. + public DpapiXmlDecryptor(IServiceProvider services) + { + CryptoUtil.AssertPlatformIsWindows(); + + _logger = services.GetLogger(); + } + + /// + /// Decrypts the specified XML element. + /// + /// An encrypted XML element. + /// The decrypted form of . + public XElement Decrypt(XElement encryptedElement) + { + if (encryptedElement == null) + { + throw new ArgumentNullException(nameof(encryptedElement)); + } + + _logger?.DecryptingSecretElementUsingWindowsDPAPI(); + + try + { + // + // + // {base64} + // + + var protectedSecret = Convert.FromBase64String((string)encryptedElement.Element("value")); + using (var secret = DpapiSecretSerializerHelper.UnprotectWithDpapi(protectedSecret)) + { + return secret.ToXElement(); + } + } + catch (Exception ex) + { + // It's OK for us to log the error, as we control the exception, and it doesn't contain + // sensitive information. + _logger?.ExceptionOccurredTryingToDecryptElement(ex); + throw; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiXmlEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiXmlEncryptor.cs new file mode 100644 index 0000000000..d7fa2d7b1b --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/DpapiXmlEncryptor.cs @@ -0,0 +1,90 @@ +// 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.Security.Principal; +using System.Xml.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// An that encrypts XML by using Windows DPAPI. + /// + /// + /// This API is only supported on Windows platforms. + /// + public sealed class DpapiXmlEncryptor : IXmlEncryptor + { + private readonly ILogger _logger; + private readonly bool _protectToLocalMachine; + + /// + /// Creates a given a protection scope and an . + /// + /// 'true' if the data should be decipherable by anybody on the local machine, + /// 'false' if the data should only be decipherable by the current Windows user account. + /// The . + public DpapiXmlEncryptor(bool protectToLocalMachine, ILoggerFactory loggerFactory) + { + CryptoUtil.AssertPlatformIsWindows(); + + _protectToLocalMachine = protectToLocalMachine; + _logger = loggerFactory.CreateLogger(); + } + + /// + /// Encrypts the specified . + /// + /// The plaintext to encrypt. + /// + /// An that contains the encrypted value of + /// along with information about how to + /// decrypt it. + /// + public EncryptedXmlInfo Encrypt(XElement plaintextElement) + { + if (plaintextElement == null) + { + throw new ArgumentNullException(nameof(plaintextElement)); + } + if (_protectToLocalMachine) + { + _logger.EncryptingToWindowsDPAPIForLocalMachineAccount(); + } + else + { + _logger.EncryptingToWindowsDPAPIForCurrentUserAccount(WindowsIdentity.GetCurrent().Name); + } + + // Convert the XML element to a binary secret so that it can be run through DPAPI + byte[] dpapiEncryptedData; + try + { + using (var plaintextElementAsSecret = plaintextElement.ToSecret()) + { + dpapiEncryptedData = DpapiSecretSerializerHelper.ProtectWithDpapi(plaintextElementAsSecret, protectToLocalMachine: _protectToLocalMachine); + } + } + catch (Exception ex) + { + _logger.ErrorOccurredWhileEncryptingToWindowsDPAPI(ex); + throw; + } + + // + // + // {base64} + // + + var element = new XElement("encryptedKey", + new XComment(" This key is encrypted with Windows DPAPI. "), + new XElement("value", + Convert.ToBase64String(dpapiEncryptedData))); + + return new EncryptedXmlInfo(element, typeof(DpapiXmlDecryptor)); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/EncryptedXmlDecryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/EncryptedXmlDecryptor.cs new file mode 100644 index 0000000000..fee981b2d7 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/EncryptedXmlDecryptor.cs @@ -0,0 +1,162 @@ +// 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.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Security.Cryptography.Xml; +using System.Xml; +using System.Xml.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// An that decrypts XML elements by using the class. + /// + public sealed class EncryptedXmlDecryptor : IInternalEncryptedXmlDecryptor, IXmlDecryptor + { + private readonly IInternalEncryptedXmlDecryptor _decryptor; + private readonly XmlKeyDecryptionOptions _options; + + /// + /// Creates a new instance of an . + /// + public EncryptedXmlDecryptor() + : this(services: null) + { + } + + /// + /// Creates a new instance of an . + /// + /// An optional to provide ancillary services. + public EncryptedXmlDecryptor(IServiceProvider services) + { + _decryptor = services?.GetService() ?? this; + _options = services?.GetService>()?.Value; + } + + /// + /// Decrypts the specified XML element. + /// + /// An encrypted XML element. + /// The decrypted form of . + public XElement Decrypt(XElement encryptedElement) + { + if (encryptedElement == null) + { + throw new ArgumentNullException(nameof(encryptedElement)); + } + + // + // ... + // + + // EncryptedXml works with XmlDocument, not XLinq. When we perform the conversion + // we'll wrap the incoming element in a dummy element since encrypted XML + // doesn't handle encrypting the root element all that well. + var xmlDocument = new XmlDocument(); + xmlDocument.Load(new XElement("root", encryptedElement).CreateReader()); + var elementToDecrypt = (XmlElement)xmlDocument.DocumentElement.FirstChild; + + // Perform the decryption and update the document in-place. + var encryptedXml = new EncryptedXmlWithCertificateKeys(_options, xmlDocument); + _decryptor.PerformPreDecryptionSetup(encryptedXml); + + encryptedXml.DecryptDocument(); + + // Strip the element back off and convert the XmlDocument to an XElement. + return XElement.Load(xmlDocument.DocumentElement.FirstChild.CreateNavigator().ReadSubtree()); + } + + void IInternalEncryptedXmlDecryptor.PerformPreDecryptionSetup(EncryptedXml encryptedXml) + { + // no-op + } + + /// + /// Can decrypt the XML key data from an that is not in stored in . + /// + private class EncryptedXmlWithCertificateKeys : EncryptedXml + { + private readonly XmlKeyDecryptionOptions _options; + + public EncryptedXmlWithCertificateKeys(XmlKeyDecryptionOptions options, XmlDocument document) + : base(document) + { + _options = options; + } + + public override byte[] DecryptEncryptedKey(EncryptedKey encryptedKey) + { + if (_options != null && _options.KeyDecryptionCertificateCount > 0) + { + var keyInfoEnum = encryptedKey.KeyInfo?.GetEnumerator(); + if (keyInfoEnum == null) + { + return null; + } + + while (keyInfoEnum.MoveNext()) + { + if (!(keyInfoEnum.Current is KeyInfoX509Data kiX509Data)) + { + continue; + } + + byte[] key = GetKeyFromCert(encryptedKey, kiX509Data); + if (key != null) + { + return key; + } + } + } + + return base.DecryptEncryptedKey(encryptedKey); + } + + private byte[] GetKeyFromCert(EncryptedKey encryptedKey, KeyInfoX509Data keyInfo) + { + var certEnum = keyInfo.Certificates?.GetEnumerator(); + if (certEnum == null) + { + return null; + } + + while (certEnum.MoveNext()) + { + if (!(certEnum.Current is X509Certificate2 certInfo)) + { + continue; + } + + if (!_options.TryGetKeyDecryptionCertificates(certInfo, out var keyDecryptionCerts)) + { + continue; + } + + foreach (var keyDecryptionCert in keyDecryptionCerts) + { + if (!keyDecryptionCert.HasPrivateKey) + { + continue; + } + + using (RSA privateKey = keyDecryptionCert.GetRSAPrivateKey()) + { + if (privateKey != null) + { + var useOAEP = encryptedKey.EncryptionMethod?.KeyAlgorithm == XmlEncRSAOAEPUrl; + return DecryptKey(encryptedKey.CipherData.CipherValue, privateKey, useOAEP); + } + } + } + } + + return null; + } + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/EncryptedXmlInfo.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/EncryptedXmlInfo.cs new file mode 100644 index 0000000000..17e2a01e4e --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/EncryptedXmlInfo.cs @@ -0,0 +1,56 @@ +// 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.Reflection; +using System.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// Wraps an that contains a blob of encrypted XML + /// and information about the class which can be used to decrypt it. + /// + public sealed class EncryptedXmlInfo + { + /// + /// Creates an instance of an . + /// + /// A piece of encrypted XML. + /// The class whose + /// method can be used to decrypt . + public EncryptedXmlInfo(XElement encryptedElement, Type decryptorType) + { + if (encryptedElement == null) + { + throw new ArgumentNullException(nameof(encryptedElement)); + } + + if (decryptorType == null) + { + throw new ArgumentNullException(nameof(decryptorType)); + } + + if (!typeof(IXmlDecryptor).IsAssignableFrom(decryptorType)) + { + throw new ArgumentException( + Resources.FormatTypeExtensions_BadCast(decryptorType.FullName, typeof(IXmlDecryptor).FullName), + nameof(decryptorType)); + } + + EncryptedElement = encryptedElement; + DecryptorType = decryptorType; + } + + /// + /// The class whose method can be used to + /// decrypt the value stored in . + /// + public Type DecryptorType { get; } + + /// + /// A piece of encrypted XML. + /// + public XElement EncryptedElement { get; } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/ICertificateResolver.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/ICertificateResolver.cs new file mode 100644 index 0000000000..1be22dfbce --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/ICertificateResolver.cs @@ -0,0 +1,20 @@ +// 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.Security.Cryptography.X509Certificates; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// Provides services for locating instances. + /// + public interface ICertificateResolver + { + /// + /// Locates an given its thumbprint. + /// + /// The thumbprint (as a hex string) of the certificate to resolve. + /// The resolved , or null if the certificate cannot be found. + X509Certificate2 ResolveCertificate(string thumbprint); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IInternalCertificateXmlEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IInternalCertificateXmlEncryptor.cs new file mode 100644 index 0000000000..ef9fe71648 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IInternalCertificateXmlEncryptor.cs @@ -0,0 +1,17 @@ +// 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.Xml; +using System.Security.Cryptography.Xml; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// Internal implementation details of for unit testing. + /// + internal interface IInternalCertificateXmlEncryptor + { + EncryptedData PerformEncryption(EncryptedXml encryptedXml, XmlElement elementToEncrypt); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IInternalEncryptedXmlDecryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IInternalEncryptedXmlDecryptor.cs new file mode 100644 index 0000000000..79fc0481ed --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IInternalEncryptedXmlDecryptor.cs @@ -0,0 +1,16 @@ +// 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.Security.Cryptography.Xml; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// Internal implementation details of for unit testing. + /// + internal interface IInternalEncryptedXmlDecryptor + { + void PerformPreDecryptionSetup(EncryptedXml encryptedXml); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IXmlDecryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IXmlDecryptor.cs new file mode 100644 index 0000000000..1ada323d21 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IXmlDecryptor.cs @@ -0,0 +1,24 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// The basic interface for decrypting an XML element. + /// + public interface IXmlDecryptor + { + /// + /// Decrypts the specified XML element. + /// + /// An encrypted XML element. + /// The decrypted form of . + /// + /// Implementations of this method must not mutate the + /// instance provided by . + /// + XElement Decrypt(XElement encryptedElement); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IXmlEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IXmlEncryptor.cs new file mode 100644 index 0000000000..40a87d1a8d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/IXmlEncryptor.cs @@ -0,0 +1,28 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// The basic interface for encrypting XML elements. + /// + public interface IXmlEncryptor + { + /// + /// Encrypts the specified . + /// + /// The plaintext to encrypt. + /// + /// An that contains the encrypted value of + /// along with information about how to + /// decrypt it. + /// + /// + /// Implementations of this method must not mutate the + /// instance provided by . + /// + EncryptedXmlInfo Encrypt(XElement plaintextElement); + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/NullXmlDecryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/NullXmlDecryptor.cs new file mode 100644 index 0000000000..a63c0f2963 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/NullXmlDecryptor.cs @@ -0,0 +1,36 @@ +// 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 System.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// An that decrypts XML elements with a null decryptor. + /// + public sealed class NullXmlDecryptor : IXmlDecryptor + { + /// + /// Decrypts the specified XML element. + /// + /// An encrypted XML element. + /// The decrypted form of . + public XElement Decrypt(XElement encryptedElement) + { + if (encryptedElement == null) + { + throw new ArgumentNullException(nameof(encryptedElement)); + } + + // + // + // + // + + // Return a clone of the single child node. + return new XElement(encryptedElement.Elements().Single()); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/NullXmlEncryptor.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/NullXmlEncryptor.cs new file mode 100644 index 0000000000..0f3100b859 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/NullXmlEncryptor.cs @@ -0,0 +1,65 @@ +// 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.Xml.Linq; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// An that encrypts XML elements with a null encryptor. + /// + public sealed class NullXmlEncryptor : IXmlEncryptor + { + private readonly ILogger _logger; + + /// + /// Creates a new instance of . + /// + public NullXmlEncryptor() + : this(services: null) + { + } + + /// + /// Creates a new instance of . + /// + /// An optional to provide ancillary services. + public NullXmlEncryptor(IServiceProvider services) + { + _logger = services.GetLogger(); + } + + /// + /// Encrypts the specified with a null encryptor, i.e., + /// by returning the original value of unencrypted. + /// + /// The plaintext to echo back. + /// + /// An that contains the null-encrypted value of + /// along with information about how to + /// decrypt it. + /// + public EncryptedXmlInfo Encrypt(XElement plaintextElement) + { + if (plaintextElement == null) + { + throw new ArgumentNullException(nameof(plaintextElement)); + } + + _logger?.EncryptingUsingNullEncryptor(); + + // + // + // + // + + var newElement = new XElement("unencryptedKey", + new XComment(" This key is not encrypted. "), + new XElement(plaintextElement) /* copy ctor */); + + return new EncryptedXmlInfo(newElement, typeof(NullXmlDecryptor)); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/XmlEncryptionExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/XmlEncryptionExtensions.cs new file mode 100644 index 0000000000..cfc65a44a2 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/XmlEncryptionExtensions.cs @@ -0,0 +1,185 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Internal; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + internal unsafe static class XmlEncryptionExtensions + { + public static XElement DecryptElement(this XElement element, IActivator activator) + { + // If no decryption necessary, return original element. + if (!DoesElementOrDescendentRequireDecryption(element)) + { + return element; + } + + // Deep copy the element (since we're going to mutate) and put + // it into a document to guarantee it has a parent. + var doc = new XDocument(new XElement(element)); + + // We remove elements from the document as we decrypt them and perform + // fix-up later. This keeps us from going into an infinite loop in + // the case of a null decryptor (which returns its original input which + // is still marked as 'requires decryption'). + var placeholderReplacements = new Dictionary(); + + while (true) + { + var elementWhichRequiresDecryption = doc.Descendants(XmlConstants.EncryptedSecretElementName).FirstOrDefault(); + if (elementWhichRequiresDecryption == null) + { + // All encryption is finished. + break; + } + + // Decrypt the clone so that the decryptor doesn't inadvertently modify + // the original document or other data structures. The element we pass to + // the decryptor should be the child of the 'encryptedSecret' element. + var clonedElementWhichRequiresDecryption = new XElement(elementWhichRequiresDecryption); + string decryptorTypeName = (string)clonedElementWhichRequiresDecryption.Attribute(XmlConstants.DecryptorTypeAttributeName); + var decryptorInstance = activator.CreateInstance(decryptorTypeName); + var decryptedElement = decryptorInstance.Decrypt(clonedElementWhichRequiresDecryption.Elements().Single()); + + // Put a placeholder into the original document so that we can continue our + // search for elements which need to be decrypted. + var newPlaceholder = new XElement("placeholder"); + placeholderReplacements[newPlaceholder] = decryptedElement; + elementWhichRequiresDecryption.ReplaceWith(newPlaceholder); + } + + // Finally, perform fixup. + Debug.Assert(placeholderReplacements.Count > 0); + foreach (var entry in placeholderReplacements) + { + entry.Key.ReplaceWith(entry.Value); + } + return doc.Root; + } + + public static XElement EncryptIfNecessary(this IXmlEncryptor encryptor, XElement element) + { + // If no encryption is necessary, return null. + if (!DoesElementOrDescendentRequireEncryption(element)) + { + return null; + } + + // Deep copy the element (since we're going to mutate) and put + // it into a document to guarantee it has a parent. + var doc = new XDocument(new XElement(element)); + + // We remove elements from the document as we encrypt them and perform + // fix-up later. This keeps us from going into an infinite loop in + // the case of a null encryptor (which returns its original input which + // is still marked as 'requires encryption'). + var placeholderReplacements = new Dictionary(); + + while (true) + { + var elementWhichRequiresEncryption = doc.Descendants().FirstOrDefault(DoesSingleElementRequireEncryption); + if (elementWhichRequiresEncryption == null) + { + // All encryption is finished. + break; + } + + // Encrypt the clone so that the encryptor doesn't inadvertently modify + // the original document or other data structures. + var clonedElementWhichRequiresEncryption = new XElement(elementWhichRequiresEncryption); + var innerDoc = new XDocument(clonedElementWhichRequiresEncryption); + var encryptedXmlInfo = encryptor.Encrypt(clonedElementWhichRequiresEncryption); + CryptoUtil.Assert(encryptedXmlInfo != null, "IXmlEncryptor.Encrypt returned null."); + + // Put a placeholder into the original document so that we can continue our + // search for elements which need to be encrypted. + var newPlaceholder = new XElement("placeholder"); + placeholderReplacements[newPlaceholder] = encryptedXmlInfo; + elementWhichRequiresEncryption.ReplaceWith(newPlaceholder); + } + + // Finally, perform fixup. + Debug.Assert(placeholderReplacements.Count > 0); + foreach (var entry in placeholderReplacements) + { + // + // + // + entry.Key.ReplaceWith( + new XElement(XmlConstants.EncryptedSecretElementName, + new XAttribute(XmlConstants.DecryptorTypeAttributeName, entry.Value.DecryptorType.AssemblyQualifiedName), + entry.Value.EncryptedElement)); + } + return doc.Root; + } + + /// + /// Converts an to a so that it can be kept in memory + /// securely or run through the DPAPI routines. + /// + public static Secret ToSecret(this XElement element) + { + const int DEFAULT_BUFFER_SIZE = 16 * 1024; // 16k buffer should be large enough to encrypt any realistic secret + var memoryStream = new MemoryStream(DEFAULT_BUFFER_SIZE); + element.Save(memoryStream); + + var underlyingBuffer = memoryStream.GetBuffer(); + fixed (byte* __unused__ = underlyingBuffer) // try to limit this moving around in memory while we allocate + { + try + { + return new Secret(new ArraySegment(underlyingBuffer, 0, checked((int)memoryStream.Length))); + } + finally + { + Array.Clear(underlyingBuffer, 0, underlyingBuffer.Length); + } + } + } + + /// + /// Converts a back into an . + /// + public static XElement ToXElement(this Secret secret) + { + var plaintextSecret = new byte[secret.Length]; + fixed (byte* __unused__ = plaintextSecret) // try to keep the GC from moving it around + { + try + { + secret.WriteSecretIntoBuffer(new ArraySegment(plaintextSecret)); + var memoryStream = new MemoryStream(plaintextSecret, writable: false); + return XElement.Load(memoryStream); + } + finally + { + Array.Clear(plaintextSecret, 0, plaintextSecret.Length); + } + } + } + + private static bool DoesElementOrDescendentRequireDecryption(XElement element) + { + return element.DescendantsAndSelf(XmlConstants.EncryptedSecretElementName).Any(); + } + + private static bool DoesElementOrDescendentRequireEncryption(XElement element) + { + return element.DescendantsAndSelf().Any(DoesSingleElementRequireEncryption); + } + + private static bool DoesSingleElementRequireEncryption(XElement element) + { + return element.IsMarkedAsRequiringEncryption(); + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/XmlKeyDecryptionOptions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/XmlKeyDecryptionOptions.cs new file mode 100644 index 0000000000..7da598816f --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlEncryption/XmlKeyDecryptionOptions.cs @@ -0,0 +1,39 @@ +// 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.Collections.Generic; +using System.Security.Cryptography.X509Certificates; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + /// + /// Specifies settings for how to decrypt XML keys. + /// + internal class XmlKeyDecryptionOptions + { + private readonly Dictionary> _certs = new Dictionary>(StringComparer.Ordinal); + + public int KeyDecryptionCertificateCount => _certs.Count; + + public bool TryGetKeyDecryptionCertificates(X509Certificate2 certInfo, out IReadOnlyList keyDecryptionCerts) + { + var key = GetKey(certInfo); + var retVal = _certs.TryGetValue(key, out var keyDecryptionCertsRetVal); + keyDecryptionCerts = keyDecryptionCertsRetVal; + return retVal; + } + + public void AddKeyDecryptionCertificate(X509Certificate2 certificate) + { + var key = GetKey(certificate); + if (!_certs.TryGetValue(key, out var certificates)) + { + certificates = _certs[key] = new List(); + } + certificates.Add(certificate); + } + + private string GetKey(X509Certificate2 cert) => cert.Thumbprint; + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlExtensions.cs b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlExtensions.cs new file mode 100644 index 0000000000..bc08eb2b3d --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/XmlExtensions.cs @@ -0,0 +1,30 @@ +// 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.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Contains helpers to work with XElement objects. + /// + internal static class XmlExtensions + { + /// + /// Returns a new XElement which is a carbon copy of the provided element, + /// but with no child nodes. Useful for writing exception messages without + /// inadvertently disclosing secret key material. It is assumed that the + /// element name itself and its attribute values are not secret. + /// + public static XElement WithoutChildNodes(this XElement element) + { + var newElement = new XElement(element.Name); + foreach (var attr in element.Attributes()) + { + newElement.SetAttributeValue(attr.Name, attr.Value); + } + return newElement; + } + } +} diff --git a/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/baseline.netcore.json b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/baseline.netcore.json new file mode 100644 index 0000000000..6c7f96a387 --- /dev/null +++ b/src/DataProtection/src/Microsoft.AspNetCore.DataProtection/baseline.netcore.json @@ -0,0 +1,3071 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.DataProtection, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "AddDataProtection", + "Parameters": [ + { + "Name": "services", + "Type": "Microsoft.Extensions.DependencyInjection.IServiceCollection" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AddDataProtection", + "Parameters": [ + { + "Name": "services", + "Type": "Microsoft.Extensions.DependencyInjection.IServiceCollection" + }, + { + "Name": "setupAction", + "Type": "System.Action" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "SetApplicationName", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "applicationName", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AddKeyEscrowSink", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "sink", + "Type": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AddKeyEscrowSink", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TImplementation", + "ParameterPosition": 0, + "Class": true, + "BaseTypeOrInterfaces": [ + "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink" + ] + } + ] + }, + { + "Kind": "Method", + "Name": "AddKeyEscrowSink", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "factory", + "Type": "System.Func" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AddKeyManagementOptions", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "setupAction", + "Type": "System.Action" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "DisableAutomaticKeyGeneration", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "PersistKeysToFileSystem", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "directory", + "Type": "System.IO.DirectoryInfo" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "PersistKeysToRegistry", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "registryKey", + "Type": "Microsoft.Win32.RegistryKey" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ProtectKeysWithCertificate", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "certificate", + "Type": "System.Security.Cryptography.X509Certificates.X509Certificate2" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ProtectKeysWithCertificate", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "thumbprint", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "UnprotectKeysWithAnyCertificate", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "certificates", + "Type": "System.Security.Cryptography.X509Certificates.X509Certificate2[]", + "IsParams": true + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ProtectKeysWithDpapi", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ProtectKeysWithDpapi", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "protectToLocalMachine", + "Type": "System.Boolean" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ProtectKeysWithDpapiNG", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ProtectKeysWithDpapiNG", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "protectionDescriptorRule", + "Type": "System.String" + }, + { + "Name": "flags", + "Type": "Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "SetDefaultKeyLifetime", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "lifetime", + "Type": "System.TimeSpan" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "UseCryptographicAlgorithms", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "configuration", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "UseCustomCryptographicAlgorithms", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "configuration", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "UseCustomCryptographicAlgorithms", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "configuration", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "UseCustomCryptographicAlgorithms", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + }, + { + "Name": "configuration", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "UseEphemeralDataProtectionProvider", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.DataProtectionOptions", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ApplicationDiscriminator", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ApplicationDiscriminator", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "GetApplicationUniqueIdentifier", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + } + ], + "ReturnType": "System.String", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider" + ], + "Members": [ + { + "Kind": "Method", + "Name": "CreateProtector", + "Parameters": [ + { + "Name": "purpose", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtector", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.IDataProtectionProvider", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Services", + "Parameters": [], + "ReturnType": "Microsoft.Extensions.DependencyInjection.IServiceCollection", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.IPersistedDataProtector", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.IDataProtector" + ], + "Members": [ + { + "Kind": "Method", + "Name": "DangerousUnprotect", + "Parameters": [ + { + "Name": "protectedData", + "Type": "System.Byte[]" + }, + { + "Name": "ignoreRevocationErrors", + "Type": "System.Boolean" + }, + { + "Name": "requiresMigration", + "Type": "System.Boolean", + "Direction": "Out" + }, + { + "Name": "wasRevoked", + "Type": "System.Boolean", + "Direction": "Out" + } + ], + "ReturnType": "System.Byte[]", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.ISecret", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [ + "System.IDisposable" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_Length", + "Parameters": [], + "ReturnType": "System.Int32", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WriteSecretIntoBuffer", + "Parameters": [ + { + "Name": "buffer", + "Type": "System.ArraySegment" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.Secret", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.ISecret" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Dispose", + "Parameters": [], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.IDisposable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Length", + "Parameters": [], + "ReturnType": "System.Int32", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.ISecret", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Random", + "Parameters": [ + { + "Name": "numBytes", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.Secret", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WriteSecretIntoBuffer", + "Parameters": [ + { + "Name": "buffer", + "Type": "System.ArraySegment" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.ISecret", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WriteSecretIntoBuffer", + "Parameters": [ + { + "Name": "buffer", + "Type": "System.Byte*" + }, + { + "Name": "bufferLength", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "value", + "Type": "System.ArraySegment" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "value", + "Type": "System.Byte[]" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "secret", + "Type": "System.Byte*" + }, + { + "Name": "secretLength", + "Type": "System.Int32" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "secret", + "Type": "Microsoft.AspNetCore.DataProtection.ISecret" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver" + ], + "Members": [ + { + "Kind": "Method", + "Name": "ResolveCertificate", + "Parameters": [ + { + "Name": "thumbprint", + "Type": "System.String" + } + ], + "ReturnType": "System.Security.Cryptography.X509Certificates.X509Certificate2", + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IInternalCertificateXmlEncryptor", + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Encrypt", + "Parameters": [ + { + "Name": "plaintextElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "thumbprint", + "Type": "System.String" + }, + { + "Name": "certificateResolver", + "Type": "Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver" + }, + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "certificate", + "Type": "System.Security.Cryptography.X509Certificates.X509Certificate2" + }, + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags", + "Visibility": "Public", + "Kind": "Enumeration", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Field", + "Name": "None", + "Parameters": [], + "GenericParameter": [], + "Literal": "0" + }, + { + "Kind": "Field", + "Name": "NamedDescriptor", + "Parameters": [], + "GenericParameter": [], + "Literal": "1" + }, + { + "Kind": "Field", + "Name": "MachineKey", + "Parameters": [], + "GenericParameter": [], + "Literal": "32" + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Decrypt", + "Parameters": [ + { + "Name": "encryptedElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "System.Xml.Linq.XElement", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Encrypt", + "Parameters": [ + { + "Name": "plaintextElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "protectionDescriptorRule", + "Type": "System.String" + }, + { + "Name": "flags", + "Type": "Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags" + }, + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Decrypt", + "Parameters": [ + { + "Name": "encryptedElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "System.Xml.Linq.XElement", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Encrypt", + "Parameters": [ + { + "Name": "plaintextElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "protectToLocalMachine", + "Type": "System.Boolean" + }, + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IInternalEncryptedXmlDecryptor", + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Decrypt", + "Parameters": [ + { + "Name": "encryptedElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "System.Xml.Linq.XElement", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_DecryptorType", + "Parameters": [], + "ReturnType": "System.Type", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_EncryptedElement", + "Parameters": [], + "ReturnType": "System.Xml.Linq.XElement", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "encryptedElement", + "Type": "System.Xml.Linq.XElement" + }, + { + "Name": "decryptorType", + "Type": "System.Type" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "ResolveCertificate", + "Parameters": [ + { + "Name": "thumbprint", + "Type": "System.String" + } + ], + "ReturnType": "System.Security.Cryptography.X509Certificates.X509Certificate2", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Decrypt", + "Parameters": [ + { + "Name": "encryptedElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "System.Xml.Linq.XElement", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Encrypt", + "Parameters": [ + { + "Name": "plaintextElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Decrypt", + "Parameters": [ + { + "Name": "encryptedElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "System.Xml.Linq.XElement", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Encrypt", + "Parameters": [ + { + "Name": "plaintextElement", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "services", + "Type": "System.IServiceProvider" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_DefaultKeyStorageDirectory", + "Parameters": [], + "ReturnType": "System.IO.DirectoryInfo", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Directory", + "Parameters": [], + "ReturnType": "System.IO.DirectoryInfo", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetAllElements", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyCollection", + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "StoreElement", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + }, + { + "Name": "friendlyName", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "directory", + "Type": "System.IO.DirectoryInfo" + }, + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "GetAllElements", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyCollection", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "StoreElement", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + }, + { + "Name": "friendlyName", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_DefaultRegistryKey", + "Parameters": [], + "ReturnType": "Microsoft.Win32.RegistryKey", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_RegistryKey", + "Parameters": [], + "ReturnType": "Microsoft.Win32.RegistryKey", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetAllElements", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyCollection", + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "StoreElement", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + }, + { + "Name": "friendlyName", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "registryKey", + "Type": "Microsoft.Win32.RegistryKey" + }, + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKey", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ActivationDate", + "Parameters": [], + "ReturnType": "System.DateTimeOffset", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_CreationDate", + "Parameters": [], + "ReturnType": "System.DateTimeOffset", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ExpirationDate", + "Parameters": [], + "ReturnType": "System.DateTimeOffset", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsRevoked", + "Parameters": [], + "ReturnType": "System.Boolean", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_KeyId", + "Parameters": [], + "ReturnType": "System.Guid", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Descriptor", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CreateEncryptor", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Store", + "Parameters": [ + { + "Name": "keyId", + "Type": "System.Guid" + }, + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CreateNewKey", + "Parameters": [ + { + "Name": "activationDate", + "Type": "System.DateTimeOffset" + }, + { + "Name": "expirationDate", + "Type": "System.DateTimeOffset" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKey", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetAllKeys", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyCollection", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetCacheExpirationToken", + "Parameters": [], + "ReturnType": "System.Threading.CancellationToken", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "RevokeKey", + "Parameters": [ + { + "Name": "keyId", + "Type": "System.Guid" + }, + { + "Name": "reason", + "Type": "System.String", + "DefaultValue": "null" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "RevokeAllKeys", + "Parameters": [ + { + "Name": "revocationDate", + "Type": "System.DateTimeOffset" + }, + { + "Name": "reason", + "Type": "System.String", + "DefaultValue": "null" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_AutoGenerateKeys", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_AutoGenerateKeys", + "Parameters": [ + { + "Name": "value", + "Type": "System.Boolean" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_NewKeyLifetime", + "Parameters": [], + "ReturnType": "System.TimeSpan", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_NewKeyLifetime", + "Parameters": [ + { + "Name": "value", + "Type": "System.TimeSpan" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_AuthenticatedEncryptorConfiguration", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_AuthenticatedEncryptorConfiguration", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_KeyEscrowSinks", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IList", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_XmlRepository", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_XmlRepository", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_XmlEncryptor", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_XmlEncryptor", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_AuthenticatedEncryptorFactories", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IList", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager", + "Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager" + ], + "Members": [ + { + "Kind": "Method", + "Name": "CreateNewKey", + "Parameters": [ + { + "Name": "activationDate", + "Type": "System.DateTimeOffset" + }, + { + "Name": "expirationDate", + "Type": "System.DateTimeOffset" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKey", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetAllKeys", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyCollection", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetCacheExpirationToken", + "Parameters": [], + "ReturnType": "System.Threading.CancellationToken", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "RevokeAllKeys", + "Parameters": [ + { + "Name": "revocationDate", + "Type": "System.DateTimeOffset" + }, + { + "Name": "reason", + "Type": "System.String", + "DefaultValue": "null" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "RevokeKey", + "Parameters": [ + { + "Name": "keyId", + "Type": "System.Guid" + }, + { + "Name": "reason", + "Type": "System.String", + "DefaultValue": "null" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "keyManagementOptions", + "Type": "Microsoft.Extensions.Options.IOptions" + }, + { + "Name": "activator", + "Type": "Microsoft.AspNetCore.DataProtection.Internal.IActivator" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "keyManagementOptions", + "Type": "Microsoft.Extensions.Options.IOptions" + }, + { + "Name": "activator", + "Type": "Microsoft.AspNetCore.DataProtection.Internal.IActivator" + }, + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory" + ], + "Members": [ + { + "Kind": "Method", + "Name": "CreateEncryptorInstance", + "Parameters": [ + { + "Name": "key", + "Type": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKey" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory" + ], + "Members": [ + { + "Kind": "Method", + "Name": "CreateEncryptorInstance", + "Parameters": [ + { + "Name": "key", + "Type": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKey" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory" + ], + "Members": [ + { + "Kind": "Method", + "Name": "CreateEncryptorInstance", + "Parameters": [ + { + "Name": "key", + "Type": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKey" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm", + "Visibility": "Public", + "Kind": "Enumeration", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Field", + "Name": "AES_128_CBC", + "Parameters": [], + "GenericParameter": [], + "Literal": "0" + }, + { + "Kind": "Field", + "Name": "AES_192_CBC", + "Parameters": [], + "GenericParameter": [], + "Literal": "1" + }, + { + "Kind": "Field", + "Name": "AES_256_CBC", + "Parameters": [], + "GenericParameter": [], + "Literal": "2" + }, + { + "Kind": "Field", + "Name": "AES_128_GCM", + "Parameters": [], + "GenericParameter": [], + "Literal": "3" + }, + { + "Kind": "Field", + "Name": "AES_192_GCM", + "Parameters": [], + "GenericParameter": [], + "Literal": "4" + }, + { + "Kind": "Field", + "Name": "AES_256_GCM", + "Parameters": [], + "GenericParameter": [], + "Literal": "5" + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Decrypt", + "Parameters": [ + { + "Name": "ciphertext", + "Type": "System.ArraySegment" + }, + { + "Name": "additionalAuthenticatedData", + "Type": "System.ArraySegment" + } + ], + "ReturnType": "System.Byte[]", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encrypt", + "Parameters": [ + { + "Name": "plaintext", + "Type": "System.ArraySegment" + }, + { + "Name": "additionalAuthenticatedData", + "Type": "System.ArraySegment" + } + ], + "ReturnType": "System.Byte[]", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CreateEncryptorInstance", + "Parameters": [ + { + "Name": "key", + "Type": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKey" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory" + ], + "Members": [ + { + "Kind": "Method", + "Name": "CreateEncryptorInstance", + "Parameters": [ + { + "Name": "key", + "Type": "Microsoft.AspNetCore.DataProtection.KeyManagement.IKey" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "loggerFactory", + "Type": "Microsoft.Extensions.Logging.ILoggerFactory" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm", + "Visibility": "Public", + "Kind": "Enumeration", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Field", + "Name": "HMACSHA256", + "Parameters": [], + "GenericParameter": [], + "Literal": "0" + }, + { + "Kind": "Field", + "Name": "HMACSHA512", + "Parameters": [], + "GenericParameter": [], + "Literal": "1" + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CreateNewDescriptor", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Protected", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "BaseType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IInternalAlgorithmConfiguration" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_EncryptionAlgorithm", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_EncryptionAlgorithm", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValidationAlgorithm", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ValidationAlgorithm", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CreateNewDescriptor", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "ExportToXml", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "configuration", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration" + }, + { + "Name": "masterKey", + "Type": "Microsoft.AspNetCore.DataProtection.ISecret" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer" + ], + "Members": [ + { + "Kind": "Method", + "Name": "ImportFromXml", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "BaseType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IInternalAlgorithmConfiguration" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_EncryptionAlgorithm", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_EncryptionAlgorithm", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_EncryptionAlgorithmProvider", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_EncryptionAlgorithmProvider", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_EncryptionAlgorithmKeySize", + "Parameters": [], + "ReturnType": "System.Int32", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_EncryptionAlgorithmKeySize", + "Parameters": [ + { + "Name": "value", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_HashAlgorithm", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_HashAlgorithm", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_HashAlgorithmProvider", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_HashAlgorithmProvider", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CreateNewDescriptor", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "ExportToXml", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "configuration", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration" + }, + { + "Name": "masterKey", + "Type": "Microsoft.AspNetCore.DataProtection.ISecret" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer" + ], + "Members": [ + { + "Kind": "Method", + "Name": "ImportFromXml", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "BaseType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IInternalAlgorithmConfiguration" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_EncryptionAlgorithm", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_EncryptionAlgorithm", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_EncryptionAlgorithmProvider", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_EncryptionAlgorithmProvider", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_EncryptionAlgorithmKeySize", + "Parameters": [], + "ReturnType": "System.Int32", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_EncryptionAlgorithmKeySize", + "Parameters": [ + { + "Name": "value", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CreateNewDescriptor", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "ExportToXml", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "configuration", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration" + }, + { + "Name": "masterKey", + "Type": "Microsoft.AspNetCore.DataProtection.ISecret" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer" + ], + "Members": [ + { + "Kind": "Method", + "Name": "ImportFromXml", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "ExportToXml", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "ImportFromXml", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "BaseType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IInternalAlgorithmConfiguration" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_EncryptionAlgorithmType", + "Parameters": [], + "ReturnType": "System.Type", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_EncryptionAlgorithmType", + "Parameters": [ + { + "Name": "value", + "Type": "System.Type" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_EncryptionAlgorithmKeySize", + "Parameters": [], + "ReturnType": "System.Int32", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_EncryptionAlgorithmKeySize", + "Parameters": [ + { + "Name": "value", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValidationAlgorithmType", + "Parameters": [], + "ReturnType": "System.Type", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ValidationAlgorithmType", + "Parameters": [ + { + "Name": "value", + "Type": "System.Type" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CreateNewDescriptor", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor" + ], + "Members": [ + { + "Kind": "Method", + "Name": "ExportToXml", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "configuration", + "Type": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration" + }, + { + "Name": "masterKey", + "Type": "Microsoft.AspNetCore.DataProtection.ISecret" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer" + ], + "Members": [ + { + "Kind": "Method", + "Name": "ImportFromXml", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "MarkAsRequiresEncryption", + "Parameters": [ + { + "Name": "element", + "Type": "System.Xml.Linq.XElement" + } + ], + "ReturnType": "System.Void", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_DeserializerType", + "Parameters": [], + "ReturnType": "System.Type", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_SerializedDescriptorElement", + "Parameters": [], + "ReturnType": "System.Xml.Linq.XElement", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "serializedDescriptorElement", + "Type": "System.Xml.Linq.XElement" + }, + { + "Name": "deserializerType", + "Type": "System.Type" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file diff --git a/src/DataProtection/test/CreateTestCert.ps1 b/src/DataProtection/test/CreateTestCert.ps1 new file mode 100644 index 0000000000..a85a040f05 --- /dev/null +++ b/src/DataProtection/test/CreateTestCert.ps1 @@ -0,0 +1,14 @@ +# +# Generates a new test cert in a .pfx file +# Obviously, don't actually use this to produce production certs +# + +param( + [Parameter(Mandatory = $true)] + $OutFile +) + +$password = ConvertTo-SecureString -Force -AsPlainText -String "password" +$cert = New-SelfSignedCertificate -DnsName "localhost" -CertStoreLocation Cert:\CurrentUser\My\ +Export-PfxCertificate -Cert $cert -Password $password -FilePath $OutFile +Remove-Item "Cert:\CurrentUser\My\$($cert.Thumbprint)" diff --git a/src/DataProtection/test/Directory.Build.props b/src/DataProtection/test/Directory.Build.props new file mode 100644 index 0000000000..f4a350c9a4 --- /dev/null +++ b/src/DataProtection/test/Directory.Build.props @@ -0,0 +1,19 @@ + + + + + netcoreapp3.0 + $(DeveloperBuildTestTfms) + + $(StandardTestTfms);net461 + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_Tests.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_Tests.cs new file mode 100644 index 0000000000..69dfcdfe03 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_Tests.cs @@ -0,0 +1,33 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + public unsafe class BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_Tests + { + [Fact] + public void Init_SetsProperties() + { + // Act + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.Init(out var cipherModeInfo); + + // Assert + Assert.Equal((uint)sizeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO), cipherModeInfo.cbSize); + Assert.Equal(1U, cipherModeInfo.dwInfoVersion); + Assert.Equal(IntPtr.Zero, (IntPtr)cipherModeInfo.pbNonce); + Assert.Equal(0U, cipherModeInfo.cbNonce); + Assert.Equal(IntPtr.Zero, (IntPtr)cipherModeInfo.pbAuthData); + Assert.Equal(0U, cipherModeInfo.cbAuthData); + Assert.Equal(IntPtr.Zero, (IntPtr)cipherModeInfo.pbTag); + Assert.Equal(0U, cipherModeInfo.cbTag); + Assert.Equal(IntPtr.Zero, (IntPtr)cipherModeInfo.pbMacContext); + Assert.Equal(0U, cipherModeInfo.cbMacContext); + Assert.Equal(0U, cipherModeInfo.cbAAD); + Assert.Equal(0UL, cipherModeInfo.cbData); + Assert.Equal(0U, cipherModeInfo.dwFlags); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/BCRYPT_KEY_LENGTHS_STRUCT_Tests.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/BCRYPT_KEY_LENGTHS_STRUCT_Tests.cs new file mode 100644 index 0000000000..34192eb758 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/BCRYPT_KEY_LENGTHS_STRUCT_Tests.cs @@ -0,0 +1,58 @@ +// 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 Microsoft.AspNetCore.Cryptography.Internal; +using Microsoft.AspNetCore.Testing; +using Xunit; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + public class BCRYPT_KEY_LENGTHS_STRUCT_Tests + { + [Theory] + [InlineData(128, 128, 0, 128)] + [InlineData(128, 256, 64, 128)] + [InlineData(128, 256, 64, 192)] + [InlineData(128, 256, 64, 256)] + public void EnsureValidKeyLength_SuccessCases(int minLength, int maxLength, int increment, int testValue) + { + // Arrange + var keyLengthsStruct = new BCRYPT_KEY_LENGTHS_STRUCT + { + dwMinLength = (uint)minLength, + dwMaxLength = (uint)maxLength, + dwIncrement = (uint)increment + }; + + // Act + keyLengthsStruct.EnsureValidKeyLength((uint)testValue); + + // Assert + // Nothing to do - if we got this far without throwing, success! + } + + [Theory] + [InlineData(128, 128, 0, 192)] + [InlineData(128, 256, 64, 64)] + [InlineData(128, 256, 64, 512)] + [InlineData(128, 256, 64, 160)] + [InlineData(128, 256, 64, 129)] + public void EnsureValidKeyLength_FailureCases(int minLength, int maxLength, int increment, int testValue) + { + // Arrange + var keyLengthsStruct = new BCRYPT_KEY_LENGTHS_STRUCT + { + dwMinLength = (uint)minLength, + dwMaxLength = (uint)maxLength, + dwIncrement = (uint)increment + }; + + // Act & assert + ExceptionAssert.ThrowsArgumentOutOfRange( + () => keyLengthsStruct.EnsureValidKeyLength((uint)testValue), + paramName: "keyLengthInBits", + exceptionMessage: Resources.FormatBCRYPT_KEY_LENGTHS_STRUCT_InvalidKeyLength(testValue, minLength, maxLength, increment)); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/BCryptUtilTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/BCryptUtilTests.cs new file mode 100644 index 0000000000..286bca18f4 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/BCryptUtilTests.cs @@ -0,0 +1,61 @@ +// 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.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + public unsafe class BCryptUtilTests + { + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void GenRandom_PopulatesBuffer() + { + // Arrange + byte[] bytes = new byte[sizeof(Guid) + 6]; + bytes[0] = 0x04; // leading canary + bytes[1] = 0x10; + bytes[2] = 0xE4; + bytes[sizeof(Guid) + 3] = 0xEA; // trailing canary + bytes[sizeof(Guid) + 4] = 0xF2; + bytes[sizeof(Guid) + 5] = 0x6A; + + fixed (byte* pBytes = &bytes[3]) + { + for (int i = 0; i < 100; i++) + { + // Act + BCryptUtil.GenRandom(pBytes, (uint)sizeof(Guid)); + + // Check that the canaries haven't changed + Assert.Equal(0x04, bytes[0]); + Assert.Equal(0x10, bytes[1]); + Assert.Equal(0xE4, bytes[2]); + Assert.Equal(0xEA, bytes[sizeof(Guid) + 3]); + Assert.Equal(0xF2, bytes[sizeof(Guid) + 4]); + Assert.Equal(0x6A, bytes[sizeof(Guid) + 5]); + + // Check that the buffer was actually filled. + // This check will fail once every 2**128 runs, which is insignificant. + Guid newGuid = new Guid(bytes.Skip(3).Take(sizeof(Guid)).ToArray()); + Assert.NotEqual(Guid.Empty, newGuid); + + // Check that the first and last bytes of the buffer are not zero, which indicates that they + // were in fact filled. This check will fail around 0.8% of the time, so we'll iterate up + // to 100 times, which puts the total failure rate at once every 2**700 runs, + // which is insignificant. + if (bytes[3] != 0x00 && bytes[18] != 0x00) + { + return; // success! + } + } + } + + Assert.True(false, "Buffer was not filled as expected."); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/CachedAlgorithmHandlesTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/CachedAlgorithmHandlesTests.cs new file mode 100644 index 0000000000..de601a12d5 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Cng/CachedAlgorithmHandlesTests.cs @@ -0,0 +1,189 @@ +// 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.Text; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.Cryptography.Cng +{ + // This class tests both the properties and the output of hash algorithms. + // It only tests the properties of the encryption algorithms. + // Output of the encryption and key derivatoin functions are tested by other projects. + public unsafe class CachedAlgorithmHandlesTests + { + private static readonly byte[] _dataToHash = Encoding.UTF8.GetBytes("Sample input data."); + private static readonly byte[] _hmacKey = Encoding.UTF8.GetBytes("Secret key material."); + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void AES_CBC_Cached_Handle() + { + RunAesBlockCipherAlgorithmTest(() => CachedAlgorithmHandles.AES_CBC); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void AES_GCM_Cached_Handle() + { + RunAesBlockCipherAlgorithmTest(() => CachedAlgorithmHandles.AES_GCM); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void SHA1_Cached_Handle_No_HMAC() + { + RunHashAlgorithmTest_No_HMAC( + getter: () => CachedAlgorithmHandles.SHA1, + expectedAlgorithmName: "SHA1", + expectedBlockSizeInBytes: 512 / 8, + expectedDigestSizeInBytes: 160 / 8, + expectedDigest: "MbYo3dZmXtgUZcUoWoxkCDKFvkk="); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void SHA1_Cached_Handle_With_HMAC() + { + RunHashAlgorithmTest_With_HMAC( + getter: () => CachedAlgorithmHandles.HMAC_SHA1, + expectedAlgorithmName: "SHA1", + expectedBlockSizeInBytes: 512 / 8, + expectedDigestSizeInBytes: 160 / 8, + expectedDigest: "PjYTgLTWkt6NeH0NudIR7N47Ipg="); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void SHA256_Cached_Handle_No_HMAC() + { + RunHashAlgorithmTest_No_HMAC( + getter: () => CachedAlgorithmHandles.SHA256, + expectedAlgorithmName: "SHA256", + expectedBlockSizeInBytes: 512 / 8, + expectedDigestSizeInBytes: 256 / 8, + expectedDigest: "5uRfQadsrnUTa3/TEo5PP6SDZQkb9AcE4wNXDVcM0Fo="); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void SHA256_Cached_Handle_With_HMAC() + { + RunHashAlgorithmTest_With_HMAC( + getter: () => CachedAlgorithmHandles.HMAC_SHA256, + expectedAlgorithmName: "SHA256", + expectedBlockSizeInBytes: 512 / 8, + expectedDigestSizeInBytes: 256 / 8, + expectedDigest: "KLzo0lVg5gZkpL5D6Ck7QT8w4iuPCe/pGCrMcOXWbKY="); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void SHA512_Cached_Handle_No_HMAC() + { + RunHashAlgorithmTest_No_HMAC( + getter: () => CachedAlgorithmHandles.SHA512, + expectedAlgorithmName: "SHA512", + expectedBlockSizeInBytes: 1024 / 8, + expectedDigestSizeInBytes: 512 / 8, + expectedDigest: "jKI7WrcgPP7n2HAYOb8uFRi7xEsNG/BmdGd18dwwkIpqJ4Vmlk2b+8hssLyMQlprTSKVJNObSiYUqW5THS7okw=="); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void SHA512_Cached_Handle_With_HMAC() + { + RunHashAlgorithmTest_With_HMAC( + getter: () => CachedAlgorithmHandles.HMAC_SHA512, + expectedAlgorithmName: "SHA512", + expectedBlockSizeInBytes: 1024 / 8, + expectedDigestSizeInBytes: 512 / 8, + expectedDigest: "pKTX5vtPtbsn7pX9ISDlOYr1NFklTBIPYAFICy0ZQbFc0QVzGaTUvtqTOi91I0sHa1DIod6uIogux5iLdHjfcA=="); + } + + private static void RunAesBlockCipherAlgorithmTest(Func getter) + { + // Getter must return the same instance of the cached handle + var algorithmHandle = getter(); + var algorithmHandleSecondAttempt = getter(); + Assert.NotNull(algorithmHandle); + Assert.Same(algorithmHandle, algorithmHandleSecondAttempt); + + // Validate that properties are what we expect + Assert.Equal("AES", algorithmHandle.GetAlgorithmName()); + Assert.Equal((uint)(128 / 8), algorithmHandle.GetCipherBlockLength()); + var supportedKeyLengths = algorithmHandle.GetSupportedKeyLengths(); + Assert.Equal(128U, supportedKeyLengths.dwMinLength); + Assert.Equal(256U, supportedKeyLengths.dwMaxLength); + Assert.Equal(64U, supportedKeyLengths.dwIncrement); + } + + private static void RunHashAlgorithmTest_No_HMAC( + Func getter, + string expectedAlgorithmName, + uint expectedBlockSizeInBytes, + uint expectedDigestSizeInBytes, + string expectedDigest) + { + // Getter must return the same instance of the cached handle + var algorithmHandle = getter(); + var algorithmHandleSecondAttempt = getter(); + Assert.NotNull(algorithmHandle); + Assert.Same(algorithmHandle, algorithmHandleSecondAttempt); + + // Validate that properties are what we expect + Assert.Equal(expectedAlgorithmName, algorithmHandle.GetAlgorithmName()); + Assert.Equal(expectedBlockSizeInBytes, algorithmHandle.GetHashBlockLength()); + Assert.Equal(expectedDigestSizeInBytes, algorithmHandle.GetHashDigestLength()); + + // Perform the digest calculation and validate against our expectation + var hashHandle = algorithmHandle.CreateHash(); + byte[] outputHash = new byte[expectedDigestSizeInBytes]; + fixed (byte* pInput = _dataToHash) + { + fixed (byte* pOutput = outputHash) + { + hashHandle.HashData(pInput, (uint)_dataToHash.Length, pOutput, (uint)outputHash.Length); + } + } + Assert.Equal(expectedDigest, Convert.ToBase64String(outputHash)); + } + + private static void RunHashAlgorithmTest_With_HMAC( + Func getter, + string expectedAlgorithmName, + uint expectedBlockSizeInBytes, + uint expectedDigestSizeInBytes, + string expectedDigest) + { + // Getter must return the same instance of the cached handle + var algorithmHandle = getter(); + var algorithmHandleSecondAttempt = getter(); + Assert.NotNull(algorithmHandle); + Assert.Same(algorithmHandle, algorithmHandleSecondAttempt); + + // Validate that properties are what we expect + Assert.Equal(expectedAlgorithmName, algorithmHandle.GetAlgorithmName()); + Assert.Equal(expectedBlockSizeInBytes, algorithmHandle.GetHashBlockLength()); + Assert.Equal(expectedDigestSizeInBytes, algorithmHandle.GetHashDigestLength()); + + // Perform the digest calculation and validate against our expectation + fixed (byte* pKey = _hmacKey) + { + var hashHandle = algorithmHandle.CreateHmac(pKey, (uint)_hmacKey.Length); + byte[] outputHash = new byte[expectedDigestSizeInBytes]; + fixed (byte* pInput = _dataToHash) + { + fixed (byte* pOutput = outputHash) + { + hashHandle.HashData(pInput, (uint)_dataToHash.Length, pOutput, (uint)outputHash.Length); + } + } + Assert.Equal(expectedDigest, Convert.ToBase64String(outputHash)); + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/CryptoUtilTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/CryptoUtilTests.cs new file mode 100644 index 0000000000..b911ab065a --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/CryptoUtilTests.cs @@ -0,0 +1,54 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.Cryptography +{ + public unsafe class CryptoUtilTests + { + [Fact] + public void TimeConstantBuffersAreEqual_Array_Equal() + { + // Arrange + byte[] a = new byte[] { 0x01, 0x23, 0x45, 0x67 }; + byte[] b = new byte[] { 0xAB, 0xCD, 0x23, 0x45, 0x67, 0xEF }; + + // Act & assert + Assert.True(CryptoUtil.TimeConstantBuffersAreEqual(a, 1, 3, b, 2, 3)); + } + + [Fact] + public void TimeConstantBuffersAreEqual_Array_Unequal() + { + byte[] a = new byte[] { 0x01, 0x23, 0x45, 0x67 }; + byte[] b = new byte[] { 0xAB, 0xCD, 0x23, 0xFF, 0x67, 0xEF }; + + // Act & assert + Assert.False(CryptoUtil.TimeConstantBuffersAreEqual(a, 1, 3, b, 2, 3)); + } + + [Fact] + public void TimeConstantBuffersAreEqual_Pointers_Equal() + { + // Arrange + uint a = 0x01234567; + uint b = 0x01234567; + + // Act & assert + Assert.True(CryptoUtil.TimeConstantBuffersAreEqual((byte*)&a, (byte*)&b, sizeof(uint))); + } + + [Fact] + public void TimeConstantBuffersAreEqual_Pointers_Unequal() + { + // Arrange + uint a = 0x01234567; + uint b = 0x89ABCDEF; + + // Act & assert + Assert.False(CryptoUtil.TimeConstantBuffersAreEqual((byte*)&a, (byte*)&b, sizeof(uint))); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Microsoft.AspNetCore.Cryptography.Internal.Test.csproj b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Microsoft.AspNetCore.Cryptography.Internal.Test.csproj new file mode 100644 index 0000000000..759f10679d --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Microsoft.AspNetCore.Cryptography.Internal.Test.csproj @@ -0,0 +1,16 @@ + + + + $(StandardTestTfms) + true + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Properties/AssemblyInfo.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..3adbc7af4e --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// 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.Runtime.CompilerServices; + +// for unit testing +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/SafeHandles/SecureLocalAllocHandleTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/SafeHandles/SecureLocalAllocHandleTests.cs new file mode 100644 index 0000000000..cf5b8f9384 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/SafeHandles/SecureLocalAllocHandleTests.cs @@ -0,0 +1,31 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.Cryptography.SafeHandles +{ + public unsafe class SecureLocalAllocHandleTests + { + [Fact] + public void Duplicate_Copies_Data() + { + // Arrange + const string expected = "xyz"; + int cbExpected = expected.Length * sizeof(char); + var controlHandle = SecureLocalAllocHandle.Allocate((IntPtr)cbExpected); + for (int i = 0; i < expected.Length; i++) + { + ((char*)controlHandle.DangerousGetHandle())[i] = expected[i]; + } + + // Act + var duplicateHandle = controlHandle.Duplicate(); + + // Assert + Assert.Equal(expected, new string((char*)duplicateHandle.DangerousGetHandle(), 0, expected.Length)); // contents the same data + Assert.NotEqual(controlHandle.DangerousGetHandle(), duplicateHandle.DangerousGetHandle()); // shouldn't just point to the same memory location + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/UnsafeBufferUtilTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/UnsafeBufferUtilTests.cs new file mode 100644 index 0000000000..359835db7e --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/UnsafeBufferUtilTests.cs @@ -0,0 +1,162 @@ +// 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.Reflection; +using System.Runtime.InteropServices; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Xunit; + +namespace Microsoft.AspNetCore.Cryptography +{ + public unsafe class UnsafeBufferUtilTests + { + [Fact] + public void BlockCopy_PtrToPtr_IntLength() + { + // Arrange + long x = 0x0123456789ABCDEF; + long y = 0; + + // Act + UnsafeBufferUtil.BlockCopy(from: &x, to: &y, byteCount: (int)sizeof(long)); + + // Assert + Assert.Equal(x, y); + } + + [Fact] + public void BlockCopy_PtrToPtr_UIntLength() + { + // Arrange + long x = 0x0123456789ABCDEF; + long y = 0; + + // Act + UnsafeBufferUtil.BlockCopy(from: &x, to: &y, byteCount: (uint)sizeof(long)); + + // Assert + Assert.Equal(x, y); + } + + [Fact] + public void BlockCopy_HandleToHandle() + { + // Arrange + const string expected = "Hello there!"; + int cbExpected = expected.Length * sizeof(char); + var controlHandle = LocalAlloc(cbExpected); + for (int i = 0; i < expected.Length; i++) + { + ((char*)controlHandle.DangerousGetHandle())[i] = expected[i]; + } + var testHandle = LocalAlloc(cbExpected); + + // Act + UnsafeBufferUtil.BlockCopy(from: controlHandle, to: testHandle, length: (IntPtr)cbExpected); + + // Assert + string actual = new string((char*)testHandle.DangerousGetHandle(), 0, expected.Length); + GC.KeepAlive(testHandle); + Assert.Equal(expected, actual); + } + + [Fact] + public void BlockCopy_HandleToPtr() + { + // Arrange + const string expected = "Hello there!"; + int cbExpected = expected.Length * sizeof(char); + var controlHandle = LocalAlloc(cbExpected); + for (int i = 0; i < expected.Length; i++) + { + ((char*)controlHandle.DangerousGetHandle())[i] = expected[i]; + } + char* dest = stackalloc char[expected.Length]; + + // Act + UnsafeBufferUtil.BlockCopy(from: controlHandle, to: dest, byteCount: (uint)cbExpected); + + // Assert + string actual = new string(dest, 0, expected.Length); + Assert.Equal(expected, actual); + } + + [Fact] + public void BlockCopy_PtrToHandle() + { + // Arrange + const string expected = "Hello there!"; + int cbExpected = expected.Length * sizeof(char); + var testHandle = LocalAlloc(cbExpected); + + // Act + fixed (char* pExpected = expected) + { + UnsafeBufferUtil.BlockCopy(from: pExpected, to: testHandle, byteCount: (uint)cbExpected); + } + + // Assert + string actual = new string((char*)testHandle.DangerousGetHandle(), 0, expected.Length); + GC.KeepAlive(testHandle); + Assert.Equal(expected, actual); + } + + [Fact] + public void SecureZeroMemory_IntLength() + { + // Arrange + long x = 0x0123456789ABCDEF; + + // Act + UnsafeBufferUtil.SecureZeroMemory((byte*)&x, byteCount: (int)sizeof(long)); + + // Assert + Assert.Equal(0, x); + } + + [Fact] + public void SecureZeroMemory_UIntLength() + { + // Arrange + long x = 0x0123456789ABCDEF; + + // Act + UnsafeBufferUtil.SecureZeroMemory((byte*)&x, byteCount: (uint)sizeof(long)); + + // Assert + Assert.Equal(0, x); + } + + [Fact] + public void SecureZeroMemory_ULongLength() + { + // Arrange + long x = 0x0123456789ABCDEF; + + // Act + UnsafeBufferUtil.SecureZeroMemory((byte*)&x, byteCount: (ulong)sizeof(long)); + + // Assert + Assert.Equal(0, x); + } + + [Fact] + public void SecureZeroMemory_IntPtrLength() + { + // Arrange + long x = 0x0123456789ABCDEF; + + // Act + UnsafeBufferUtil.SecureZeroMemory((byte*)&x, length: (IntPtr)sizeof(long)); + + // Assert + Assert.Equal(0, x); + } + + private static LocalAllocHandle LocalAlloc(int cb) + { + return SecureLocalAllocHandle.Allocate((IntPtr)cb); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/WeakReferenceHelpersTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/WeakReferenceHelpersTests.cs new file mode 100644 index 0000000000..da66146b07 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.Internal.Test/WeakReferenceHelpersTests.cs @@ -0,0 +1,84 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.Cryptography +{ + public class WeakReferenceHelpersTests + { + [Fact] + public void GetSharedInstance_ExistingWeakRefHasBeenGCed_CreatesNew() + { + // Arrange + WeakReference wrOriginal = new WeakReference(null); + WeakReference wr = wrOriginal; + MyDisposable newInstance = new MyDisposable(); + + // Act + var retVal = WeakReferenceHelpers.GetSharedInstance(ref wr, () => newInstance); + + // Assert + Assert.NotNull(wr); + Assert.NotSame(wrOriginal, wr); + Assert.True(wr.TryGetTarget(out var target)); + Assert.Same(newInstance, target); + Assert.Same(newInstance, retVal); + Assert.False(newInstance.HasBeenDisposed); + } + + [Fact] + public void GetSharedInstance_ExistingWeakRefIsNull_CreatesNew() + { + // Arrange + WeakReference wr = null; + MyDisposable newInstance = new MyDisposable(); + + // Act + var retVal = WeakReferenceHelpers.GetSharedInstance(ref wr, () => newInstance); + + // Assert + Assert.NotNull(wr); + Assert.True(wr.TryGetTarget(out var target)); + Assert.Same(newInstance, target); + Assert.Same(newInstance, retVal); + Assert.False(newInstance.HasBeenDisposed); + } + + [Fact] + public void GetSharedInstance_ExistingWeakRefIsNull_AnotherThreadCreatesInstanceWhileOurFactoryRuns_ReturnsExistingInstanceAndDisposesNewInstance() + { + // Arrange + WeakReference wr = null; + MyDisposable instanceThatWillBeCreatedFirst = new MyDisposable(); + MyDisposable instanceThatWillBeCreatedSecond = new MyDisposable(); + + // Act + var retVal = WeakReferenceHelpers.GetSharedInstance(ref wr, () => + { + // mimic another thread creating the instance while our factory is being invoked + WeakReferenceHelpers.GetSharedInstance(ref wr, () => instanceThatWillBeCreatedFirst); + return instanceThatWillBeCreatedSecond; + }); + + // Assert + Assert.NotNull(wr); + Assert.True(wr.TryGetTarget(out var target)); + Assert.Same(instanceThatWillBeCreatedFirst, target); + Assert.Same(instanceThatWillBeCreatedFirst, retVal); + Assert.False(instanceThatWillBeCreatedFirst.HasBeenDisposed); + Assert.True(instanceThatWillBeCreatedSecond.HasBeenDisposed); + } + + private sealed class MyDisposable : IDisposable + { + public bool HasBeenDisposed { get; private set; } + + public void Dispose() + { + HasBeenDisposed = true; + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test.csproj b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test.csproj new file mode 100644 index 0000000000..a475ac199d --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test.csproj @@ -0,0 +1,17 @@ + + + + $(StandardTestTfms) + true + + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test/Pbkdf2Tests.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test/Pbkdf2Tests.cs new file mode 100644 index 0000000000..a45f5e24ce --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test/Pbkdf2Tests.cs @@ -0,0 +1,196 @@ +// 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.Text; +using Microsoft.AspNetCore.Cryptography.KeyDerivation.PBKDF2; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.Cryptography.KeyDerivation +{ + public class Pbkdf2Tests + { + +#if NET461 +#elif NETCOREAPP3_0 + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF. We only use 5 iterations so + // that our unit tests are fast. + + // This provider is only available in .NET Core because .NET Standard only supports HMACSHA1 + [Theory] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 - 1, "efmxNcKD/U1urTEDGvsThlPnHA==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 + 0, "efmxNcKD/U1urTEDGvsThlPnHDI=")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 + 1, "efmxNcKD/U1urTEDGvsThlPnHDLk")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 - 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRA==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 + 0, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLo=")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 + 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLpk")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 - 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm9")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 + 0, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Q==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 + 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Wk=")] + public void RunTest_Normal_NetCore(string password, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedValueAsBase64) + { + // Arrange + byte[] salt = new byte[256]; + for (int i = 0; i < salt.Length; i++) + { + salt[i] = (byte)i; + } + + // Act & assert + TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedValueAsBase64); + } + + [Fact] + public void RunTest_WithLongPassword_NetCore_FallbackToManaged() + { + // salt is less than 8 bytes + byte[] salt = Encoding.UTF8.GetBytes("salt"); + const string expectedDerivedKeyBase64 = "Sc+V/c3fiZq5Z5qH3iavAiojTsW97FAp2eBNmCQAwCNzA8hfhFFYyQLIMK65qPnBFHOHXQPwAxNQNhaEAH9hzfiaNBSRJpF9V4rpl02d5ZpI6cZbsQFF7TJW7XJzQVpYoPDgJlg0xVmYLhn1E9qMtUVUuXsBjOOdd7K1M+ZI00c="; + + RunTest_WithLongPassword_Impl(salt, expectedDerivedKeyBase64); + } + + [Fact] + public void RunTest_WithLongPassword_NetCore() + { + // salt longer than 8 bytes + var salt = Encoding.UTF8.GetBytes("abcdefghijkl"); + RunTest_WithLongPassword_Impl(salt, "NGJtFzYUaaSxu+3ZsMeZO5d/qPJDUYW4caLkFlaY0cLSYdh1PN4+nHUVp4pUUubJWu3UeXNMnHKNDfnn8GMfnDVrAGTv1lldszsvUJ0JQ6p4+daQEYBc//Tj/ejuB3luwW0IinyE7U/ViOQKbfi5pCZFMQ0FFx9I+eXRlyT+I74="); + } +#else +#error Update target framework +#endif + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF. We only use 5 iterations so + // that our unit tests are fast. + [Theory] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 - 1, "efmxNcKD/U1urTEDGvsThlPnHA==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 + 0, "efmxNcKD/U1urTEDGvsThlPnHDI=")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 + 1, "efmxNcKD/U1urTEDGvsThlPnHDLk")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 - 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRA==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 + 0, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLo=")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 + 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLpk")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 - 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm9")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 + 0, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Q==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 + 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Wk=")] + public void RunTest_Normal_Managed(string password, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedValueAsBase64) + { + // Arrange + byte[] salt = new byte[256]; + for (int i = 0; i < salt.Length; i++) + { + salt[i] = (byte)i; + } + + // Act & assert + TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedValueAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF. We only use 5 iterations so + // that our unit tests are fast. + [ConditionalTheory] + [ConditionalRunTestOnlyOnWindows] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 - 1, "efmxNcKD/U1urTEDGvsThlPnHA==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 + 0, "efmxNcKD/U1urTEDGvsThlPnHDI=")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 + 1, "efmxNcKD/U1urTEDGvsThlPnHDLk")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 - 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRA==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 + 0, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLo=")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 + 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLpk")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 - 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm9")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 + 0, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Q==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 + 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Wk=")] + public void RunTest_Normal_Win7(string password, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedValueAsBase64) + { + // Arrange + byte[] salt = new byte[256]; + for (int i = 0; i < salt.Length; i++) + { + salt[i] = (byte)i; + } + + // Act & assert + TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedValueAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF. We only use 5 iterations so + // that our unit tests are fast. + [ConditionalTheory] + [ConditionalRunTestOnlyOnWindows8OrLater] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 - 1, "efmxNcKD/U1urTEDGvsThlPnHA==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 + 0, "efmxNcKD/U1urTEDGvsThlPnHDI=")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA1, 5, 160 / 8 + 1, "efmxNcKD/U1urTEDGvsThlPnHDLk")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 - 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRA==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 + 0, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLo=")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA256, 5, 256 / 8 + 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLpk")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 - 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm9")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 + 0, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Q==")] + [InlineData("my-password", KeyDerivationPrf.HMACSHA512, 5, 512 / 8 + 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Wk=")] + public void RunTest_Normal_Win8(string password, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedValueAsBase64) + { + // Arrange + byte[] salt = new byte[256]; + for (int i = 0; i < salt.Length; i++) + { + salt[i] = (byte)i; + } + + // Act & assert + TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedValueAsBase64); + } + + [Fact] + public void RunTest_WithLongPassword_Managed() + { + RunTest_WithLongPassword_Impl(); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void RunTest_WithLongPassword_Win7() + { + RunTest_WithLongPassword_Impl(); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows8OrLater] + public void RunTest_WithLongPassword_Win8() + { + RunTest_WithLongPassword_Impl(); + } + + private static void RunTest_WithLongPassword_Impl() + where TProvider : IPbkdf2Provider, new() + { + byte[] salt = Encoding.UTF8.GetBytes("salt"); + const string expectedDerivedKeyBase64 = "Sc+V/c3fiZq5Z5qH3iavAiojTsW97FAp2eBNmCQAwCNzA8hfhFFYyQLIMK65qPnBFHOHXQPwAxNQNhaEAH9hzfiaNBSRJpF9V4rpl02d5ZpI6cZbsQFF7TJW7XJzQVpYoPDgJlg0xVmYLhn1E9qMtUVUuXsBjOOdd7K1M+ZI00c="; + RunTest_WithLongPassword_Impl(salt, expectedDerivedKeyBase64); + } + + private static void RunTest_WithLongPassword_Impl(byte[] salt, string expectedDerivedKeyBase64) + where TProvider : IPbkdf2Provider, new() + { + // Arrange + string password = new String('x', 50000); // 50,000 char password + const KeyDerivationPrf prf = KeyDerivationPrf.HMACSHA256; + const int iterationCount = 5; + const int numBytesRequested = 128; + + // Act & assert + TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedDerivedKeyBase64); + } + + private static void TestProvider(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedDerivedKeyAsBase64) + where TProvider : IPbkdf2Provider, new() + { + byte[] derivedKey = new TProvider().DeriveKey(password, salt, prf, iterationCount, numBytesRequested); + Assert.Equal(numBytesRequested, derivedKey.Length); + Assert.Equal(expectedDerivedKeyAsBase64, Convert.ToBase64String(derivedKey)); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test/Properties/AssemblyInfo.cs b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..3adbc7af4e --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// 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.Runtime.CompilerServices; + +// for unit testing +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Abstractions.Test/DataProtectionCommonExtensionsTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Abstractions.Test/DataProtectionCommonExtensionsTests.cs new file mode 100644 index 0000000000..cfd4f3b41f --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Abstractions.Test/DataProtectionCommonExtensionsTests.cs @@ -0,0 +1,313 @@ +// 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.Collections.Generic; +using System.Security.Cryptography; +using System.Text; +using Microsoft.AspNetCore.DataProtection.Abstractions; +using Microsoft.AspNetCore.Testing; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class DataProtectionCommonExtensionsTests + { + [Theory] + [InlineData(new object[] { new string[0] })] + [InlineData(new object[] { new string[] { null } })] + [InlineData(new object[] { new string[] { "the next value is bad", null } })] + public void CreateProtector_ChainedAsIEnumerable_FailureCases(string[] purposes) + { + // Arrange + var mockProtector = new Mock(); + mockProtector.Setup(o => o.CreateProtector(It.IsAny())).Returns(mockProtector.Object); + var provider = mockProtector.Object; + + // Act & assert + ExceptionAssert.ThrowsArgument( + testCode: () => provider.CreateProtector((IEnumerable)purposes), + paramName: "purposes", + exceptionMessage: Resources.DataProtectionExtensions_NullPurposesCollection); + } + + [Theory] + [InlineData(new object[] { new string[] { null } })] + [InlineData(new object[] { new string[] { "the next value is bad", null } })] + public void CreateProtector_ChainedAsParams_FailureCases(string[] subPurposes) + { + // Arrange + var mockProtector = new Mock(); + mockProtector.Setup(o => o.CreateProtector(It.IsAny())).Returns(mockProtector.Object); + var provider = mockProtector.Object; + + // Act & assert + ExceptionAssert.ThrowsArgument( + testCode: () => provider.CreateProtector("primary-purpose", subPurposes), + paramName: "purposes", + exceptionMessage: Resources.DataProtectionExtensions_NullPurposesCollection); + } + + [Fact] + public void CreateProtector_ChainedAsIEnumerable_SuccessCase() + { + // Arrange + var finalExpectedProtector = new Mock().Object; + + var thirdMock = new Mock(); + thirdMock.Setup(o => o.CreateProtector("third")).Returns(finalExpectedProtector); + var secondMock = new Mock(); + secondMock.Setup(o => o.CreateProtector("second")).Returns(thirdMock.Object); + var firstMock = new Mock(); + firstMock.Setup(o => o.CreateProtector("first")).Returns(secondMock.Object); + + // Act + var retVal = firstMock.Object.CreateProtector((IEnumerable)new string[] { "first", "second", "third" }); + + // Assert + Assert.Same(finalExpectedProtector, retVal); + } + + [Fact] + public void CreateProtector_ChainedAsParams_NonEmptyParams_SuccessCase() + { + // Arrange + var finalExpectedProtector = new Mock().Object; + + var thirdMock = new Mock(); + thirdMock.Setup(o => o.CreateProtector("third")).Returns(finalExpectedProtector); + var secondMock = new Mock(); + secondMock.Setup(o => o.CreateProtector("second")).Returns(thirdMock.Object); + var firstMock = new Mock(); + firstMock.Setup(o => o.CreateProtector("first")).Returns(secondMock.Object); + + // Act + var retVal = firstMock.Object.CreateProtector("first", "second", "third"); + + // Assert + Assert.Same(finalExpectedProtector, retVal); + } + + [Theory] + [InlineData(new object[] { null })] + [InlineData(new object[] { new string[0] })] + public void CreateProtector_ChainedAsParams_EmptyParams_SuccessCases(string[] subPurposes) + { + // Arrange + var finalExpectedProtector = new Mock().Object; + var firstMock = new Mock(); + firstMock.Setup(o => o.CreateProtector("first")).Returns(finalExpectedProtector); + + // Act + var retVal = firstMock.Object.CreateProtector("first", subPurposes); + + // Assert + Assert.Same(finalExpectedProtector, retVal); + } + + [Fact] + public void GetDataProtectionProvider_NoServiceFound_Throws() + { + // Arrange + var services = new Mock().Object; + + // Act & assert + var ex = Assert.Throws(() => services.GetDataProtectionProvider()); + Assert.Equal(Resources.FormatDataProtectionExtensions_NoService(typeof(IDataProtectionProvider).FullName), ex.Message); + } + + [Fact] + public void GetDataProtectionProvider_ServiceFound_ReturnsService() + { + // Arrange + var expected = new Mock().Object; + var mockServices = new Mock(); + mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(expected); + var services = mockServices.Object; + + // Act + var actual = services.GetDataProtectionProvider(); + + // Assert + Assert.Same(expected, actual); + } + + [Theory] + [InlineData(new object[] { new string[0] })] + [InlineData(new object[] { new string[] { null } })] + [InlineData(new object[] { new string[] { "the next value is bad", null } })] + public void GetDataProtector_ChainedAsIEnumerable_FailureCases(string[] purposes) + { + // Arrange + var mockProtector = new Mock(); + mockProtector.Setup(o => o.CreateProtector(It.IsAny())).Returns(mockProtector.Object); + var mockServices = new Mock(); + mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(mockProtector.Object); + var services = mockServices.Object; + + // Act & assert + ExceptionAssert.ThrowsArgument( + testCode: () => services.GetDataProtector((IEnumerable)purposes), + paramName: "purposes", + exceptionMessage: Resources.DataProtectionExtensions_NullPurposesCollection); + } + + [Theory] + [InlineData(new object[] { new string[] { null } })] + [InlineData(new object[] { new string[] { "the next value is bad", null } })] + public void GetDataProtector_ChainedAsParams_FailureCases(string[] subPurposes) + { + // Arrange + var mockProtector = new Mock(); + mockProtector.Setup(o => o.CreateProtector(It.IsAny())).Returns(mockProtector.Object); + var mockServices = new Mock(); + mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(mockProtector.Object); + var services = mockServices.Object; + + // Act & assert + ExceptionAssert.ThrowsArgument( + testCode: () => services.GetDataProtector("primary-purpose", subPurposes), + paramName: "purposes", + exceptionMessage: Resources.DataProtectionExtensions_NullPurposesCollection); + } + + [Fact] + public void GetDataProtector_ChainedAsIEnumerable_SuccessCase() + { + // Arrange + var finalExpectedProtector = new Mock().Object; + + var thirdMock = new Mock(); + thirdMock.Setup(o => o.CreateProtector("third")).Returns(finalExpectedProtector); + var secondMock = new Mock(); + secondMock.Setup(o => o.CreateProtector("second")).Returns(thirdMock.Object); + var firstMock = new Mock(); + firstMock.Setup(o => o.CreateProtector("first")).Returns(secondMock.Object); + + var mockServices = new Mock(); + mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(firstMock.Object); + var services = mockServices.Object; + + // Act + var retVal = services.GetDataProtector((IEnumerable)new string[] { "first", "second", "third" }); + + // Assert + Assert.Same(finalExpectedProtector, retVal); + } + + [Fact] + public void GetDataProtector_ChainedAsParams_NonEmptyParams_SuccessCase() + { + // Arrange + var finalExpectedProtector = new Mock().Object; + + var thirdMock = new Mock(); + thirdMock.Setup(o => o.CreateProtector("third")).Returns(finalExpectedProtector); + var secondMock = new Mock(); + secondMock.Setup(o => o.CreateProtector("second")).Returns(thirdMock.Object); + var firstMock = new Mock(); + firstMock.Setup(o => o.CreateProtector("first")).Returns(secondMock.Object); + + var mockServices = new Mock(); + mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(firstMock.Object); + var services = mockServices.Object; + + // Act + var retVal = services.GetDataProtector("first", "second", "third"); + + // Assert + Assert.Same(finalExpectedProtector, retVal); + } + + [Theory] + [InlineData(new object[] { null })] + [InlineData(new object[] { new string[0] })] + public void GetDataProtector_ChainedAsParams_EmptyParams_SuccessCases(string[] subPurposes) + { + // Arrange + var finalExpectedProtector = new Mock().Object; + var firstMock = new Mock(); + firstMock.Setup(o => o.CreateProtector("first")).Returns(finalExpectedProtector); + var mockServices = new Mock(); + mockServices.Setup(o => o.GetService(typeof(IDataProtectionProvider))).Returns(firstMock.Object); + var services = mockServices.Object; + + // Act + var retVal = services.GetDataProtector("first", subPurposes); + + // Assert + Assert.Same(finalExpectedProtector, retVal); + } + + [Fact] + public void Protect_InvalidUtf8_Failure() + { + // Arrange + Mock mockProtector = new Mock(); + + // Act & assert + var ex = Assert.Throws(() => + { + mockProtector.Object.Protect("Hello\ud800"); + }); + Assert.IsAssignableFrom(ex.InnerException); + } + + [Fact] + public void Protect_Success() + { + // Arrange + Mock mockProtector = new Mock(); + mockProtector.Setup(p => p.Protect(new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f })).Returns(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }); + + // Act + string retVal = mockProtector.Object.Protect("Hello"); + + // Assert + Assert.Equal("AQIDBAU", retVal); + } + + [Fact] + public void Unprotect_InvalidBase64BeforeDecryption_Failure() + { + // Arrange + Mock mockProtector = new Mock(); + + // Act & assert + var ex = Assert.Throws(() => + { + mockProtector.Object.Unprotect("A"); + }); + } + + [Fact] + public void Unprotect_InvalidUtf8AfterDecryption_Failure() + { + // Arrange + Mock mockProtector = new Mock(); + mockProtector.Setup(p => p.Unprotect(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 })).Returns(new byte[] { 0xff }); + + // Act & assert + var ex = Assert.Throws(() => + { + mockProtector.Object.Unprotect("AQIDBAU"); + }); + Assert.IsAssignableFrom(ex.InnerException); + } + + [Fact] + public void Unprotect_Success() + { + // Arrange + Mock mockProtector = new Mock(); + mockProtector.Setup(p => p.Unprotect(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 })).Returns(new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f }); + + // Act + string retVal = DataProtectionCommonExtensions.Unprotect(mockProtector.Object, "AQIDBAU"); + + // Assert + Assert.Equal("Hello", retVal); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Abstractions.Test/Microsoft.AspNetCore.DataProtection.Abstractions.Test.csproj b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Abstractions.Test/Microsoft.AspNetCore.DataProtection.Abstractions.Test.csproj new file mode 100644 index 0000000000..1da22cec0d --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Abstractions.Test/Microsoft.AspNetCore.DataProtection.Abstractions.Test.csproj @@ -0,0 +1,16 @@ + + + + $(StandardTestTfms) + + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test/AzureKeyVaultXmlEncryptorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test/AzureKeyVaultXmlEncryptorTests.cs new file mode 100644 index 0000000000..faa9bd1c96 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test/AzureKeyVaultXmlEncryptorTests.cs @@ -0,0 +1,78 @@ +// 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.Linq; +using System.Security.Cryptography; +using System.Threading.Tasks; +using System.Xml.Linq; +using Microsoft.Azure.KeyVault.Models; +using Microsoft.Azure.KeyVault.WebKey; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test +{ + public class AzureKeyVaultXmlEncryptorTests + { + [Fact] + public void UsesKeyVaultToEncryptKey() + { + var mock = new Mock(); + mock.Setup(client => client.WrapKeyAsync("key", JsonWebKeyEncryptionAlgorithm.RSAOAEP, It.IsAny())) + .Returns((_, __, data) => Task.FromResult(new KeyOperationResult("KeyId", data.Reverse().ToArray()))); + + var encryptor = new AzureKeyVaultXmlEncryptor(mock.Object, "key", new MockNumberGenerator()); + var result = encryptor.Encrypt(new XElement("Element")); + + var encryptedElement = result.EncryptedElement; + var value = encryptedElement.Element("value"); + + mock.VerifyAll(); + Assert.NotNull(result); + Assert.NotNull(value); + Assert.Equal(typeof(AzureKeyVaultXmlDecryptor), result.DecryptorType); + Assert.Equal("VfLYL2prdymawfucH3Goso0zkPbQ4/GKqUsj2TRtLzsBPz7p7cL1SQaY6I29xSlsPQf6IjxHSz4sDJ427GvlLQ==", encryptedElement.Element("value").Value); + Assert.Equal("AAECAwQFBgcICQoLDA0ODw==", encryptedElement.Element("iv").Value); + Assert.Equal("Dw4NDAsKCQgHBgUEAwIBAA==", encryptedElement.Element("key").Value); + Assert.Equal("KeyId", encryptedElement.Element("kid").Value); + } + + [Fact] + public void UsesKeyVaultToDecryptKey() + { + var mock = new Mock(); + mock.Setup(client => client.UnwrapKeyAsync("KeyId", JsonWebKeyEncryptionAlgorithm.RSAOAEP, It.IsAny())) + .Returns((_, __, data) => Task.FromResult(new KeyOperationResult(null, data.Reverse().ToArray()))) + .Verifiable(); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(mock.Object); + + var encryptor = new AzureKeyVaultXmlDecryptor(serviceCollection.BuildServiceProvider()); + + var result = encryptor.Decrypt(XElement.Parse( + @" + KeyId + Dw4NDAsKCQgHBgUEAwIBAA== + AAECAwQFBgcICQoLDA0ODw== + VfLYL2prdymawfucH3Goso0zkPbQ4/GKqUsj2TRtLzsBPz7p7cL1SQaY6I29xSlsPQf6IjxHSz4sDJ427GvlLQ== + ")); + + mock.VerifyAll(); + Assert.NotNull(result); + Assert.Equal("", result.ToString()); + } + + private class MockNumberGenerator : RandomNumberGenerator + { + public override void GetBytes(byte[] data) + { + for (int i = 0; i < data.Length; i++) + { + data[i] = (byte)i; + } + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test.csproj b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test.csproj new file mode 100644 index 0000000000..c5ffd2f4e3 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Test.csproj @@ -0,0 +1,17 @@ + + + + $(StandardTestTfms) + true + + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test/AzureBlobXmlRepositoryTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test/AzureBlobXmlRepositoryTests.cs new file mode 100644 index 0000000000..61d5d0ae78 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test/AzureBlobXmlRepositoryTests.cs @@ -0,0 +1,111 @@ +// 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.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Blob; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AzureStorage.Test +{ + public class AzureBlobXmlRepositoryTests + { + [Fact] + public void StoreCreatesBlobWhenNotExist() + { + AccessCondition downloadCondition = null; + AccessCondition uploadCondition = null; + byte[] bytes = null; + BlobProperties properties = new BlobProperties(); + + var mock = new Mock(); + mock.SetupGet(c => c.Properties).Returns(properties); + mock.Setup(c => c.UploadFromByteArrayAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(async (byte[] buffer, int index, int count, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext) => + { + bytes = buffer.Skip(index).Take(count).ToArray(); + uploadCondition = accessCondition; + await Task.Yield(); + }); + + var repository = new AzureBlobXmlRepository(() => mock.Object); + repository.StoreElement(new XElement("Element"), null); + + Assert.Null(downloadCondition); + Assert.Equal("*", uploadCondition.IfNoneMatchETag); + Assert.Equal("application/xml; charset=utf-8", properties.ContentType); + var element = ""; + + Assert.Equal(bytes, GetEnvelopedContent(element)); + } + + [Fact] + public void StoreUpdatesWhenExistsAndNewerExists() + { + AccessCondition downloadCondition = null; + byte[] bytes = null; + BlobProperties properties = new BlobProperties(); + + var mock = new Mock(); + mock.SetupGet(c => c.Properties).Returns(properties); + mock.Setup(c => c.DownloadToStreamAsync( + It.IsAny(), + It.IsAny(), + null, + null)) + .Returns(async (Stream target, AccessCondition condition, BlobRequestOptions options, OperationContext context) => + { + var data = GetEnvelopedContent(""); + await target.WriteAsync(data, 0, data.Length); + }) + .Verifiable(); + + mock.Setup(c => c.UploadFromByteArrayAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.Is((AccessCondition cond) => cond.IfNoneMatchETag == "*"), + It.IsAny(), + It.IsAny())) + .Throws(new StorageException(new RequestResult { HttpStatusCode = 412 }, null, null)) + .Verifiable(); + + mock.Setup(c => c.UploadFromByteArrayAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.Is((AccessCondition cond) => cond.IfNoneMatchETag != "*"), + It.IsAny(), + It.IsAny())) + .Returns(async (byte[] buffer, int index, int count, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext) => + { + bytes = buffer.Skip(index).Take(count).ToArray(); + await Task.Yield(); + }) + .Verifiable(); + + var repository = new AzureBlobXmlRepository(() => mock.Object); + repository.StoreElement(new XElement("Element2"), null); + + mock.Verify(); + Assert.Null(downloadCondition); + Assert.Equal(bytes, GetEnvelopedContent("")); + } + + private static byte[] GetEnvelopedContent(string element) + { + return Encoding.UTF8.GetBytes($"{element}"); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test/AzureDataProtectionBuilderExtensionsTest.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test/AzureDataProtectionBuilderExtensionsTest.cs new file mode 100644 index 0000000000..d386352b73 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test/AzureDataProtectionBuilderExtensionsTest.cs @@ -0,0 +1,32 @@ +// 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 Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.WindowsAzure.Storage.Blob; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AzureStorage +{ + public class AzureDataProtectionBuilderExtensionsTest + { + [Fact] + public void PersistKeysToAzureBlobStorage_UsesAzureBlobXmlRepository() + { + // Arrange + var container = new CloudBlobContainer(new Uri("http://www.example.com")); + var serviceCollection = new ServiceCollection(); + var builder = serviceCollection.AddDataProtection(); + + // Act + builder.PersistKeysToAzureBlobStorage(container, "keys.xml"); + var services = serviceCollection.BuildServiceProvider(); + + // Assert + var options = services.GetRequiredService>(); + Assert.IsType(options.Value.XmlRepository); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test.csproj b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test.csproj new file mode 100644 index 0000000000..8644347572 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test/Microsoft.AspNetCore.DataProtection.AzureStorage.Test.csproj @@ -0,0 +1,17 @@ + + + + $(StandardTestTfms) + true + + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/DataProtectionEntityFrameworkTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/DataProtectionEntityFrameworkTests.cs new file mode 100644 index 0000000000..c298d8e64f --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/DataProtectionEntityFrameworkTests.cs @@ -0,0 +1,69 @@ +// 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 System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; +using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class DataProtectionEntityFrameworkTests + { + [Fact] + public void CreateRepository_ThrowsIf_ContextIsNull() + { + Assert.Throws(() => new EntityFrameworkCoreXmlRepository(null, null)); + } + + [Fact] + public void StoreElement_PersistsData() + { + var element = XElement.Parse(""); + var friendlyName = "Element1"; + var key = new DataProtectionKey() { FriendlyName = friendlyName, Xml = element.ToString() }; + + var services = GetServices(nameof(StoreElement_PersistsData)); + var service = new EntityFrameworkCoreXmlRepository(services, NullLoggerFactory.Instance); + service.StoreElement(element, friendlyName); + + // Use a separate instance of the context to verify correct data was saved to database + using (var context = services.CreateScope().ServiceProvider.GetRequiredService< DataProtectionKeyContext>()) + { + Assert.Equal(1, context.DataProtectionKeys.Count()); + Assert.Equal(key.FriendlyName, context.DataProtectionKeys.Single()?.FriendlyName); + Assert.Equal(key.Xml, context.DataProtectionKeys.Single()?.Xml); + } + } + + [Fact] + public void GetAllElements_ReturnsAllElements() + { + var element1 = XElement.Parse(""); + var element2 = XElement.Parse(""); + + var services = GetServices(nameof(GetAllElements_ReturnsAllElements)); + var service1 = CreateRepo(services); + service1.StoreElement(element1, "element1"); + service1.StoreElement(element2, "element2"); + + // Use a separate instance of the context to verify correct data was saved to database + var service2 = CreateRepo(services); + var elements = service2.GetAllElements(); + Assert.Equal(2, elements.Count); + } + + private EntityFrameworkCoreXmlRepository CreateRepo(IServiceProvider services) + => new EntityFrameworkCoreXmlRepository(services, NullLoggerFactory.Instance); + + private IServiceProvider GetServices(string dbName) + => new ServiceCollection() + .AddDbContext(o => o.UseInMemoryDatabase(dbName)) + .BuildServiceProvider(validateScopes: true); + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/DataProtectionKeyContext.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/DataProtectionKeyContext.cs new file mode 100644 index 0000000000..96151de0bb --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/DataProtectionKeyContext.cs @@ -0,0 +1,14 @@ +// 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 Microsoft.EntityFrameworkCore; + +namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test +{ + class DataProtectionKeyContext : DbContext, IDataProtectionKeyContext + { + public DataProtectionKeyContext(DbContextOptions options) : base(options) { } + + public DbSet DataProtectionKeys { get; set; } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/EntityFrameworkCoreDataProtectionBuilderExtensionsTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/EntityFrameworkCoreDataProtectionBuilderExtensionsTests.cs new file mode 100644 index 0000000000..55b67d98e3 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/EntityFrameworkCoreDataProtectionBuilderExtensionsTests.cs @@ -0,0 +1,26 @@ +// 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 Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test +{ + public class EntityFrameworkCoreDataProtectionBuilderExtensionsTests + { + [Fact] + public void PersistKeysToEntityFrameworkCore_UsesEntityFrameworkCoreXmlRepository() + { + var serviceCollection = new ServiceCollection(); + serviceCollection + .AddDbContext() + .AddDataProtection() + .PersistKeysToDbContext(); + var serviceProvider = serviceCollection.BuildServiceProvider(validateScopes: true); + var keyManagementOptions = serviceProvider.GetRequiredService>(); + Assert.IsType>(keyManagementOptions.Value.XmlRepository); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test.csproj b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test.csproj new file mode 100644 index 0000000000..ed07b79f25 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test.csproj @@ -0,0 +1,15 @@ + + + + $(StandardTestTfms) + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/DataProtectionAdvancedExtensionsTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/DataProtectionAdvancedExtensionsTests.cs new file mode 100644 index 0000000000..c98aff6c8f --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/DataProtectionAdvancedExtensionsTests.cs @@ -0,0 +1,101 @@ +// 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.Globalization; +using System.Text; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class DataProtectionAdvancedExtensionsTests + { + private const string SampleEncodedString = "AQI"; // = WebEncoders.Base64UrlEncode({ 0x01, 0x02 }) + + [Fact] + public void Protect_PayloadAsString_WithExplicitExpiration() + { + // Arrange + var plaintextAsBytes = Encoding.UTF8.GetBytes("this is plaintext"); + var expiration = StringToDateTime("2015-01-01 00:00:00Z"); + var mockDataProtector = new Mock(); + mockDataProtector.Setup(o => o.Protect(plaintextAsBytes, expiration)).Returns(new byte[] { 0x01, 0x02 }); + + // Act + string protectedPayload = mockDataProtector.Object.Protect("this is plaintext", expiration); + + // Assert + Assert.Equal(SampleEncodedString, protectedPayload); + } + + [Fact] + public void Protect_PayloadAsString_WithLifetimeAsTimeSpan() + { + // Arrange + var plaintextAsBytes = Encoding.UTF8.GetBytes("this is plaintext"); + DateTimeOffset actualExpiration = default(DateTimeOffset); + var mockDataProtector = new Mock(); + mockDataProtector.Setup(o => o.Protect(plaintextAsBytes, It.IsAny())) + .Returns((_, exp) => + { + actualExpiration = exp; + return new byte[] { 0x01, 0x02 }; + }); + + // Act + DateTimeOffset lowerBound = DateTimeOffset.UtcNow.AddHours(48); + string protectedPayload = mockDataProtector.Object.Protect("this is plaintext", TimeSpan.FromHours(48)); + DateTimeOffset upperBound = DateTimeOffset.UtcNow.AddHours(48); + + // Assert + Assert.Equal(SampleEncodedString, protectedPayload); + Assert.InRange(actualExpiration, lowerBound, upperBound); + } + + [Fact] + public void Protect_PayloadAsBytes_WithLifetimeAsTimeSpan() + { + // Arrange + DateTimeOffset actualExpiration = default(DateTimeOffset); + var mockDataProtector = new Mock(); + mockDataProtector.Setup(o => o.Protect(new byte[] { 0x11, 0x22, 0x33 }, It.IsAny())) + .Returns((_, exp) => + { + actualExpiration = exp; + return new byte[] { 0x01, 0x02 }; + }); + + // Act + DateTimeOffset lowerBound = DateTimeOffset.UtcNow.AddHours(48); + byte[] protectedPayload = mockDataProtector.Object.Protect(new byte[] { 0x11, 0x22, 0x33 }, TimeSpan.FromHours(48)); + DateTimeOffset upperBound = DateTimeOffset.UtcNow.AddHours(48); + + // Assert + Assert.Equal(new byte[] { 0x01, 0x02 }, protectedPayload); + Assert.InRange(actualExpiration, lowerBound, upperBound); + } + + [Fact] + public void Unprotect_PayloadAsString() + { + // Arrange + var futureDate = DateTimeOffset.UtcNow.AddYears(1); + var controlExpiration = futureDate; + var mockDataProtector = new Mock(); + mockDataProtector.Setup(o => o.Unprotect(new byte[] { 0x01, 0x02 }, out controlExpiration)).Returns(Encoding.UTF8.GetBytes("this is plaintext")); + + // Act + string unprotectedPayload = mockDataProtector.Object.Unprotect(SampleEncodedString, out var testExpiration); + + // Assert + Assert.Equal("this is plaintext", unprotectedPayload); + Assert.Equal(futureDate, testExpiration); + } + + private static DateTime StringToDateTime(string input) + { + return DateTimeOffset.ParseExact(input, "u", CultureInfo.InvariantCulture).UtcDateTime; + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/DataProtectionProviderTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/DataProtectionProviderTests.cs new file mode 100644 index 0000000000..a66ebec2e8 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/DataProtectionProviderTests.cs @@ -0,0 +1,313 @@ +// 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.IO; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Repositories; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class DataProtectionProviderTests + { + [Fact] + public void System_UsesProvidedDirectory() + { + WithUniqueTempDirectory(directory => + { + // Step 1: directory should be completely empty + directory.Create(); + Assert.Empty(directory.GetFiles()); + + // Step 2: instantiate the system and round-trip a payload + var protector = DataProtectionProvider.Create(directory).CreateProtector("purpose"); + Assert.Equal("payload", protector.Unprotect(protector.Protect("payload"))); + + // Step 3: validate that there's now a single key in the directory and that it's not protected + var allFiles = directory.GetFiles(); + Assert.Single(allFiles); + Assert.StartsWith("key-", allFiles[0].Name, StringComparison.OrdinalIgnoreCase); + string fileText = File.ReadAllText(allFiles[0].FullName); + Assert.Contains("Warning: the key below is in an unencrypted form.", fileText, StringComparison.Ordinal); + Assert.DoesNotContain("Windows DPAPI", fileText, StringComparison.Ordinal); + }); + } + + [Fact] + public void System_NoKeysDirectoryProvided_UsesDefaultKeysDirectory() + { + var mock = new Mock(); + var keysPath = Path.Combine(AppContext.BaseDirectory, Path.GetRandomFileName()); + mock.Setup(m => m.GetKeyStorageDirectory()).Returns(new DirectoryInfo(keysPath)); + + // Step 1: Instantiate the system and round-trip a payload + var provider = DataProtectionProvider.CreateProvider( + keyDirectory: null, + certificate: null, + setupAction: builder => + { + builder.SetApplicationName("TestApplication"); + builder.Services.AddSingleton(s => + new XmlKeyManager( + s.GetRequiredService>(), + s.GetRequiredService(), + NullLoggerFactory.Instance, + mock.Object)); + }); + + var protector = provider.CreateProtector("Protector"); + Assert.Equal("payload", protector.Unprotect(protector.Protect("payload"))); + + // Step 2: Validate that there's now a single key in the directory + var newFileName = Assert.Single(Directory.GetFiles(keysPath)); + var file = new FileInfo(newFileName); + Assert.StartsWith("key-", file.Name, StringComparison.OrdinalIgnoreCase); + var fileText = File.ReadAllText(file.FullName); + // On Windows, validate that it's protected using Windows DPAPI. + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Assert.DoesNotContain("Warning: the key below is in an unencrypted form.", fileText, StringComparison.Ordinal); + Assert.Contains("This key is encrypted with Windows DPAPI.", fileText, StringComparison.Ordinal); + } + else + { + Assert.Contains("Warning: the key below is in an unencrypted form.", fileText, StringComparison.Ordinal); + } + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void System_UsesProvidedDirectory_WithConfigurationCallback() + { + WithUniqueTempDirectory(directory => + { + // Step 1: directory should be completely empty + directory.Create(); + Assert.Empty(directory.GetFiles()); + + // Step 2: instantiate the system and round-trip a payload + var protector = DataProtectionProvider.Create(directory, configure => + { + configure.ProtectKeysWithDpapi(); + }).CreateProtector("purpose"); + Assert.Equal("payload", protector.Unprotect(protector.Protect("payload"))); + + // Step 3: validate that there's now a single key in the directory and that it's protected with DPAPI + var allFiles = directory.GetFiles(); + Assert.Single(allFiles); + Assert.StartsWith("key-", allFiles[0].Name, StringComparison.OrdinalIgnoreCase); + string fileText = File.ReadAllText(allFiles[0].FullName); + Assert.DoesNotContain("Warning: the key below is in an unencrypted form.", fileText, StringComparison.Ordinal); + Assert.Contains("Windows DPAPI", fileText, StringComparison.Ordinal); + }); + } + + [ConditionalFact] + [X509StoreIsAvailable(StoreName.My, StoreLocation.CurrentUser)] + public void System_UsesProvidedDirectoryAndCertificate() + { + var filePath = Path.Combine(GetTestFilesPath(), "TestCert.pfx"); + using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) + { + store.Open(OpenFlags.ReadWrite); + store.Add(new X509Certificate2(filePath, "password", X509KeyStorageFlags.Exportable)); + store.Close(); + } + + WithUniqueTempDirectory(directory => + { + var certificateStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); + certificateStore.Open(OpenFlags.ReadWrite); + var certificate = certificateStore.Certificates.Find(X509FindType.FindBySubjectName, "TestCert", false)[0]; + + try + { + // Step 1: directory should be completely empty + directory.Create(); + Assert.Empty(directory.GetFiles()); + + // Step 2: instantiate the system and round-trip a payload + var protector = DataProtectionProvider.Create(directory, certificate).CreateProtector("purpose"); + var data = protector.Protect("payload"); + + // add a cert without the private key to ensure the decryption will still fallback to the cert store + var certWithoutKey = new X509Certificate2(Path.Combine(GetTestFilesPath(), "TestCertWithoutPrivateKey.pfx"), "password"); + var unprotector = DataProtectionProvider.Create(directory, o => o.UnprotectKeysWithAnyCertificate(certWithoutKey)).CreateProtector("purpose"); + Assert.Equal("payload", unprotector.Unprotect(data)); + + // Step 3: validate that there's now a single key in the directory and that it's is protected using the certificate + var allFiles = directory.GetFiles(); + Assert.Single(allFiles); + Assert.StartsWith("key-", allFiles[0].Name, StringComparison.OrdinalIgnoreCase); + string fileText = File.ReadAllText(allFiles[0].FullName); + Assert.DoesNotContain("Warning: the key below is in an unencrypted form.", fileText, StringComparison.Ordinal); + Assert.Contains("X509Certificate", fileText, StringComparison.Ordinal); + } + finally + { + certificateStore.Remove(certificate); + certificateStore.Close(); + } + }); + } + + [ConditionalFact] + [X509StoreIsAvailable(StoreName.My, StoreLocation.CurrentUser)] + public void System_UsesProvidedCertificateNotFromStore() + { + using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) + { + store.Open(OpenFlags.ReadWrite); + var certWithoutKey = new X509Certificate2(Path.Combine(GetTestFilesPath(), "TestCert3WithoutPrivateKey.pfx"), "password3", X509KeyStorageFlags.Exportable); + Assert.False(certWithoutKey.HasPrivateKey, "Cert should not have private key"); + store.Add(certWithoutKey); + store.Close(); + } + + WithUniqueTempDirectory(directory => + { + using (var certificateStore = new X509Store(StoreName.My, StoreLocation.CurrentUser)) + { + certificateStore.Open(OpenFlags.ReadWrite); + var certInStore = certificateStore.Certificates.Find(X509FindType.FindBySubjectName, "TestCert", false)[0]; + Assert.NotNull(certInStore); + Assert.False(certInStore.HasPrivateKey); + + try + { + var certWithKey = new X509Certificate2(Path.Combine(GetTestFilesPath(), "TestCert3.pfx"), "password3"); + + var protector = DataProtectionProvider.Create(directory, certWithKey).CreateProtector("purpose"); + var data = protector.Protect("payload"); + + var keylessUnprotector = DataProtectionProvider.Create(directory).CreateProtector("purpose"); + Assert.Throws(() => keylessUnprotector.Unprotect(data)); + + var unprotector = DataProtectionProvider.Create(directory, o => o.UnprotectKeysWithAnyCertificate(certInStore, certWithKey)).CreateProtector("purpose"); + Assert.Equal("payload", unprotector.Unprotect(data)); + } + finally + { + certificateStore.Remove(certInStore); + certificateStore.Close(); + } + } + }); + } + + [Fact] + public void System_UsesInMemoryCertificate() + { + var filePath = Path.Combine(GetTestFilesPath(), "TestCert2.pfx"); + var certificate = new X509Certificate2(filePath, "password"); + + AssetStoreDoesNotContain(certificate); + + WithUniqueTempDirectory(directory => + { + // Step 1: directory should be completely empty + directory.Create(); + Assert.Empty(directory.GetFiles()); + + // Step 2: instantiate the system and round-trip a payload + var protector = DataProtectionProvider.Create(directory, certificate).CreateProtector("purpose"); + Assert.Equal("payload", protector.Unprotect(protector.Protect("payload"))); + + // Step 3: validate that there's now a single key in the directory and that it's is protected using the certificate + var allFiles = directory.GetFiles(); + Assert.Single(allFiles); + Assert.StartsWith("key-", allFiles[0].Name, StringComparison.OrdinalIgnoreCase); + string fileText = File.ReadAllText(allFiles[0].FullName); + Assert.DoesNotContain("Warning: the key below is in an unencrypted form.", fileText, StringComparison.Ordinal); + Assert.Contains("X509Certificate", fileText, StringComparison.Ordinal); + }); + } + + private static void AssetStoreDoesNotContain(X509Certificate2 certificate) + { + using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) + { + try + { + store.Open(OpenFlags.ReadOnly); + } + catch + { + return; + } + + // ensure this cert is not in the x509 store + Assert.Empty(store.Certificates.Find(X509FindType.FindByThumbprint, certificate.Thumbprint, false)); + } + } + + [Fact] + public void System_CanUnprotectWithCert() + { + var filePath = Path.Combine(GetTestFilesPath(), "TestCert2.pfx"); + var certificate = new X509Certificate2(filePath, "password"); + + WithUniqueTempDirectory(directory => + { + // Step 1: directory should be completely empty + directory.Create(); + Assert.Empty(directory.GetFiles()); + + // Step 2: instantiate the system and create some data + var protector = DataProtectionProvider + .Create(directory, certificate) + .CreateProtector("purpose"); + + var data = protector.Protect("payload"); + + // Step 3: validate that there's now a single key in the directory and that it's is protected using the certificate + var allFiles = directory.GetFiles(); + Assert.Single(allFiles); + Assert.StartsWith("key-", allFiles[0].Name, StringComparison.OrdinalIgnoreCase); + string fileText = File.ReadAllText(allFiles[0].FullName); + Assert.DoesNotContain("Warning: the key below is in an unencrypted form.", fileText, StringComparison.Ordinal); + Assert.Contains("X509Certificate", fileText, StringComparison.Ordinal); + + // Step 4: setup a second system and validate it can decrypt keys and unprotect data + var unprotector = DataProtectionProvider.Create(directory, + b => b.UnprotectKeysWithAnyCertificate(certificate)); + Assert.Equal("payload", unprotector.CreateProtector("purpose").Unprotect(data)); + }); + } + + /// + /// Runs a test and cleans up the temp directory afterward. + /// + private static void WithUniqueTempDirectory(Action testCode) + { + string uniqueTempPath = Path.Combine(AppContext.BaseDirectory, Path.GetRandomFileName()); + var dirInfo = new DirectoryInfo(uniqueTempPath); + try + { + testCode(dirInfo); + } + finally + { + // clean up when test is done + if (dirInfo.Exists) + { + dirInfo.Delete(recursive: true); + } + } + } + + private static string GetTestFilesPath() + => Path.Combine(AppContext.BaseDirectory, "TestFiles"); + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/Microsoft.AspNetCore.DataProtection.Extensions.Test.csproj b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/Microsoft.AspNetCore.DataProtection.Extensions.Test.csproj new file mode 100644 index 0000000000..16a4f12c98 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/Microsoft.AspNetCore.DataProtection.Extensions.Test.csproj @@ -0,0 +1,17 @@ + + + + $(StandardTestTfms) + + + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/Properties/AssemblyInfo.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..a613784a32 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// 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 Xunit; + +// Workaround for DataProtectionProviderTests.System_UsesProvidedDirectoryAndCertificate +// https://github.com/aspnet/DataProtection/issues/160 +[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)] \ No newline at end of file diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert.pfx b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert.pfx new file mode 100644 index 0000000000..266754e8ee Binary files /dev/null and b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert.pfx differ diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert2.pfx b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert2.pfx new file mode 100644 index 0000000000..4ed9bbe394 Binary files /dev/null and b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert2.pfx differ diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert3.pfx b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert3.pfx new file mode 100644 index 0000000000..364251ba09 Binary files /dev/null and b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert3.pfx differ diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert3WithoutPrivateKey.pfx b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert3WithoutPrivateKey.pfx new file mode 100644 index 0000000000..9776e9006d Binary files /dev/null and b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCert3WithoutPrivateKey.pfx differ diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCertWithoutPrivateKey.pfx b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCertWithoutPrivateKey.pfx new file mode 100644 index 0000000000..812374c50c Binary files /dev/null and b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TestFiles/TestCertWithoutPrivateKey.pfx differ diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TimeLimitedDataProtectorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TimeLimitedDataProtectorTests.cs new file mode 100644 index 0000000000..47dfc26fd7 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/TimeLimitedDataProtectorTests.cs @@ -0,0 +1,180 @@ +// 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.Globalization; +using System.Security.Cryptography; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; +using ExtResources = Microsoft.AspNetCore.DataProtection.Extensions.Resources; + +namespace Microsoft.AspNetCore.DataProtection +{ + + public class TimeLimitedDataProtectorTests + { + private const string TimeLimitedPurposeString = "Microsoft.AspNetCore.DataProtection.TimeLimitedDataProtector.v1"; + + [Fact] + public void Protect_LifetimeSpecified() + { + // Arrange + // 0x08c1220247e44000 is the representation of midnight 2000-01-01 UTC. + DateTimeOffset expiration = StringToDateTime("2000-01-01 00:00:00Z"); + var mockInnerProtector = new Mock(); + mockInnerProtector.Setup(o => o.CreateProtector("new purpose").CreateProtector(TimeLimitedPurposeString).Protect( + new byte[] { + 0x08, 0xc1, 0x22, 0x02, 0x47, 0xe4, 0x40, 0x00, /* header */ + 0x01, 0x02, 0x03, 0x04, 0x05 /* payload */ + })).Returns(new byte[] { 0x10, 0x11 }); + + var timeLimitedProtector = new TimeLimitedDataProtector(mockInnerProtector.Object); + + // Act + var subProtector = timeLimitedProtector.CreateProtector("new purpose"); + var protectedPayload = subProtector.Protect(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }, expiration); + + // Assert + Assert.Equal(new byte[] { 0x10, 0x11 }, protectedPayload); + } + + [Fact] + public void Protect_LifetimeNotSpecified_UsesInfiniteLifetime() + { + // Arrange + // 0x2bca2875f4373fff is the representation of DateTimeOffset.MaxValue. + DateTimeOffset expiration = StringToDateTime("2000-01-01 00:00:00Z"); + var mockInnerProtector = new Mock(); + mockInnerProtector.Setup(o => o.CreateProtector("new purpose").CreateProtector(TimeLimitedPurposeString).Protect( + new byte[] { + 0x2b, 0xca, 0x28, 0x75, 0xf4, 0x37, 0x3f, 0xff, /* header */ + 0x01, 0x02, 0x03, 0x04, 0x05 /* payload */ + })).Returns(new byte[] { 0x10, 0x11 }); + + var timeLimitedProtector = new TimeLimitedDataProtector(mockInnerProtector.Object); + + // Act + var subProtector = timeLimitedProtector.CreateProtector("new purpose"); + var protectedPayload = subProtector.Protect(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }); + + // Assert + Assert.Equal(new byte[] { 0x10, 0x11 }, protectedPayload); + } + + [Fact] + public void Unprotect_WithinPayloadValidityPeriod_Success() + { + // Arrange + // 0x08c1220247e44000 is the representation of midnight 2000-01-01 UTC. + DateTimeOffset expectedExpiration = StringToDateTime("2000-01-01 00:00:00Z"); + DateTimeOffset now = StringToDateTime("1999-01-01 00:00:00Z"); + var mockInnerProtector = new Mock(); + mockInnerProtector.Setup(o => o.CreateProtector(TimeLimitedPurposeString).Unprotect(new byte[] { 0x10, 0x11 })).Returns( + new byte[] { + 0x08, 0xc1, 0x22, 0x02, 0x47, 0xe4, 0x40, 0x00, /* header */ + 0x01, 0x02, 0x03, 0x04, 0x05 /* payload */ + }); + + var timeLimitedProtector = new TimeLimitedDataProtector(mockInnerProtector.Object); + + // Act + var retVal = timeLimitedProtector.UnprotectCore(new byte[] { 0x10, 0x11 }, now, out var actualExpiration); + + // Assert + Assert.Equal(expectedExpiration, actualExpiration); + Assert.Equal(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }, retVal); + } + + [Fact] + public void Unprotect_PayloadHasExpired_Fails() + { + // Arrange + // 0x08c1220247e44000 is the representation of midnight 2000-01-01 UTC. + DateTimeOffset expectedExpiration = StringToDateTime("2000-01-01 00:00:00Z"); + DateTimeOffset now = StringToDateTime("2001-01-01 00:00:00Z"); + var mockInnerProtector = new Mock(); + mockInnerProtector.Setup(o => o.CreateProtector(TimeLimitedPurposeString).Unprotect(new byte[] { 0x10, 0x11 })).Returns( + new byte[] { + 0x08, 0xc1, 0x22, 0x02, 0x47, 0xe4, 0x40, 0x00, /* header */ + 0x01, 0x02, 0x03, 0x04, 0x05 /* payload */ + }); + + var timeLimitedProtector = new TimeLimitedDataProtector(mockInnerProtector.Object); + + // Act & assert + var ex = Assert.Throws(() + => timeLimitedProtector.UnprotectCore(new byte[] { 0x10, 0x11 }, now, out var _)); + + // Assert + Assert.Equal(ExtResources.FormatTimeLimitedDataProtector_PayloadExpired(expectedExpiration), ex.Message); + } + + [Fact] + public void Unprotect_ProtectedDataMalformed_Fails() + { + // Arrange + // 0x08c1220247e44000 is the representation of midnight 2000-01-01 UTC. + var mockInnerProtector = new Mock(); + mockInnerProtector.Setup(o => o.CreateProtector(TimeLimitedPurposeString).Unprotect(new byte[] { 0x10, 0x11 })).Returns( + new byte[] { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 /* header too short */ + }); + + var timeLimitedProtector = new TimeLimitedDataProtector(mockInnerProtector.Object); + + // Act & assert + var ex = Assert.Throws(() + => timeLimitedProtector.Unprotect(new byte[] { 0x10, 0x11 }, out var _)); + + // Assert + Assert.Equal(ExtResources.TimeLimitedDataProtector_PayloadInvalid, ex.Message); + } + + [Fact] + public void Unprotect_UnprotectOperationFails_HomogenizesExceptionToCryptographicException() + { + // Arrange + // 0x08c1220247e44000 is the representation of midnight 2000-01-01 UTC. + var mockInnerProtector = new Mock(); + mockInnerProtector.Setup(o => o.CreateProtector(TimeLimitedPurposeString).Unprotect(new byte[] { 0x10, 0x11 })).Throws(new Exception("How exceptional!")); + var timeLimitedProtector = new TimeLimitedDataProtector(mockInnerProtector.Object); + + // Act & assert + var ex = Assert.Throws(() + => timeLimitedProtector.Unprotect(new byte[] { 0x10, 0x11 }, out var _)); + + // Assert + Assert.Equal(Resources.CryptCommon_GenericError, ex.Message); + Assert.Equal("How exceptional!", ex.InnerException.Message); + } + + [Fact] + public void RoundTrip_ProtectedData() + { + // Arrange + var ephemeralProtector = new EphemeralDataProtectionProvider(NullLoggerFactory.Instance).CreateProtector("my purpose"); + var timeLimitedProtector = new TimeLimitedDataProtector(ephemeralProtector); + var expectedExpiration = StringToDateTime("2020-01-01 00:00:00Z"); + + // Act + byte[] ephemeralProtectedPayload = ephemeralProtector.Protect(new byte[] { 0x01, 0x02, 0x03, 0x04 }); + byte[] timeLimitedProtectedPayload = timeLimitedProtector.Protect(new byte[] { 0x11, 0x22, 0x33, 0x44 }, expectedExpiration); + + // Assert + Assert.Equal( + new byte[] { 0x11, 0x22, 0x33, 0x44 }, + timeLimitedProtector.UnprotectCore(timeLimitedProtectedPayload, StringToDateTime("2010-01-01 00:00:00Z"), out var actualExpiration)); + Assert.Equal(expectedExpiration, actualExpiration); + + // the two providers shouldn't be able to talk to one another (due to the purpose chaining) + Assert.Throws(() => ephemeralProtector.Unprotect(timeLimitedProtectedPayload)); + Assert.Throws(() => timeLimitedProtector.Unprotect(ephemeralProtectedPayload, out actualExpiration)); + } + + private static DateTime StringToDateTime(string input) + { + return DateTimeOffset.ParseExact(input, "u", CultureInfo.InvariantCulture).UtcDateTime; + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/X509StoreIsAvailableAttribute.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/X509StoreIsAvailableAttribute.cs new file mode 100644 index 0000000000..2181b4c24f --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Extensions.Test/X509StoreIsAvailableAttribute.cs @@ -0,0 +1,43 @@ +// 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.Security.Cryptography.X509Certificates; +using Microsoft.AspNetCore.Testing.xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + [AttributeUsage(AttributeTargets.Method)] + public class X509StoreIsAvailableAttribute : Attribute, ITestCondition + { + public X509StoreIsAvailableAttribute(StoreName name, StoreLocation location) + { + Name = name; + Location = location; + } + + public bool IsMet + { + get + { + try + { + using (var store = new X509Store(Name, Location)) + { + store.Open(OpenFlags.ReadWrite); + return true; + } + } + catch + { + return false; + } + } + } + + public string SkipReason => $"Skipping because the X509Store({Name}/{Location}) is not available on this machine."; + + public StoreName Name { get; } + public StoreLocation Location { get; } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/DataProtectionRedisTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/DataProtectionRedisTests.cs new file mode 100644 index 0000000000..a204050ad1 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/DataProtectionRedisTests.cs @@ -0,0 +1,110 @@ +// 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 System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; +using Microsoft.AspNetCore.Testing; +using Microsoft.AspNetCore.Testing.xunit; +using Moq; +using StackExchange.Redis; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.DataProtection.StackExchangeRedis +{ + public class DataProtectionRedisTests + { + private readonly ITestOutputHelper _output; + + public DataProtectionRedisTests(ITestOutputHelper output) + { + _output = output; + } + + [Fact] + public void GetAllElements_ReturnsAllXmlValuesForGivenKey() + { + var database = new Mock(); + database.Setup(d => d.ListRange("Key", 0, -1, CommandFlags.None)).Returns(new RedisValue[] + { + "", + "", + }).Verifiable(); + var repo = new RedisXmlRepository(() => database.Object, "Key"); + + var elements = repo.GetAllElements().ToArray(); + + database.Verify(); + Assert.Equal(new XElement("Element1").ToString(), elements[0].ToString()); + Assert.Equal(new XElement("Element2").ToString(), elements[1].ToString()); + } + + [Fact] + public void GetAllElements_ThrowsParsingException() + { + var database = new Mock(); + database.Setup(d => d.ListRange("Key", 0, -1, CommandFlags.None)).Returns(new RedisValue[] + { + "", + " database.Object, "Key"); + + Assert.Throws(() => repo.GetAllElements()); + } + + [Fact] + public void StoreElement_PushesValueToList() + { + var database = new Mock(); + database.Setup(d => d.ListRightPush("Key", "", When.Always, CommandFlags.None)).Verifiable(); + var repo = new RedisXmlRepository(() => database.Object, "Key"); + + repo.StoreElement(new XElement("Element2"), null); + + database.Verify(); + } + + [ConditionalFact] + [TestRedisServerIsAvailable] + public async Task XmlRoundTripsToActualRedisServer() + { + var connStr = TestRedisServer.GetConnectionString(); + + _output.WriteLine("Attempting to connect to " + connStr); + + var guid = Guid.NewGuid().ToString(); + RedisKey key = "Test:DP:Key" + guid; + + try + { + using (var redis = await ConnectionMultiplexer.ConnectAsync(connStr).TimeoutAfter(TimeSpan.FromMinutes(1))) + { + var repo = new RedisXmlRepository(() => redis.GetDatabase(), key); + var element = new XElement("HelloRedis", guid); + repo.StoreElement(element, guid); + } + + using (var redis = await ConnectionMultiplexer.ConnectAsync(connStr).TimeoutAfter(TimeSpan.FromMinutes(1))) + { + var repo = new RedisXmlRepository(() => redis.GetDatabase(), key); + var elements = repo.GetAllElements(); + + Assert.Contains(elements, e => e.Name == "HelloRedis" && e.Value == guid); + } + } + finally + { + // cleanup + using (var redis = await ConnectionMultiplexer.ConnectAsync(connStr).TimeoutAfter(TimeSpan.FromMinutes(1))) + { + await redis.GetDatabase().KeyDeleteAsync(key); + } + } + + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test.csproj b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test.csproj new file mode 100644 index 0000000000..87f9f318bc --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test.csproj @@ -0,0 +1,28 @@ + + + + $(StandardTestTfms) + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/RedisDataProtectionBuilderExtensionsTest.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/RedisDataProtectionBuilderExtensionsTest.cs new file mode 100644 index 0000000000..2b4c2865c3 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/RedisDataProtectionBuilderExtensionsTest.cs @@ -0,0 +1,32 @@ +// 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 Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Moq; +using StackExchange.Redis; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.StackExchangeRedis +{ + public class RedisDataProtectionBuilderExtensionsTest + { + [Fact] + public void PersistKeysToRedis_UsesRedisXmlRepository() + { + // Arrange + var connection = Mock.Of(); + var serviceCollection = new ServiceCollection(); + var builder = serviceCollection.AddDataProtection(); + + // Act + builder.PersistKeysToStackExchangeRedis(connection); + var services = serviceCollection.BuildServiceProvider(); + + // Assert + var options = services.GetRequiredService>(); + Assert.IsType(options.Value.XmlRepository); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/TestRedisServer.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/TestRedisServer.cs new file mode 100644 index 0000000000..dfe369625a --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/TestRedisServer.cs @@ -0,0 +1,28 @@ +// 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 Microsoft.Extensions.Configuration; +using System; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal class TestRedisServer + { + public const string ConnectionStringKeyName = "Test:Redis:Server"; + private static readonly IConfigurationRoot _config; + + static TestRedisServer() + { + _config = new ConfigurationBuilder() + .SetBasePath(AppContext.BaseDirectory) + .AddJsonFile("testconfig.json") + .AddEnvironmentVariables() + .Build(); + } + + internal static string GetConnectionString() + { + return _config[ConnectionStringKeyName]; + } + } +} \ No newline at end of file diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/TestRedisServerIsAvailableAttribute.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/TestRedisServerIsAvailableAttribute.cs new file mode 100644 index 0000000000..04857c494b --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/TestRedisServerIsAvailableAttribute.cs @@ -0,0 +1,15 @@ +// 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 Microsoft.AspNetCore.Testing.xunit; +using System; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal class TestRedisServerIsAvailableAttribute : Attribute, ITestCondition + { + public bool IsMet => !string.IsNullOrEmpty(TestRedisServer.GetConnectionString()); + + public string SkipReason => $"A test redis server must be configured to run. Set the connection string as an environment variable as {TestRedisServer.ConnectionStringKeyName.Replace(":", "__")} or in testconfig.json"; + } +} \ No newline at end of file diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/testconfig.json b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/testconfig.json new file mode 100644 index 0000000000..2e2f447946 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Test/testconfig.json @@ -0,0 +1,10 @@ +{ + "Test": { + "Redis": { + // You can setup a local Redis server easily with Docker by running + // docker run --rm -it -p 6379:6379 redis + // Then uncomment this config below + // "Server": "localhost:6379,127.0.0.1:6379" + } + } +} \ No newline at end of file diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/ActivatorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/ActivatorTests.cs new file mode 100644 index 0000000000..a249162706 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/ActivatorTests.cs @@ -0,0 +1,117 @@ +// 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 Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class ActivatorTests + { + [Fact] + public void CreateInstance_WithServiceProvider_PrefersParameterfulCtor() + { + // Arrange + var serviceCollection = new ServiceCollection(); + var services = serviceCollection.BuildServiceProvider(); + var activator = services.GetActivator(); + + // Act + var retVal1 = (ClassWithParameterlessCtor)activator.CreateInstance(typeof(ClassWithParameterlessCtor).AssemblyQualifiedName); + var retVal2 = (ClassWithServiceProviderCtor)activator.CreateInstance(typeof(ClassWithServiceProviderCtor).AssemblyQualifiedName); + var retVal3 = (ClassWithBothCtors)activator.CreateInstance(typeof(ClassWithBothCtors).AssemblyQualifiedName); + + // Assert + Assert.NotNull(services); + Assert.NotNull(retVal1); + Assert.NotNull(retVal2); + Assert.Same(services, retVal2.Services); + Assert.NotNull(retVal3); + Assert.False(retVal3.ParameterlessCtorCalled); + Assert.Same(services, retVal3.Services); + } + + [Fact] + public void CreateInstance_WithoutServiceProvider_PrefersParameterlessCtor() + { + // Arrange + var activator = ((IServiceProvider)null).GetActivator(); + + // Act + var retVal1 = (ClassWithParameterlessCtor)activator.CreateInstance(typeof(ClassWithParameterlessCtor).AssemblyQualifiedName); + var retVal2 = (ClassWithServiceProviderCtor)activator.CreateInstance(typeof(ClassWithServiceProviderCtor).AssemblyQualifiedName); + var retVal3 = (ClassWithBothCtors)activator.CreateInstance(typeof(ClassWithBothCtors).AssemblyQualifiedName); + + // Assert + Assert.NotNull(retVal1); + Assert.NotNull(retVal2); + Assert.Null(retVal2.Services); + Assert.NotNull(retVal3); + Assert.True(retVal3.ParameterlessCtorCalled); + Assert.Null(retVal3.Services); + } + + + [Fact] + public void CreateInstance_TypeDoesNotImplementInterface_ThrowsInvalidCast() + { + // Arrange + var activator = ((IServiceProvider)null).GetActivator(); + + // Act & assert + var ex = Assert.Throws( + () => activator.CreateInstance(typeof(ClassWithParameterlessCtor).AssemblyQualifiedName)); + Assert.Equal(Resources.FormatTypeExtensions_BadCast(typeof(IDisposable).AssemblyQualifiedName, typeof(ClassWithParameterlessCtor).AssemblyQualifiedName), ex.Message); + } + + [Fact] + public void GetActivator_ServiceProviderHasActivator_ReturnsSameInstance() + { + // Arrange + var expectedActivator = new Mock().Object; + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(expectedActivator); + + // Act + var actualActivator = serviceCollection.BuildServiceProvider().GetActivator(); + + // Assert + Assert.Same(expectedActivator, actualActivator); + } + + private class ClassWithParameterlessCtor + { + } + + private class ClassWithServiceProviderCtor + { + public readonly IServiceProvider Services; + + public ClassWithServiceProviderCtor(IServiceProvider services) + { + Services = services; + } + } + + private class ClassWithBothCtors + { + public readonly IServiceProvider Services; + public readonly bool ParameterlessCtorCalled; + + public ClassWithBothCtors() + { + ParameterlessCtorCalled = true; + Services = null; + } + + public ClassWithBothCtors(IServiceProvider services) + { + ParameterlessCtorCalled = false; + Services = services; + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AnonymousImpersonation.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AnonymousImpersonation.cs new file mode 100644 index 0000000000..e142b698e7 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AnonymousImpersonation.cs @@ -0,0 +1,92 @@ +// 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. + +#if NET461 +using System; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.Win32.SafeHandles; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Helpers for working with the anonymous Windows identity. + /// + internal static class AnonymousImpersonation + { + /// + /// Performs an action while impersonated under the anonymous user (NT AUTHORITY\ANONYMOUS LOGIN). + /// + public static void Run(Action callback) + { + using (var threadHandle = ThreadHandle.OpenCurrentThreadHandle()) + { + bool impersonated = false; + try + { + impersonated = ImpersonateAnonymousToken(threadHandle); + if (!impersonated) + { + Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); + } + callback(); + } + finally + { + if (impersonated && !RevertToSelf()) + { + Environment.FailFast("RevertToSelf() returned false!"); + } + } + } + } + + [DllImport("advapi32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + private static extern bool ImpersonateAnonymousToken([In] ThreadHandle ThreadHandle); + + [DllImport("advapi32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + private static extern bool RevertToSelf(); + + private sealed class ThreadHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private ThreadHandle() + : base(ownsHandle: true) + { + } + + public static ThreadHandle OpenCurrentThreadHandle() + { + const int THREAD_ALL_ACCESS = 0x1FFFFF; + var handle = OpenThread( + dwDesiredAccess: THREAD_ALL_ACCESS, + bInheritHandle: false, +#pragma warning disable CS0618 // Type or member is obsolete + dwThreadId: (uint)AppDomain.GetCurrentThreadId()); +#pragma warning restore CS0618 // Type or member is obsolete + CryptoUtil.AssertSafeHandleIsValid(handle); + return handle; + } + + protected override bool ReleaseHandle() + { + return CloseHandle(handle); + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + private static extern bool CloseHandle( + [In] IntPtr hObject); + + [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + private static extern ThreadHandle OpenThread( + [In] uint dwDesiredAccess, + [In] bool bInheritHandle, + [In] uint dwThreadId); + } + } +} +#elif NETCOREAPP3_0 +#else +#error Target framework needs to be updated +#endif diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorFactoryTest.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorFactoryTest.cs new file mode 100644 index 0000000000..2b13d7990c --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorFactoryTest.cs @@ -0,0 +1,52 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + public class CngCbcAuthenticatedEncryptorFactoryTest + { + [Fact] + public void CreateEncrptorInstance_UnknownDescriptorType_ReturnsNull() + { + // Arrange + var key = new Mock(); + key.Setup(k => k.Descriptor).Returns(new Mock().Object); + + var factory = new CngCbcAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + + // Act + var encryptor = factory.CreateEncryptorInstance(key.Object); + + // Assert + Assert.Null(encryptor); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void CreateEncrptorInstance_ExpectedDescriptorType_ReturnsEncryptor() + { + // Arrange + var descriptor = new CngCbcAuthenticatedEncryptorConfiguration().CreateNewDescriptor(); + var key = new Mock(); + key.Setup(k => k.Descriptor).Returns(descriptor); + + var factory = new CngCbcAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + + // Act + var encryptor = factory.CreateEncryptorInstance(key.Object); + + // Assert + Assert.NotNull(encryptor); + Assert.IsType(encryptor); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorFactoryTest.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorFactoryTest.cs new file mode 100644 index 0000000000..e641705f3a --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorFactoryTest.cs @@ -0,0 +1,52 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + public class CngGcmAuthenticatedEncryptorFactoryTest + { + [Fact] + public void CreateEncrptorInstance_UnknownDescriptorType_ReturnsNull() + { + // Arrange + var key = new Mock(); + key.Setup(k => k.Descriptor).Returns(new Mock().Object); + + var factory = new CngGcmAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + + // Act + var encryptor = factory.CreateEncryptorInstance(key.Object); + + // Assert + Assert.Null(encryptor); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void CreateEncrptorInstance_ExpectedDescriptorType_ReturnsEncryptor() + { + // Arrange + var descriptor = new CngGcmAuthenticatedEncryptorConfiguration().CreateNewDescriptor(); + var key = new Mock(); + key.Setup(k => k.Descriptor).Returns(descriptor); + + var factory = new CngGcmAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + + // Act + var encryptor = factory.CreateEncryptorInstance(key.Object); + + // Assert + Assert.NotNull(encryptor); + Assert.IsType(encryptor); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializerTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializerTests.cs new file mode 100644 index 0000000000..e7ef5d69c7 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializerTests.cs @@ -0,0 +1,59 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class AuthenticatedEncryptorDescriptorDeserializerTests + { + [Fact] + public void ImportFromXml_Cbc_CreatesAppropriateDescriptor() + { + // Arrange + var descriptor = new AuthenticatedEncryptorDescriptor( + new AuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = EncryptionAlgorithm.AES_192_CBC, + ValidationAlgorithm = ValidationAlgorithm.HMACSHA512 + }, + "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret()); + var control = CreateEncryptorInstanceFromDescriptor(descriptor); + + const string xml = @" + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + "; + var deserializedDescriptor = new AuthenticatedEncryptorDescriptorDeserializer().ImportFromXml(XElement.Parse(xml)); + var test = CreateEncryptorInstanceFromDescriptor(deserializedDescriptor as AuthenticatedEncryptorDescriptor); + + // Act & assert + byte[] plaintext = new byte[] { 1, 2, 3, 4, 5 }; + byte[] aad = new byte[] { 2, 4, 6, 8, 0 }; + byte[] ciphertext = control.Encrypt(new ArraySegment(plaintext), new ArraySegment(aad)); + byte[] roundTripPlaintext = test.Decrypt(new ArraySegment(ciphertext), new ArraySegment(aad)); + Assert.Equal(plaintext, roundTripPlaintext); + } + + private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(AuthenticatedEncryptorDescriptor descriptor) + { + var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + var key = new Key( + Guid.NewGuid(), + DateTimeOffset.Now, + DateTimeOffset.Now + TimeSpan.FromHours(1), + DateTimeOffset.Now + TimeSpan.FromDays(30), + descriptor, + new[] { encryptorFactory }); + + + return key.CreateEncryptor(); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorTests.cs new file mode 100644 index 0000000000..0bed1de2e4 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorTests.cs @@ -0,0 +1,189 @@ +// 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.Globalization; +using System.Security.Cryptography; +using System.Text.RegularExpressions; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Cryptography.SafeHandles; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Managed; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class AuthenticatedEncryptorDescriptorTests + { + [ConditionalTheory] + [ConditionalRunTestOnlyOnWindows] + [InlineData(EncryptionAlgorithm.AES_128_CBC, ValidationAlgorithm.HMACSHA256)] + [InlineData(EncryptionAlgorithm.AES_192_CBC, ValidationAlgorithm.HMACSHA256)] + [InlineData(EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm.HMACSHA256)] + [InlineData(EncryptionAlgorithm.AES_128_CBC, ValidationAlgorithm.HMACSHA512)] + [InlineData(EncryptionAlgorithm.AES_192_CBC, ValidationAlgorithm.HMACSHA512)] + [InlineData(EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm.HMACSHA512)] + public void CreateAuthenticatedEncryptor_RoundTripsData_CngCbcImplementation(EncryptionAlgorithm encryptionAlgorithm, ValidationAlgorithm validationAlgorithm) + { + // Parse test input + int keyLengthInBits = Int32.Parse(Regex.Match(encryptionAlgorithm.ToString(), @"^AES_(?\d{3})_CBC$").Groups["keyLength"].Value, CultureInfo.InvariantCulture); + string hashAlgorithm = Regex.Match(validationAlgorithm.ToString(), @"^HMAC(?.*)$").Groups["hashAlgorithm"].Value; + + // Arrange + var masterKey = Secret.Random(512 / 8); + var control = new CbcAuthenticatedEncryptor( + keyDerivationKey: masterKey, + symmetricAlgorithmHandle: CachedAlgorithmHandles.AES_CBC, + symmetricAlgorithmKeySizeInBytes: (uint)(keyLengthInBits / 8), + hmacAlgorithmHandle: BCryptAlgorithmHandle.OpenAlgorithmHandle(hashAlgorithm, hmac: true)); + var test = CreateEncryptorInstanceFromDescriptor(CreateDescriptor(encryptionAlgorithm, validationAlgorithm, masterKey)); + + // Act & assert - data round trips properly from control to test + byte[] plaintext = new byte[] { 1, 2, 3, 4, 5 }; + byte[] aad = new byte[] { 2, 4, 6, 8, 0 }; + byte[] ciphertext = control.Encrypt(new ArraySegment(plaintext), new ArraySegment(aad)); + byte[] roundTripPlaintext = test.Decrypt(new ArraySegment(ciphertext), new ArraySegment(aad)); + Assert.Equal(plaintext, roundTripPlaintext); + } + + [ConditionalTheory] + [ConditionalRunTestOnlyOnWindows] + [InlineData(EncryptionAlgorithm.AES_128_GCM)] + [InlineData(EncryptionAlgorithm.AES_192_GCM)] + [InlineData(EncryptionAlgorithm.AES_256_GCM)] + public void CreateAuthenticatedEncryptor_RoundTripsData_CngGcmImplementation(EncryptionAlgorithm encryptionAlgorithm) + { + // Parse test input + int keyLengthInBits = Int32.Parse(Regex.Match(encryptionAlgorithm.ToString(), @"^AES_(?\d{3})_GCM$").Groups["keyLength"].Value, CultureInfo.InvariantCulture); + + // Arrange + var masterKey = Secret.Random(512 / 8); + var control = new GcmAuthenticatedEncryptor( + keyDerivationKey: masterKey, + symmetricAlgorithmHandle: CachedAlgorithmHandles.AES_GCM, + symmetricAlgorithmKeySizeInBytes: (uint)(keyLengthInBits / 8)); + var test = CreateEncryptorInstanceFromDescriptor(CreateDescriptor(encryptionAlgorithm, ValidationAlgorithm.HMACSHA256 /* unused */, masterKey)); + + // Act & assert - data round trips properly from control to test + byte[] plaintext = new byte[] { 1, 2, 3, 4, 5 }; + byte[] aad = new byte[] { 2, 4, 6, 8, 0 }; + byte[] ciphertext = control.Encrypt(new ArraySegment(plaintext), new ArraySegment(aad)); + byte[] roundTripPlaintext = test.Decrypt(new ArraySegment(ciphertext), new ArraySegment(aad)); + Assert.Equal(plaintext, roundTripPlaintext); + } + + public static TheoryData CreateAuthenticatedEncryptor_RoundTripsData_ManagedImplementationData + => new TheoryData> + { + { EncryptionAlgorithm.AES_128_CBC, ValidationAlgorithm.HMACSHA256, () => new HMACSHA256() }, + { EncryptionAlgorithm.AES_192_CBC, ValidationAlgorithm.HMACSHA256, () => new HMACSHA256() }, + { EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm.HMACSHA256, () => new HMACSHA256() }, + { EncryptionAlgorithm.AES_128_CBC, ValidationAlgorithm.HMACSHA512, () => new HMACSHA512() }, + { EncryptionAlgorithm.AES_192_CBC, ValidationAlgorithm.HMACSHA512, () => new HMACSHA512() }, + { EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm.HMACSHA512, () => new HMACSHA512() }, + }; + + [Theory] + [MemberData(nameof(CreateAuthenticatedEncryptor_RoundTripsData_ManagedImplementationData))] + public void CreateAuthenticatedEncryptor_RoundTripsData_ManagedImplementation( + EncryptionAlgorithm encryptionAlgorithm, + ValidationAlgorithm validationAlgorithm, + Func validationAlgorithmFactory) + { + // Parse test input + int keyLengthInBits = Int32.Parse(Regex.Match(encryptionAlgorithm.ToString(), @"^AES_(?\d{3})_CBC$").Groups["keyLength"].Value, CultureInfo.InvariantCulture); + + // Arrange + var masterKey = Secret.Random(512 / 8); + var control = new ManagedAuthenticatedEncryptor( + keyDerivationKey: masterKey, + symmetricAlgorithmFactory: () => Aes.Create(), + symmetricAlgorithmKeySizeInBytes: keyLengthInBits / 8, + validationAlgorithmFactory: validationAlgorithmFactory); + var test = CreateEncryptorInstanceFromDescriptor(CreateDescriptor(encryptionAlgorithm, validationAlgorithm, masterKey)); + + // Act & assert - data round trips properly from control to test + byte[] plaintext = new byte[] { 1, 2, 3, 4, 5 }; + byte[] aad = new byte[] { 2, 4, 6, 8, 0 }; + byte[] ciphertext = control.Encrypt(new ArraySegment(plaintext), new ArraySegment(aad)); + byte[] roundTripPlaintext = test.Decrypt(new ArraySegment(ciphertext), new ArraySegment(aad)); + Assert.Equal(plaintext, roundTripPlaintext); + } + + [Fact] + public void ExportToXml_ProducesCorrectPayload_Cbc() + { + // Arrange + var masterKey = "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret(); + var descriptor = CreateDescriptor(EncryptionAlgorithm.AES_192_CBC, ValidationAlgorithm.HMACSHA512, masterKey); + + // Act + var retVal = descriptor.ExportToXml(); + + // Assert + Assert.Equal(typeof(AuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); + const string expectedXml = @" + + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + "; + XmlAssert.Equal(expectedXml, retVal.SerializedDescriptorElement); + } + + [Fact] + public void ExportToXml_ProducesCorrectPayload_Gcm() + { + // Arrange + var masterKey = "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret(); + var descriptor = CreateDescriptor(EncryptionAlgorithm.AES_192_GCM, ValidationAlgorithm.HMACSHA512, masterKey); + + // Act + var retVal = descriptor.ExportToXml(); + + // Assert + Assert.Equal(typeof(AuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); + const string expectedXml = @" + + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + "; + XmlAssert.Equal(expectedXml, retVal.SerializedDescriptorElement); + } + + private static AuthenticatedEncryptorDescriptor CreateDescriptor(EncryptionAlgorithm encryptionAlgorithm, ValidationAlgorithm validationAlgorithm, ISecret masterKey) + { + return new AuthenticatedEncryptorDescriptor(new AuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = encryptionAlgorithm, + ValidationAlgorithm = validationAlgorithm + }, masterKey); + } + + private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(AuthenticatedEncryptorDescriptor descriptor) + { + var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + + // Dummy key with the specified descriptor. + var key = new Key( + Guid.NewGuid(), + DateTimeOffset.Now, + DateTimeOffset.Now + TimeSpan.FromHours(1), + DateTimeOffset.Now + TimeSpan.FromDays(30), + descriptor, + new[] { encryptorFactory }); + + + return key.CreateEncryptor(); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfigurationTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfigurationTests.cs new file mode 100644 index 0000000000..9be301495e --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfigurationTests.cs @@ -0,0 +1,40 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class CngCbcAuthenticatedEncryptorConfigurationTests + { + [Fact] + public void CreateNewDescriptor_CreatesUniqueCorrectlySizedMasterKey() + { + // Arrange + var configuration = new CngCbcAuthenticatedEncryptorConfiguration(); + + // Act + var masterKey1 = ((CngCbcAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey; + var masterKey2 = ((CngCbcAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey; + + // Assert + SecretAssert.NotEqual(masterKey1, masterKey2); + SecretAssert.LengthIs(512 /* bits */, masterKey1); + SecretAssert.LengthIs(512 /* bits */, masterKey2); + } + + [Fact] + public void CreateNewDescriptor_PropagatesOptions() + { + // Arrange + var configuration = new CngCbcAuthenticatedEncryptorConfiguration(); + + // Act + var descriptor = (CngCbcAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor(); + + // Assert + Assert.Equal(configuration, descriptor.Configuration); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializerTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializerTests.cs new file mode 100644 index 0000000000..eb61aaa676 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializerTests.cs @@ -0,0 +1,66 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class CngCbcAuthenticatedEncryptorDescriptorDeserializerTests + { + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void ImportFromXml_CreatesAppropriateDescriptor() + { + // Arrange + var descriptor = new CngCbcAuthenticatedEncryptorDescriptor( + new CngCbcAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = Constants.BCRYPT_AES_ALGORITHM, + EncryptionAlgorithmKeySize = 192, + EncryptionAlgorithmProvider = null, + HashAlgorithm = Constants.BCRYPT_SHA512_ALGORITHM, + HashAlgorithmProvider = null + }, + "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret()); + var control = CreateEncryptorInstanceFromDescriptor(descriptor); + + const string xml = @" + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + "; + var deserializedDescriptor = new CngCbcAuthenticatedEncryptorDescriptorDeserializer().ImportFromXml(XElement.Parse(xml)); + var test = CreateEncryptorInstanceFromDescriptor(deserializedDescriptor as CngCbcAuthenticatedEncryptorDescriptor); + + // Act & assert + byte[] plaintext = new byte[] { 1, 2, 3, 4, 5 }; + byte[] aad = new byte[] { 2, 4, 6, 8, 0 }; + byte[] ciphertext = control.Encrypt(new ArraySegment(plaintext), new ArraySegment(aad)); + byte[] roundTripPlaintext = test.Decrypt(new ArraySegment(ciphertext), new ArraySegment(aad)); + Assert.Equal(plaintext, roundTripPlaintext); + } + + private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(CngCbcAuthenticatedEncryptorDescriptor descriptor) + { + var encryptorFactory = new CngCbcAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + var key = new Key( + Guid.NewGuid(), + DateTimeOffset.Now, + DateTimeOffset.Now + TimeSpan.FromHours(1), + DateTimeOffset.Now + TimeSpan.FromDays(30), + descriptor, + new[] { encryptorFactory }); + + + return key.CreateEncryptor(); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorTests.cs new file mode 100644 index 0000000000..090465fb13 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorTests.cs @@ -0,0 +1,69 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class CngCbcAuthenticatedEncryptorDescriptorTests + { + [Fact] + public void ExportToXml_WithProviders_ProducesCorrectPayload() + { + // Arrange + var masterKey = "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret(); + var descriptor = new CngCbcAuthenticatedEncryptorDescriptor(new CngCbcAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = "enc-alg", + EncryptionAlgorithmKeySize = 2048, + EncryptionAlgorithmProvider = "enc-alg-prov", + HashAlgorithm = "hash-alg", + HashAlgorithmProvider = "hash-alg-prov" + }, masterKey); + + // Act + var retVal = descriptor.ExportToXml(); + + // Assert + Assert.Equal(typeof(CngCbcAuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); + const string expectedXml = @" + + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + "; + XmlAssert.Equal(expectedXml, retVal.SerializedDescriptorElement); + } + + [Fact] + public void ExportToXml_WithoutProviders_ProducesCorrectPayload() + { + // Arrange + var masterKey = "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret(); + var descriptor = new CngCbcAuthenticatedEncryptorDescriptor(new CngCbcAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = "enc-alg", + EncryptionAlgorithmKeySize = 2048, + HashAlgorithm = "hash-alg" + }, masterKey); + + // Act + var retVal = descriptor.ExportToXml(); + + // Assert + Assert.Equal(typeof(CngCbcAuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); + const string expectedXml = @" + + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + "; + XmlAssert.Equal(expectedXml, retVal.SerializedDescriptorElement); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfigurationTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfigurationTests.cs new file mode 100644 index 0000000000..e70460cf40 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfigurationTests.cs @@ -0,0 +1,40 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class CngGcmAuthenticatedEncryptorConfigurationTests + { + [Fact] + public void CreateNewDescriptor_CreatesUniqueCorrectlySizedMasterKey() + { + // Arrange + var configuration = new CngGcmAuthenticatedEncryptorConfiguration(); + + // Act + var masterKey1 = ((CngGcmAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey; + var masterKey2 = ((CngGcmAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey; + + // Assert + SecretAssert.NotEqual(masterKey1, masterKey2); + SecretAssert.LengthIs(512 /* bits */, masterKey1); + SecretAssert.LengthIs(512 /* bits */, masterKey2); + } + + [Fact] + public void CreateNewDescriptor_PropagatesOptions() + { + // Arrange + var configuration = new CngGcmAuthenticatedEncryptorConfiguration(); + + // Act + var descriptor = (CngGcmAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor(); + + // Assert + Assert.Equal(configuration, descriptor.Configuration); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializerTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializerTests.cs new file mode 100644 index 0000000000..05845dfde0 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializerTests.cs @@ -0,0 +1,63 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.Cryptography; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class CngGcmAuthenticatedEncryptorDescriptorDeserializerTests + { + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void ImportFromXml_CreatesAppropriateDescriptor() + { + // Arrange + var descriptor = new CngGcmAuthenticatedEncryptorDescriptor( + new CngGcmAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = Constants.BCRYPT_AES_ALGORITHM, + EncryptionAlgorithmKeySize = 192, + EncryptionAlgorithmProvider = null + }, + "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret()); + var control = CreateEncryptorInstanceFromDescriptor(descriptor); + + const string xml = @" + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + "; + var deserializedDescriptor = new CngGcmAuthenticatedEncryptorDescriptorDeserializer().ImportFromXml(XElement.Parse(xml)); + var test = CreateEncryptorInstanceFromDescriptor(deserializedDescriptor as CngGcmAuthenticatedEncryptorDescriptor); + + // Act & assert + byte[] plaintext = new byte[] { 1, 2, 3, 4, 5 }; + byte[] aad = new byte[] { 2, 4, 6, 8, 0 }; + byte[] ciphertext = control.Encrypt(new ArraySegment(plaintext), new ArraySegment(aad)); + byte[] roundTripPlaintext = test.Decrypt(new ArraySegment(ciphertext), new ArraySegment(aad)); + Assert.Equal(plaintext, roundTripPlaintext); + } + + private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(CngGcmAuthenticatedEncryptorDescriptor descriptor) + { + var encryptorFactory = new CngGcmAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + var key = new Key( + keyId: Guid.NewGuid(), + creationDate: DateTimeOffset.Now, + activationDate: DateTimeOffset.Now + TimeSpan.FromHours(1), + expirationDate: DateTimeOffset.Now + TimeSpan.FromDays(30), + descriptor: descriptor, + encryptorFactories: new[] { encryptorFactory }); + + + return key.CreateEncryptor(); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorTests.cs new file mode 100644 index 0000000000..933f7e7d85 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorTests.cs @@ -0,0 +1,64 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class CngGcmAuthenticatedEncryptorDescriptorTests + { + [Fact] + public void ExportToXml_WithProviders_ProducesCorrectPayload() + { + // Arrange + var masterKey = "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret(); + var descriptor = new CngGcmAuthenticatedEncryptorDescriptor(new CngGcmAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = "enc-alg", + EncryptionAlgorithmKeySize = 2048, + EncryptionAlgorithmProvider = "enc-alg-prov" + }, masterKey); + + // Act + var retVal = descriptor.ExportToXml(); + + // Assert + Assert.Equal(typeof(CngGcmAuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); + const string expectedXml = @" + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + "; + XmlAssert.Equal(expectedXml, retVal.SerializedDescriptorElement); + } + + [Fact] + public void ExportToXml_WithoutProviders_ProducesCorrectPayload() + { + // Arrange + var masterKey = "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret(); + var descriptor = new CngGcmAuthenticatedEncryptorDescriptor(new CngGcmAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = "enc-alg", + EncryptionAlgorithmKeySize = 2048 + }, masterKey); + + // Act + var retVal = descriptor.ExportToXml(); + + // Assert + Assert.Equal(typeof(CngGcmAuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); + const string expectedXml = @" + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + "; + XmlAssert.Equal(expectedXml, retVal.SerializedDescriptorElement); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfigurationTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfigurationTests.cs new file mode 100644 index 0000000000..6dbc4b7fea --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfigurationTests.cs @@ -0,0 +1,40 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class ManagedAuthenticatedEncryptorConfigurationTests + { + [Fact] + public void CreateNewDescriptor_CreatesUniqueCorrectlySizedMasterKey() + { + // Arrange + var configuration = new ManagedAuthenticatedEncryptorConfiguration(); + + // Act + var masterKey1 = ((ManagedAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey; + var masterKey2 = ((ManagedAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey; + + // Assert + SecretAssert.NotEqual(masterKey1, masterKey2); + SecretAssert.LengthIs(512 /* bits */, masterKey1); + SecretAssert.LengthIs(512 /* bits */, masterKey2); + } + + [Fact] + public void CreateNewDescriptor_PropagatesOptions() + { + // Arrange + var configuration = new ManagedAuthenticatedEncryptorConfiguration(); + + // Act + var descriptor = (ManagedAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor(); + + // Assert + Assert.Equal(configuration, descriptor.Configuration); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs new file mode 100644 index 0000000000..69cc556e6b --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs @@ -0,0 +1,101 @@ +// 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.Security.Cryptography; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class ManagedAuthenticatedEncryptorDescriptorDeserializerTests + { + [Theory] + [InlineData(typeof(Aes), typeof(HMACSHA1))] + [InlineData(typeof(Aes), typeof(HMACSHA256))] + [InlineData(typeof(Aes), typeof(HMACSHA384))] + [InlineData(typeof(Aes), typeof(HMACSHA512))] + public void ImportFromXml_BuiltInTypes_CreatesAppropriateDescriptor(Type encryptionAlgorithmType, Type validationAlgorithmType) + { + // Arrange + var descriptor = new ManagedAuthenticatedEncryptorDescriptor( + new ManagedAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithmType = encryptionAlgorithmType, + EncryptionAlgorithmKeySize = 192, + ValidationAlgorithmType = validationAlgorithmType + }, + "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret()); + var control = CreateEncryptorInstanceFromDescriptor(descriptor); + + string xml = string.Format(@" + + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + ", + encryptionAlgorithmType.Name, validationAlgorithmType.Name); + var deserializedDescriptor = new ManagedAuthenticatedEncryptorDescriptorDeserializer().ImportFromXml(XElement.Parse(xml)); + var test = CreateEncryptorInstanceFromDescriptor(deserializedDescriptor as ManagedAuthenticatedEncryptorDescriptor); + + // Act & assert + byte[] plaintext = new byte[] { 1, 2, 3, 4, 5 }; + byte[] aad = new byte[] { 2, 4, 6, 8, 0 }; + byte[] ciphertext = control.Encrypt(new ArraySegment(plaintext), new ArraySegment(aad)); + byte[] roundTripPlaintext = test.Decrypt(new ArraySegment(ciphertext), new ArraySegment(aad)); + Assert.Equal(plaintext, roundTripPlaintext); + } + + [Fact] + public void ImportFromXml_CustomType_CreatesAppropriateDescriptor() + { + // Arrange + var descriptor = new ManagedAuthenticatedEncryptorDescriptor( + new ManagedAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithmType = typeof(Aes), + EncryptionAlgorithmKeySize = 192, + ValidationAlgorithmType = typeof(HMACSHA384) + }, + "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret()); + var control = CreateEncryptorInstanceFromDescriptor(descriptor); + + string xml = string.Format(@" + + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + ", + typeof(Aes).AssemblyQualifiedName, typeof(HMACSHA384).AssemblyQualifiedName); + var deserializedDescriptor = new ManagedAuthenticatedEncryptorDescriptorDeserializer().ImportFromXml(XElement.Parse(xml)); + var test = CreateEncryptorInstanceFromDescriptor(deserializedDescriptor as ManagedAuthenticatedEncryptorDescriptor); + + // Act & assert + byte[] plaintext = new byte[] { 1, 2, 3, 4, 5 }; + byte[] aad = new byte[] { 2, 4, 6, 8, 0 }; + byte[] ciphertext = control.Encrypt(new ArraySegment(plaintext), new ArraySegment(aad)); + byte[] roundTripPlaintext = test.Decrypt(new ArraySegment(ciphertext), new ArraySegment(aad)); + Assert.Equal(plaintext, roundTripPlaintext); + } + + private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(ManagedAuthenticatedEncryptorDescriptor descriptor) + { + var encryptorFactory = new ManagedAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + var key = new Key( + Guid.NewGuid(), + DateTimeOffset.Now, + DateTimeOffset.Now + TimeSpan.FromHours(1), + DateTimeOffset.Now + TimeSpan.FromDays(30), + descriptor, + new[] { encryptorFactory }); + + return key.CreateEncryptor(); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorTests.cs new file mode 100644 index 0000000000..4e4f453448 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorTests.cs @@ -0,0 +1,115 @@ +// 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.Security.Cryptography; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + public class ManagedAuthenticatedEncryptorDescriptorTests + { + [Fact] + public void ExportToXml_CustomTypes_ProducesCorrectPayload() + { + // Arrange + var masterKey = "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret(); + var descriptor = new ManagedAuthenticatedEncryptorDescriptor(new ManagedAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithmType = typeof(MySymmetricAlgorithm), + EncryptionAlgorithmKeySize = 2048, + ValidationAlgorithmType = typeof(MyKeyedHashAlgorithm) + }, masterKey); + + // Act + var retVal = descriptor.ExportToXml(); + + // Assert + Assert.Equal(typeof(ManagedAuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); + string expectedXml = string.Format(@" + + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + ", + typeof(MySymmetricAlgorithm).AssemblyQualifiedName, typeof(MyKeyedHashAlgorithm).AssemblyQualifiedName); + XmlAssert.Equal(expectedXml, retVal.SerializedDescriptorElement); + } + + [Theory] + [InlineData(typeof(Aes), typeof(HMACSHA1))] + [InlineData(typeof(Aes), typeof(HMACSHA256))] + [InlineData(typeof(Aes), typeof(HMACSHA384))] + [InlineData(typeof(Aes), typeof(HMACSHA512))] + public void ExportToXml_BuiltInTypes_ProducesCorrectPayload(Type encryptionAlgorithmType, Type validationAlgorithmType) + { + // Arrange + var masterKey = "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret(); + var descriptor = new ManagedAuthenticatedEncryptorDescriptor(new ManagedAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithmType = encryptionAlgorithmType, + EncryptionAlgorithmKeySize = 2048, + ValidationAlgorithmType = validationAlgorithmType + }, masterKey); + + // Act + var retVal = descriptor.ExportToXml(); + + // Assert + Assert.Equal(typeof(ManagedAuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); + string expectedXml = string.Format(@" + + + + + k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA== + + ", + encryptionAlgorithmType.Name, validationAlgorithmType.Name); + XmlAssert.Equal(expectedXml, retVal.SerializedDescriptorElement); + } + + private sealed class MySymmetricAlgorithm : SymmetricAlgorithm + { + public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV) + { + throw new NotImplementedException(); + } + + public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV) + { + throw new NotImplementedException(); + } + + public override void GenerateIV() + { + throw new NotImplementedException(); + } + + public override void GenerateKey() + { + throw new NotImplementedException(); + } + } + + private sealed class MyKeyedHashAlgorithm : KeyedHashAlgorithm + { + public override void Initialize() + { + throw new NotImplementedException(); + } + + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + throw new NotImplementedException(); + } + + protected override byte[] HashFinal() + { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ManagedAuthenticatedEncryptorFactoryTest.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ManagedAuthenticatedEncryptorFactoryTest.cs new file mode 100644 index 0000000000..ef5eae5d19 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ManagedAuthenticatedEncryptorFactoryTest.cs @@ -0,0 +1,50 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Managed; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption +{ + public class ManagedAuthenticatedEncryptorFactoryTest + { + [Fact] + public void CreateEncrptorInstance_UnknownDescriptorType_ReturnsNull() + { + // Arrange + var key = new Mock(); + key.Setup(k => k.Descriptor).Returns(new Mock().Object); + + var factory = new ManagedAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + + // Act + var encryptor = factory.CreateEncryptorInstance(key.Object); + + // Assert + Assert.Null(encryptor); + } + + [Fact] + public void CreateEncrptorInstance_ExpectedDescriptorType_ReturnsEncryptor() + { + // Arrange + var descriptor = new ManagedAuthenticatedEncryptorConfiguration().CreateNewDescriptor(); + var key = new Mock(); + key.Setup(k => k.Descriptor).Returns(descriptor); + + var factory = new ManagedAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + + // Act + var encryptor = factory.CreateEncryptorInstance(key.Object); + + // Assert + Assert.NotNull(encryptor); + Assert.IsType(encryptor); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs new file mode 100644 index 0000000000..97e7d7a96d --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs @@ -0,0 +1,120 @@ +// 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 System.Security.Cryptography; +using System.Text; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Cng +{ + public class CbcAuthenticatedEncryptorTests + { + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void Encrypt_Decrypt_RoundTrips() + { + // Arrange + Secret kdk = new Secret(new byte[512 / 8]); + CbcAuthenticatedEncryptor encryptor = new CbcAuthenticatedEncryptor(kdk, + symmetricAlgorithmHandle: CachedAlgorithmHandles.AES_CBC, + symmetricAlgorithmKeySizeInBytes: 256 / 8, + hmacAlgorithmHandle: CachedAlgorithmHandles.HMAC_SHA256); + ArraySegment plaintext = new ArraySegment(Encoding.UTF8.GetBytes("plaintext")); + ArraySegment aad = new ArraySegment(Encoding.UTF8.GetBytes("aad")); + + // Act + byte[] ciphertext = encryptor.Encrypt(plaintext, aad); + byte[] decipheredtext = encryptor.Decrypt(new ArraySegment(ciphertext), aad); + + // Assert + Assert.Equal(plaintext, decipheredtext); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void Encrypt_Decrypt_Tampering_Fails() + { + // Arrange + Secret kdk = new Secret(new byte[512 / 8]); + CbcAuthenticatedEncryptor encryptor = new CbcAuthenticatedEncryptor(kdk, + symmetricAlgorithmHandle: CachedAlgorithmHandles.AES_CBC, + symmetricAlgorithmKeySizeInBytes: 256 / 8, + hmacAlgorithmHandle: CachedAlgorithmHandles.HMAC_SHA256); + ArraySegment plaintext = new ArraySegment(Encoding.UTF8.GetBytes("plaintext")); + ArraySegment aad = new ArraySegment(Encoding.UTF8.GetBytes("aad")); + byte[] validCiphertext = encryptor.Encrypt(plaintext, aad); + + // Act & assert - 1 + // Ciphertext is too short to be a valid payload + byte[] invalidCiphertext_tooShort = new byte[10]; + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(invalidCiphertext_tooShort), aad); + }); + + // Act & assert - 2 + // Ciphertext has been manipulated + byte[] invalidCiphertext_manipulated = (byte[])validCiphertext.Clone(); + invalidCiphertext_manipulated[0] ^= 0x01; + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(invalidCiphertext_manipulated), aad); + }); + + // Act & assert - 3 + // Ciphertext is too long + byte[] invalidCiphertext_tooLong = validCiphertext.Concat(new byte[] { 0 }).ToArray(); + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(invalidCiphertext_tooLong), aad); + }); + + // Act & assert - 4 + // AAD is incorrect + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(validCiphertext), new ArraySegment(Encoding.UTF8.GetBytes("different aad"))); + }); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void Encrypt_KnownKey() + { + // Arrange + Secret kdk = new Secret(Encoding.UTF8.GetBytes("master key")); + CbcAuthenticatedEncryptor encryptor = new CbcAuthenticatedEncryptor(kdk, + symmetricAlgorithmHandle: CachedAlgorithmHandles.AES_CBC, + symmetricAlgorithmKeySizeInBytes: 256 / 8, + hmacAlgorithmHandle: CachedAlgorithmHandles.HMAC_SHA256, + genRandom: new SequentialGenRandom()); + ArraySegment plaintext = new ArraySegment(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }, 2, 3); + ArraySegment aad = new ArraySegment(new byte[] { 7, 6, 5, 4, 3, 2, 1, 0 }, 1, 4); + + // Act + byte[] retVal = encryptor.Encrypt( + plaintext: plaintext, + additionalAuthenticatedData: aad, + preBufferSize: 3, + postBufferSize: 4); + + // Assert + + // retVal := 00 00 00 (preBuffer) + // | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F (keyModifier) + // | 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F (IV) + // | B7 EA 3E 32 58 93 A3 06 03 89 C6 66 03 63 08 4B (encryptedData) + // | 9D 8A 85 C7 0F BD 98 D8 7F 72 E7 72 3E B5 A6 26 (HMAC) + // | 6C 38 77 F7 66 19 A2 C9 2C BB AD DA E7 62 00 00 + // | 00 00 00 00 (postBuffer) + + string retValAsString = Convert.ToBase64String(retVal); + Assert.Equal("AAAAAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh+36j4yWJOjBgOJxmYDYwhLnYqFxw+9mNh/cudyPrWmJmw4d/dmGaLJLLut2udiAAAAAAAA", retValAsString); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Cng/CngAuthenticatedEncryptorBaseTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Cng/CngAuthenticatedEncryptorBaseTests.cs new file mode 100644 index 0000000000..faedbf44e9 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Cng/CngAuthenticatedEncryptorBaseTests.cs @@ -0,0 +1,110 @@ +// 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 Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Cng.Internal +{ + public unsafe class CngAuthenticatedEncryptorBaseTests + { + [Fact] + public void Decrypt_ForwardsArraySegment() + { + // Arrange + var ciphertext = new ArraySegment(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 }, 3, 2); + var aad = new ArraySegment(new byte[] { 0x10, 0x11, 0x12, 0x13, 0x14 }, 1, 4); + + var encryptorMock = new Mock(); + encryptorMock + .Setup(o => o.DecryptHook(It.IsAny(), 2, It.IsAny(), 4)) + .Returns((IntPtr pbCiphertext, uint cbCiphertext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData) => + { + // ensure that pointers started at the right place + Assert.Equal((byte)0x03, *(byte*)pbCiphertext); + Assert.Equal((byte)0x11, *(byte*)pbAdditionalAuthenticatedData); + return new byte[] { 0x20, 0x21, 0x22 }; + }); + + // Act + var retVal = encryptorMock.Object.Decrypt(ciphertext, aad); + + // Assert + Assert.Equal(new byte[] { 0x20, 0x21, 0x22 }, retVal); + } + + [Fact] + public void Decrypt_HandlesEmptyAADPointerFixup() + { + // Arrange + var ciphertext = new ArraySegment(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 }, 3, 2); + var aad = new ArraySegment(new byte[0]); + + var encryptorMock = new Mock(); + encryptorMock + .Setup(o => o.DecryptHook(It.IsAny(), 2, It.IsAny(), 0)) + .Returns((IntPtr pbCiphertext, uint cbCiphertext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData) => + { + // ensure that pointers started at the right place + Assert.Equal((byte)0x03, *(byte*)pbCiphertext); + Assert.NotEqual(IntPtr.Zero, pbAdditionalAuthenticatedData); // CNG will complain if this pointer is zero + return new byte[] { 0x20, 0x21, 0x22 }; + }); + + // Act + var retVal = encryptorMock.Object.Decrypt(ciphertext, aad); + + // Assert + Assert.Equal(new byte[] { 0x20, 0x21, 0x22 }, retVal); + } + + [Fact] + public void Decrypt_HandlesEmptyCiphertextPointerFixup() + { + // Arrange + var ciphertext = new ArraySegment(new byte[0]); + var aad = new ArraySegment(new byte[] { 0x10, 0x11, 0x12, 0x13, 0x14 }, 1, 4); + + var encryptorMock = new Mock(); + encryptorMock + .Setup(o => o.DecryptHook(It.IsAny(), 0, It.IsAny(), 4)) + .Returns((IntPtr pbCiphertext, uint cbCiphertext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData) => + { + // ensure that pointers started at the right place + Assert.NotEqual(IntPtr.Zero, pbCiphertext); // CNG will complain if this pointer is zero + Assert.Equal((byte)0x11, *(byte*)pbAdditionalAuthenticatedData); + return new byte[] { 0x20, 0x21, 0x22 }; + }); + + // Act + var retVal = encryptorMock.Object.Decrypt(ciphertext, aad); + + // Assert + Assert.Equal(new byte[] { 0x20, 0x21, 0x22 }, retVal); + } + + public abstract class MockableEncryptor : CngAuthenticatedEncryptorBase + { + public override void Dispose() + { + } + + public abstract byte[] DecryptHook(IntPtr pbCiphertext, uint cbCiphertext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData); + + protected override sealed unsafe byte[] DecryptImpl(byte* pbCiphertext, uint cbCiphertext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData) + { + return DecryptHook((IntPtr)pbCiphertext, cbCiphertext, (IntPtr)pbAdditionalAuthenticatedData, cbAdditionalAuthenticatedData); + } + + public abstract byte[] EncryptHook(IntPtr pbPlaintext, uint cbPlaintext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer); + + protected override sealed unsafe byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer) + { + return EncryptHook((IntPtr)pbPlaintext, cbPlaintext, (IntPtr)pbAdditionalAuthenticatedData, cbAdditionalAuthenticatedData, cbPreBuffer, cbPostBuffer); + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs new file mode 100644 index 0000000000..b01058e5b4 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs @@ -0,0 +1,109 @@ +// 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 System.Security.Cryptography; +using System.Text; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Cng +{ + public class GcmAuthenticatedEncryptorTests + { + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void Encrypt_Decrypt_RoundTrips() + { + // Arrange + Secret kdk = new Secret(new byte[512 / 8]); + GcmAuthenticatedEncryptor encryptor = new GcmAuthenticatedEncryptor(kdk, CachedAlgorithmHandles.AES_GCM, symmetricAlgorithmKeySizeInBytes: 256 / 8); + ArraySegment plaintext = new ArraySegment(Encoding.UTF8.GetBytes("plaintext")); + ArraySegment aad = new ArraySegment(Encoding.UTF8.GetBytes("aad")); + + // Act + byte[] ciphertext = encryptor.Encrypt(plaintext, aad); + byte[] decipheredtext = encryptor.Decrypt(new ArraySegment(ciphertext), aad); + + // Assert + Assert.Equal(plaintext, decipheredtext); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void Encrypt_Decrypt_Tampering_Fails() + { + // Arrange + Secret kdk = new Secret(new byte[512 / 8]); + GcmAuthenticatedEncryptor encryptor = new GcmAuthenticatedEncryptor(kdk, CachedAlgorithmHandles.AES_GCM, symmetricAlgorithmKeySizeInBytes: 256 / 8); + ArraySegment plaintext = new ArraySegment(Encoding.UTF8.GetBytes("plaintext")); + ArraySegment aad = new ArraySegment(Encoding.UTF8.GetBytes("aad")); + byte[] validCiphertext = encryptor.Encrypt(plaintext, aad); + + // Act & assert - 1 + // Ciphertext is too short to be a valid payload + byte[] invalidCiphertext_tooShort = new byte[10]; + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(invalidCiphertext_tooShort), aad); + }); + + // Act & assert - 2 + // Ciphertext has been manipulated + byte[] invalidCiphertext_manipulated = (byte[])validCiphertext.Clone(); + invalidCiphertext_manipulated[0] ^= 0x01; + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(invalidCiphertext_manipulated), aad); + }); + + // Act & assert - 3 + // Ciphertext is too long + byte[] invalidCiphertext_tooLong = validCiphertext.Concat(new byte[] { 0 }).ToArray(); + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(invalidCiphertext_tooLong), aad); + }); + + // Act & assert - 4 + // AAD is incorrect + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(validCiphertext), new ArraySegment(Encoding.UTF8.GetBytes("different aad"))); + }); + } + + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void Encrypt_KnownKey() + { + // Arrange + Secret kdk = new Secret(Encoding.UTF8.GetBytes("master key")); + GcmAuthenticatedEncryptor encryptor = new GcmAuthenticatedEncryptor(kdk, CachedAlgorithmHandles.AES_GCM, symmetricAlgorithmKeySizeInBytes: 128 / 8, genRandom: new SequentialGenRandom()); + ArraySegment plaintext = new ArraySegment(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }, 2, 3); + ArraySegment aad = new ArraySegment(new byte[] { 7, 6, 5, 4, 3, 2, 1, 0 }, 1, 4); + + // Act + byte[] retVal = encryptor.Encrypt( + plaintext: plaintext, + additionalAuthenticatedData: aad, + preBufferSize: 3, + postBufferSize: 4); + + // Assert + + // retVal := 00 00 00 (preBuffer) + // | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F (keyModifier) + // | 10 11 12 13 14 15 16 17 18 19 1A 1B (nonce) + // | 43 B6 91 (encryptedData) + // | 8D 0D 66 D9 A1 D9 44 2D 5D 8E 41 DA 39 60 9C E8 (authTag) + // | 00 00 00 00 (postBuffer) + + string retValAsString = Convert.ToBase64String(retVal); + Assert.Equal("AAAAAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaG0O2kY0NZtmh2UQtXY5B2jlgnOgAAAAA", retValAsString); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/DataProtectionUtilityExtensionsTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/DataProtectionUtilityExtensionsTests.cs new file mode 100644 index 0000000000..5af33b1b25 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/DataProtectionUtilityExtensionsTests.cs @@ -0,0 +1,87 @@ +// 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 Microsoft.AspNetCore.DataProtection.Infrastructure; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class DataProtectionUtilityExtensionsTests + { + [Theory] + [InlineData("app-path", "app-path")] + [InlineData("app-path ", "app-path")] // normalized trim + [InlineData(" ", null)] // normalized whitespace -> null + [InlineData(null, null)] // nothing provided at all + public void GetApplicationUniqueIdentifierFromHosting(string contentRootPath, string expected) + { + // Arrange + var mockEnvironment = new Mock(); + mockEnvironment.Setup(o => o.ContentRootPath).Returns(contentRootPath); + + var services = new ServiceCollection() + .AddSingleton(mockEnvironment.Object) + .AddDataProtection() + .Services + .BuildServiceProvider(); + + // Act + var actual = services.GetApplicationUniqueIdentifier(); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData(" discriminator ", "discriminator")] + [InlineData(" discriminator", "discriminator")] // normalized trim + [InlineData(" ", null)] // normalized whitespace -> null + [InlineData(null, null)] // nothing provided at all + public void GetApplicationIdentifierFromApplicationDiscriminator(string discriminator, string expected) + { + // Arrange + var mockAppDiscriminator = new Mock(); + mockAppDiscriminator.Setup(o => o.Discriminator).Returns(discriminator); + + var mockEnvironment = new Mock(); + mockEnvironment.SetupGet(o => o.ContentRootPath).Throws(new InvalidOperationException("Hosting environment should not be checked")); + + var services = new ServiceCollection() + .AddSingleton(mockEnvironment.Object) + .AddSingleton(mockAppDiscriminator.Object) + .AddDataProtection() + .Services + .BuildServiceProvider(); + + // Act + var actual = services.GetApplicationUniqueIdentifier(); + + // Assert + Assert.Equal(expected, actual); + mockAppDiscriminator.VerifyAll(); + } + + [Fact] + public void GetApplicationUniqueIdentifier_NoServiceProvider_ReturnsNull() + { + Assert.Null(((IServiceProvider)null).GetApplicationUniqueIdentifier()); + } + + [Fact] + public void GetApplicationUniqueIdentifier_NoHostingEnvironment_ReturnsNull() + { + // arrange + var services = new ServiceCollection() + .AddDataProtection() + .Services + .BuildServiceProvider(); + + // act & assert + Assert.Null(services.GetApplicationUniqueIdentifier()); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/DockerUtilsTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/DockerUtilsTests.cs new file mode 100644 index 0000000000..9ede10426b --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/DockerUtilsTests.cs @@ -0,0 +1,56 @@ +// 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.IO; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Test +{ + public class DockerUtilsTests + { + // example of content from /proc/self/mounts + private static readonly string[] fstab = new [] + { + "none / aufs rw,relatime,si=f9bfcf896de3f6c2,dio,dirperm1 0 0", + "# comments", + "", + "proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0", + "tmpfs /dev tmpfs rw,nosuid,mode=755 0 0", + "devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666 0 0", + "/dev/vda2 /etc/resolv.conf ext4 rw,relatime,data=ordered 0 0", + "/dev/vda2 /etc/hostname ext4 rw,relatime,data=ordered 0 0", + "/dev/vda2 /etc/hosts ext4 rw,relatime,data=ordered 0 0", + "shm /dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,size=65536k 0 0", + // the mounted directory + "osxfs /app fuse.osxfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other,max_read=1048576 0 0", + }; + + [ConditionalTheory] + [OSSkipCondition(OperatingSystems.Windows)] + [InlineData("/")] + [InlineData("/home")] + [InlineData("/home/")] + [InlineData("/home/root")] + [InlineData("./dir")] + [InlineData("../dir")] + public void DeterminesFolderIsNotMounted(string directory) + { + Assert.False(DockerUtils.IsDirectoryMounted(new DirectoryInfo(directory), fstab)); + } + + [ConditionalTheory] + [OSSkipCondition(OperatingSystems.Windows)] + [InlineData("/app")] + [InlineData("/app/")] + [InlineData("/app/subdir")] + [InlineData("/app/subdir/")] + [InlineData("/app/subdir/two")] + [InlineData("/app/subdir/two/")] + public void DeterminesFolderIsMounted(string directory) + { + Assert.True(DockerUtils.IsDirectoryMounted(new DirectoryInfo(directory), fstab)); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/EphemeralDataProtectionProviderTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/EphemeralDataProtectionProviderTests.cs new file mode 100644 index 0000000000..d42fe2113c --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/EphemeralDataProtectionProviderTests.cs @@ -0,0 +1,65 @@ +// 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.Security.Cryptography; +using System.Text; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class EphemeralDataProtectionProviderTests + { + [Fact] + public void DifferentProvider_SamePurpose_DoesNotRoundTripData() + { + // Arrange + var dataProtector1 = new EphemeralDataProtectionProvider().CreateProtector("purpose"); + var dataProtector2 = new EphemeralDataProtectionProvider(NullLoggerFactory.Instance).CreateProtector("purpose"); + byte[] bytes = Encoding.UTF8.GetBytes("Hello there!"); + + // Act & assert + // Each instance of the EphemeralDataProtectionProvider has its own unique KDK, so payloads can't be shared. + byte[] protectedBytes = dataProtector1.Protect(bytes); + Assert.ThrowsAny(() => + { + byte[] unprotectedBytes = dataProtector2.Unprotect(protectedBytes); + }); + } + + [Fact] + public void SingleProvider_DifferentPurpose_DoesNotRoundTripData() + { + // Arrange + var dataProtectionProvider = new EphemeralDataProtectionProvider(NullLoggerFactory.Instance); + var dataProtector1 = dataProtectionProvider.CreateProtector("purpose"); + var dataProtector2 = dataProtectionProvider.CreateProtector("different purpose"); + byte[] bytes = Encoding.UTF8.GetBytes("Hello there!"); + + // Act & assert + byte[] protectedBytes = dataProtector1.Protect(bytes); + Assert.ThrowsAny(() => + { + byte[] unprotectedBytes = dataProtector2.Unprotect(protectedBytes); + }); + } + + [Fact] + public void SingleProvider_SamePurpose_RoundTripsData() + { + // Arrange + var dataProtectionProvider = new EphemeralDataProtectionProvider(NullLoggerFactory.Instance); + var dataProtector1 = dataProtectionProvider.CreateProtector("purpose"); + var dataProtector2 = dataProtectionProvider.CreateProtector("purpose"); // should be equivalent to the previous instance + byte[] bytes = Encoding.UTF8.GetBytes("Hello there!"); + + // Act + byte[] protectedBytes = dataProtector1.Protect(bytes); + byte[] unprotectedBytes = dataProtector2.Unprotect(protectedBytes); + + // Assert + Assert.Equal(bytes, unprotectedBytes); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/HostingTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/HostingTests.cs new file mode 100644 index 0000000000..cd43effe37 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/HostingTests.cs @@ -0,0 +1,104 @@ +// 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.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Test +{ + public class HostingTests + { + [Fact] + public async Task LoadsKeyRingBeforeServerStarts() + { + var tcs = new TaskCompletionSource(); + var mockKeyRing = new Mock(); + mockKeyRing.Setup(m => m.GetCurrentKeyRing()) + .Returns(Mock.Of()) + .Callback(() => tcs.TrySetResult(null)); + + var builder = new WebHostBuilder() + .UseStartup() + .ConfigureServices(s => + s.AddDataProtection() + .Services + .Replace(ServiceDescriptor.Singleton(mockKeyRing.Object)) + .AddSingleton( + new FakeServer(onStart: () => tcs.TrySetException(new InvalidOperationException("Server was started before key ring was initialized"))))); + + using (var host = builder.Build()) + { + await host.StartAsync(); + } + + await tcs.Task.TimeoutAfter(TimeSpan.FromSeconds(10)); + mockKeyRing.VerifyAll(); + } + + [Fact] + public async Task StartupContinuesOnFailureToLoadKey() + { + var mockKeyRing = new Mock(); + mockKeyRing.Setup(m => m.GetCurrentKeyRing()) + .Throws(new NotSupportedException("This mock doesn't actually work, but shouldn't kill the server")) + .Verifiable(); + + var builder = new WebHostBuilder() + .UseStartup() + .ConfigureServices(s => + s.AddDataProtection() + .Services + .Replace(ServiceDescriptor.Singleton(mockKeyRing.Object)) + .AddSingleton(Mock.Of())); + + using (var host = builder.Build()) + { + await host.StartAsync(); + } + + mockKeyRing.VerifyAll(); + } + + private class TestStartup + { + public void Configure(IApplicationBuilder app) + { + } + } + + public class FakeServer : IServer + { + private readonly Action _onStart; + + public FakeServer(Action onStart) + { + _onStart = onStart; + } + + public IFeatureCollection Features => new FeatureCollection(); + + public Task StartAsync(IHttpApplication application, CancellationToken cancellationToken) + { + _onStart(); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + + public void Dispose() + { + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Internal/KeyManagementOptionsSetupTest.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Internal/KeyManagementOptionsSetupTest.cs new file mode 100644 index 0000000000..ae49c7edab --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Internal/KeyManagementOptionsSetupTest.cs @@ -0,0 +1,154 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Win32; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Internal +{ + public class KeyManagementOptionsSetupTest + { + [Fact] + public void Configure_SetsExpectedValues() + { + // Arrange + var setup = new KeyManagementOptionsSetup(NullLoggerFactory.Instance); + var options = new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = null + }; + + // Act + setup.Configure(options); + + // Assert + Assert.Empty(options.KeyEscrowSinks); + Assert.NotNull(options.AuthenticatedEncryptorConfiguration); + Assert.IsType(options.AuthenticatedEncryptorConfiguration); + Assert.Collection( + options.AuthenticatedEncryptorFactories, + f => Assert.IsType(f), + f => Assert.IsType(f), + f => Assert.IsType(f), + f => Assert.IsType(f)); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void Configure_WithRegistryPolicyResolver_SetsValuesFromResolver() + { + // Arrange + var registryEntries = new Dictionary() + { + ["KeyEscrowSinks"] = String.Join(" ;; ; ", new Type[] { typeof(MyKeyEscrowSink1), typeof(MyKeyEscrowSink2) }.Select(t => t.AssemblyQualifiedName)), + ["EncryptionType"] = "managed", + ["DefaultKeyLifetime"] = 1024 // days + }; + var options = new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = null + }; + + // Act + RunTest(registryEntries, options); + + // Assert + Assert.Collection( + options.KeyEscrowSinks, + k => Assert.IsType(k), + k => Assert.IsType(k)); + Assert.Equal(TimeSpan.FromDays(1024), options.NewKeyLifetime); + Assert.NotNull(options.AuthenticatedEncryptorConfiguration); + Assert.IsType(options.AuthenticatedEncryptorConfiguration); + Assert.Collection( + options.AuthenticatedEncryptorFactories, + f => Assert.IsType(f), + f => Assert.IsType(f), + f => Assert.IsType(f), + f => Assert.IsType(f)); + } + + private static void RunTest(Dictionary regValues, KeyManagementOptions options) + { + WithUniqueTempRegKey(registryKey => + { + foreach (var entry in regValues) + { + registryKey.SetValue(entry.Key, entry.Value); + } + + var policyResolver = new RegistryPolicyResolver( + registryKey, + activator: SimpleActivator.DefaultWithoutServices); + + var setup = new KeyManagementOptionsSetup(NullLoggerFactory.Instance, policyResolver); + + setup.Configure(options); + }); + } + + /// + /// Runs a test and cleans up the registry key afterward. + /// + private static void WithUniqueTempRegKey(Action testCode) + { + string uniqueName = Guid.NewGuid().ToString(); + var uniqueSubkey = LazyHkcuTempKey.Value.CreateSubKey(uniqueName); + try + { + testCode(uniqueSubkey); + } + finally + { + // clean up when test is done + LazyHkcuTempKey.Value.DeleteSubKeyTree(uniqueName, throwOnMissingSubKey: false); + } + } + + private static readonly Lazy LazyHkcuTempKey = new Lazy(() => + { + try + { + return Registry.CurrentUser.CreateSubKey(@"SOFTWARE\Microsoft\ASP.NET\temp"); + } + catch + { + // swallow all failures + return null; + } + }); + + private class ConditionalRunTestOnlyIfHkcuRegistryAvailable : Attribute, ITestCondition + { + public bool IsMet => (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && LazyHkcuTempKey.Value != null); + + public string SkipReason { get; } = "HKCU registry couldn't be opened."; + } + + private class MyKeyEscrowSink1 : IKeyEscrowSink + { + public void Store(Guid keyId, XElement element) + { + throw new NotImplementedException(); + } + } + + private class MyKeyEscrowSink2 : IKeyEscrowSink + { + public void Store(Guid keyId, XElement element) + { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/CacheableKeyRingTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/CacheableKeyRingTests.cs new file mode 100644 index 0000000000..27eaa3bf31 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/CacheableKeyRingTests.cs @@ -0,0 +1,61 @@ +// 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.Threading; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + public class CacheableKeyRingTests + { + [Fact] + public void IsValid_NullKeyRing_ReturnsFalse() + { + Assert.False(CacheableKeyRing.IsValid(null, DateTime.UtcNow)); + } + + [Fact] + public void IsValid_CancellationTokenTriggered_ReturnsFalse() + { + // Arrange + var keyRing = new Mock().Object; + DateTimeOffset now = DateTimeOffset.UtcNow; + var cts = new CancellationTokenSource(); + var cacheableKeyRing = new CacheableKeyRing(cts.Token, now.AddHours(1), keyRing); + + // Act & assert + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now.UtcDateTime)); + cts.Cancel(); + Assert.False(CacheableKeyRing.IsValid(cacheableKeyRing, now.UtcDateTime)); + } + + [Fact] + public void IsValid_Expired_ReturnsFalse() + { + // Arrange + var keyRing = new Mock().Object; + DateTimeOffset now = DateTimeOffset.UtcNow; + var cts = new CancellationTokenSource(); + var cacheableKeyRing = new CacheableKeyRing(cts.Token, now.AddHours(1), keyRing); + + // Act & assert + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now.UtcDateTime)); + Assert.False(CacheableKeyRing.IsValid(cacheableKeyRing, now.AddHours(1).UtcDateTime)); + } + + + [Fact] + public void KeyRing_Prop() + { + // Arrange + var keyRing = new Mock().Object; + var cacheableKeyRing = new CacheableKeyRing(CancellationToken.None, DateTimeOffset.Now, keyRing); + + // Act & assert + Assert.Same(keyRing, cacheableKeyRing.KeyRing); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DefaultKeyResolverTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DefaultKeyResolverTests.cs new file mode 100644 index 0000000000..46e9b5f993 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DefaultKeyResolverTests.cs @@ -0,0 +1,277 @@ +// 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.Collections.Generic; +using System.Globalization; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + public class DefaultKeyResolverTests + { + [Fact] + public void ResolveDefaultKeyPolicy_EmptyKeyRing_ReturnsNullDefaultKey() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy(DateTimeOffset.Now, new IKey[0]); + + // Assert + Assert.Null(resolution.DefaultKey); + Assert.True(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_ValidExistingKey_ReturnsExistingKey() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2016-02-20 23:59:00Z", key1, key2); + + // Assert + Assert.Same(key1, resolution.DefaultKey); + Assert.False(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_ValidExistingKey_AllowsForClockSkew_KeysStraddleSkewLine_ReturnsExistingKey() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2016-02-29 23:59:00Z", key1, key2); + + // Assert + Assert.Same(key2, resolution.DefaultKey); + Assert.False(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_ValidExistingKey_AllowsForClockSkew_AllKeysInFuture_ReturnsExistingKey() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2016-02-29 23:59:00Z", key1); + + // Assert + Assert.Same(key1, resolution.DefaultKey); + Assert.False(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_ValidExistingKey_NoSuccessor_ReturnsExistingKey_SignalsGenerateNewKey() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2016-02-29 23:59:00Z", key1); + + // Assert + Assert.Same(key1, resolution.DefaultKey); + Assert.True(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_ValidExistingKey_NoLegitimateSuccessor_ReturnsExistingKey_SignalsGenerateNewKey() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z", isRevoked: true); + var key3 = CreateKey("2016-03-01 00:00:00Z", "2016-03-02 00:00:00Z"); // key expires too soon + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2016-02-29 23:50:00Z", key1, key2, key3); + + // Assert + Assert.Same(key1, resolution.DefaultKey); + Assert.True(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_MostRecentKeyIsInvalid_BecauseOfRevocation_ReturnsNull() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var key2 = CreateKey("2015-03-02 00:00:00Z", "2016-03-01 00:00:00Z", isRevoked: true); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2015-04-01 00:00:00Z", key1, key2); + + // Assert + Assert.Null(resolution.DefaultKey); + Assert.True(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_MostRecentKeyIsInvalid_BecauseOfFailureToDecipher_ReturnsNull() + { + // Arrange + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var key2 = CreateKey("2015-03-02 00:00:00Z", "2016-03-01 00:00:00Z", createEncryptorThrows: true); + var resolver = CreateDefaultKeyResolver(); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2015-04-01 00:00:00Z", key1, key2); + + // Assert + Assert.Null(resolution.DefaultKey); + Assert.True(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_FutureKeyIsValidAndWithinClockSkew_ReturnsFutureKey() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2015-02-28 23:55:00Z", key1); + + // Assert + Assert.Same(key1, resolution.DefaultKey); + Assert.False(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_FutureKeyIsValidButNotWithinClockSkew_ReturnsNull() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2015-02-28 23:00:00Z", key1); + + // Assert + Assert.Null(resolution.DefaultKey); + Assert.True(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_IgnoresExpiredOrRevokedFutureKeys() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2014-03-01 00:00:00Z"); // expiration before activation should never occur + var key2 = CreateKey("2015-03-01 00:01:00Z", "2015-04-01 00:00:00Z", isRevoked: true); + var key3 = CreateKey("2015-03-01 00:02:00Z", "2015-04-01 00:00:00Z"); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2015-02-28 23:59:00Z", key1, key2, key3); + + // Assert + Assert.Same(key3, resolution.DefaultKey); + Assert.False(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_FallbackKey_SelectsLatestBeforePriorPropagationWindow_IgnoresRevokedKeys() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-01 00:00:00Z"); + var key2 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-02 00:00:00Z"); + var key3 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-03 00:00:00Z", isRevoked: true); + var key4 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-04 00:00:00Z"); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2000-01-05 00:00:00Z", key1, key2, key3, key4); + + // Assert + Assert.Same(key2, resolution.FallbackKey); + Assert.True(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_FallbackKey_SelectsLatestBeforePriorPropagationWindow_IgnoresFailures() + { + // Arrange + var key1 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-01 00:00:00Z"); + var key2 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-02 00:00:00Z"); + var key3 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-03 00:00:00Z", createEncryptorThrows: true); + var key4 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-04 00:00:00Z"); + var resolver = CreateDefaultKeyResolver(); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2000-01-05 00:00:00Z", key1, key2, key3, key4); + + // Assert + Assert.Same(key2, resolution.FallbackKey); + Assert.True(resolution.ShouldGenerateNewKey); + } + + [Fact] + public void ResolveDefaultKeyPolicy_FallbackKey_NoNonRevokedKeysBeforePriorPropagationWindow_SelectsEarliestNonRevokedKey() + { + // Arrange + var resolver = CreateDefaultKeyResolver(); + var key1 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-03 00:00:00Z", isRevoked: true); + var key2 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-04 00:00:00Z"); + var key3 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-05 00:00:00Z"); + + // Act + var resolution = resolver.ResolveDefaultKeyPolicy("2000-01-05 00:00:00Z", key1, key2, key3); + + // Assert + Assert.Same(key2, resolution.FallbackKey); + Assert.True(resolution.ShouldGenerateNewKey); + } + + private static IDefaultKeyResolver CreateDefaultKeyResolver() + { + var options = Options.Create(new KeyManagementOptions()); + return new DefaultKeyResolver(options, NullLoggerFactory.Instance); + } + + private static IKey CreateKey(string activationDate, string expirationDate, string creationDate = null, bool isRevoked = false, bool createEncryptorThrows = false) + { + var mockKey = new Mock(); + mockKey.Setup(o => o.KeyId).Returns(Guid.NewGuid()); + mockKey.Setup(o => o.CreationDate).Returns((creationDate != null) ? DateTimeOffset.ParseExact(creationDate, "u", CultureInfo.InvariantCulture) : DateTimeOffset.MinValue); + mockKey.Setup(o => o.ActivationDate).Returns(DateTimeOffset.ParseExact(activationDate, "u", CultureInfo.InvariantCulture)); + mockKey.Setup(o => o.ExpirationDate).Returns(DateTimeOffset.ParseExact(expirationDate, "u", CultureInfo.InvariantCulture)); + mockKey.Setup(o => o.IsRevoked).Returns(isRevoked); + if (createEncryptorThrows) + { + mockKey.Setup(o => o.CreateEncryptor()).Throws(new Exception("This method fails.")); + } + else + { + mockKey.Setup(o => o.CreateEncryptor()).Returns(Mock.Of()); + } + + return mockKey.Object; + } + } + + internal static class DefaultKeyResolverExtensions + { + public static DefaultKeyResolution ResolveDefaultKeyPolicy(this IDefaultKeyResolver resolver, string now, params IKey[] allKeys) + { + return resolver.ResolveDefaultKeyPolicy(DateTimeOffset.ParseExact(now, "u", CultureInfo.InvariantCulture), (IEnumerable)allKeys); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DeferredKeyTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DeferredKeyTests.cs new file mode 100644 index 0000000000..2a166564d0 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DeferredKeyTests.cs @@ -0,0 +1,84 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + public class DeferredKeyTests + { + [Fact] + public void Ctor_Properties() + { + // Arrange + var keyId = Guid.NewGuid(); + var creationDate = DateTimeOffset.Now; + var activationDate = creationDate.AddDays(2); + var expirationDate = creationDate.AddDays(90); + var mockDescriptor = Mock.Of(); + var mockInternalKeyManager = new Mock(); + mockInternalKeyManager.Setup(o => o.DeserializeDescriptorFromKeyElement(It.IsAny())) + .Returns(element => + { + XmlAssert.Equal(@"", element); + return mockDescriptor; + }); + var encryptorFactory = Mock.Of(); + + // Act + var key = new DeferredKey(keyId, creationDate, activationDate, expirationDate, mockInternalKeyManager.Object, XElement.Parse(@""), new[] { encryptorFactory }); + + // Assert + Assert.Equal(keyId, key.KeyId); + Assert.Equal(creationDate, key.CreationDate); + Assert.Equal(activationDate, key.ActivationDate); + Assert.Equal(expirationDate, key.ExpirationDate); + Assert.Same(mockDescriptor, key.Descriptor); + } + + [Fact] + public void SetRevoked_Respected() + { + // Arrange + var now = DateTimeOffset.UtcNow; + var encryptorFactory = Mock.Of(); + var key = new DeferredKey(Guid.Empty, now, now, now, new Mock().Object, XElement.Parse(@""), new[] { encryptorFactory }); + + // Act & assert + Assert.False(key.IsRevoked); + key.SetRevoked(); + Assert.True(key.IsRevoked); + } + + [Fact] + public void Get_Descriptor_CachesFailures() + { + // Arrange + int numTimesCalled = 0; + var mockKeyManager = new Mock(); + mockKeyManager.Setup(o => o.DeserializeDescriptorFromKeyElement(It.IsAny())) + .Returns(element => + { + numTimesCalled++; + throw new Exception("How exceptional."); + }); + + var now = DateTimeOffset.UtcNow; + var encryptorFactory = Mock.Of(); + var key = new DeferredKey(Guid.Empty, now, now, now, mockKeyManager.Object, XElement.Parse(@""), new[] { encryptorFactory }); + + // Act & assert + ExceptionAssert.Throws(() => key.Descriptor, "How exceptional."); + ExceptionAssert.Throws(() => key.Descriptor, "How exceptional."); + Assert.Equal(1, numTimesCalled); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyEscrowServiceProviderExtensionsTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyEscrowServiceProviderExtensionsTests.cs new file mode 100644 index 0000000000..8db64657db --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyEscrowServiceProviderExtensionsTests.cs @@ -0,0 +1,90 @@ +// 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.Collections.Generic; +using System.Globalization; +using System.Xml.Linq; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + public class KeyEscrowServiceProviderExtensionsTests + { + [Fact] + public void GetKeyEscrowSink_NullServiceProvider_ReturnsNull() + { + Assert.Null(((IServiceProvider)null).GetKeyEscrowSink()); + } + + [Fact] + public void GetKeyEscrowSink_EmptyServiceProvider_ReturnsNull() + { + // Arrange + var services = new ServiceCollection().BuildServiceProvider(); + + // Act & assert + Assert.Null(services.GetKeyEscrowSink()); + } + + [Fact] + public void GetKeyEscrowSink_SingleKeyEscrowRegistration_ReturnsAggregateOverSingleSink() + { + // Arrange + List output = new List(); + + var mockKeyEscrowSink = new Mock(); + mockKeyEscrowSink.Setup(o => o.Store(It.IsAny(), It.IsAny())) + .Callback((keyId, element) => + { + output.Add(string.Format(CultureInfo.InvariantCulture, "{0:D}: {1}", keyId, element.Name.LocalName)); + }); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(mockKeyEscrowSink.Object); + var services = serviceCollection.BuildServiceProvider(); + + // Act + var sink = services.GetKeyEscrowSink(); + sink.Store(new Guid("39974d8e-3e53-4d78-b7e9-4ff64a2a5d7b"), XElement.Parse("")); + + // Assert + Assert.Equal(new[] { "39974d8e-3e53-4d78-b7e9-4ff64a2a5d7b: theElement" }, output); + } + + [Fact] + public void GetKeyEscrowSink_MultipleKeyEscrowRegistration_ReturnsAggregate() + { + // Arrange + List output = new List(); + + var mockKeyEscrowSink1 = new Mock(); + mockKeyEscrowSink1.Setup(o => o.Store(It.IsAny(), It.IsAny())) + .Callback((keyId, element) => + { + output.Add(string.Format(CultureInfo.InvariantCulture, "[sink1] {0:D}: {1}", keyId, element.Name.LocalName)); + }); + + var mockKeyEscrowSink2 = new Mock(); + mockKeyEscrowSink2.Setup(o => o.Store(It.IsAny(), It.IsAny())) + .Callback((keyId, element) => + { + output.Add(string.Format(CultureInfo.InvariantCulture, "[sink2] {0:D}: {1}", keyId, element.Name.LocalName)); + }); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(mockKeyEscrowSink1.Object); + serviceCollection.AddSingleton(mockKeyEscrowSink2.Object); + var services = serviceCollection.BuildServiceProvider(); + + // Act + var sink = services.GetKeyEscrowSink(); + sink.Store(new Guid("39974d8e-3e53-4d78-b7e9-4ff64a2a5d7b"), XElement.Parse("")); + + // Assert + Assert.Equal(new[] { "[sink1] 39974d8e-3e53-4d78-b7e9-4ff64a2a5d7b: theElement", "[sink2] 39974d8e-3e53-4d78-b7e9-4ff64a2a5d7b: theElement" }, output); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingBasedDataProtectorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingBasedDataProtectorTests.cs new file mode 100644 index 0000000000..d28ea7ff84 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingBasedDataProtectorTests.cs @@ -0,0 +1,500 @@ +// 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.IO; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Text; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + public class KeyRingBasedDataProtectorTests + { + [Fact] + public void Protect_NullPlaintext_Throws() + { + // Arrange + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: new Mock().Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + // Act & assert + ExceptionAssert.ThrowsArgumentNull(() => protector.Protect(plaintext: null), "plaintext"); + } + + [Fact] + public void Protect_EncryptsToDefaultProtector_MultiplePurposes() + { + // Arrange + Guid defaultKey = new Guid("ba73c9ce-d322-4e45-af90-341307e11c38"); + byte[] expectedPlaintext = new byte[] { 0x03, 0x05, 0x07, 0x11, 0x13, 0x17, 0x19 }; + byte[] expectedAad = BuildAadFromPurposeStrings(defaultKey, "purpose1", "purpose2", "yet another purpose"); + byte[] expectedProtectedData = BuildProtectedDataFromCiphertext(defaultKey, new byte[] { 0x23, 0x29, 0x31, 0x37 }); + + var mockEncryptor = new Mock(); + mockEncryptor + .Setup(o => o.Encrypt(It.IsAny>(), It.IsAny>())) + .Returns, ArraySegment>((actualPlaintext, actualAad) => + { + Assert.Equal(expectedPlaintext, actualPlaintext); + Assert.Equal(expectedAad, actualAad); + return new byte[] { 0x23, 0x29, 0x31, 0x37 }; // ciphertext + tag + }); + + var mockKeyRing = new Mock(MockBehavior.Strict); + mockKeyRing.Setup(o => o.DefaultKeyId).Returns(defaultKey); + mockKeyRing.Setup(o => o.DefaultAuthenticatedEncryptor).Returns(mockEncryptor.Object); + var mockKeyRingProvider = new Mock(); + mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(mockKeyRing.Object); + + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: mockKeyRingProvider.Object, + logger: GetLogger(), + originalPurposes: new[] { "purpose1", "purpose2" }, + newPurpose: "yet another purpose"); + + // Act + byte[] retVal = protector.Protect(expectedPlaintext); + + // Assert + Assert.Equal(expectedProtectedData, retVal); + } + + [Fact] + public void Protect_EncryptsToDefaultProtector_SinglePurpose() + { + // Arrange + Guid defaultKey = new Guid("ba73c9ce-d322-4e45-af90-341307e11c38"); + byte[] expectedPlaintext = new byte[] { 0x03, 0x05, 0x07, 0x11, 0x13, 0x17, 0x19 }; + byte[] expectedAad = BuildAadFromPurposeStrings(defaultKey, "single purpose"); + byte[] expectedProtectedData = BuildProtectedDataFromCiphertext(defaultKey, new byte[] { 0x23, 0x29, 0x31, 0x37 }); + + var mockEncryptor = new Mock(); + mockEncryptor + .Setup(o => o.Encrypt(It.IsAny>(), It.IsAny>())) + .Returns, ArraySegment>((actualPlaintext, actualAad) => + { + Assert.Equal(expectedPlaintext, actualPlaintext); + Assert.Equal(expectedAad, actualAad); + return new byte[] { 0x23, 0x29, 0x31, 0x37 }; // ciphertext + tag + }); + + var mockKeyRing = new Mock(MockBehavior.Strict); + mockKeyRing.Setup(o => o.DefaultKeyId).Returns(defaultKey); + mockKeyRing.Setup(o => o.DefaultAuthenticatedEncryptor).Returns(mockEncryptor.Object); + var mockKeyRingProvider = new Mock(); + mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(mockKeyRing.Object); + + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: mockKeyRingProvider.Object, + logger: GetLogger(), + originalPurposes: new string[0], + newPurpose: "single purpose"); + + // Act + byte[] retVal = protector.Protect(expectedPlaintext); + + // Assert + Assert.Equal(expectedProtectedData, retVal); + } + + [Fact] + public void Protect_HomogenizesExceptionsToCryptographicException() + { + // Arrange + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: new Mock(MockBehavior.Strict).Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + // Act & assert + var ex = ExceptionAssert2.ThrowsCryptographicException(() => protector.Protect(new byte[0])); + Assert.IsAssignableFrom(ex.InnerException); + } + + [Fact] + public void Unprotect_NullProtectedData_Throws() + { + // Arrange + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: new Mock().Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + // Act & assert + ExceptionAssert.ThrowsArgumentNull(() => protector.Unprotect(protectedData: null), "protectedData"); + } + + [Fact] + public void Unprotect_PayloadTooShort_ThrowsBadMagicHeader() + { + // Arrange + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: new Mock().Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + byte[] badProtectedPayload = BuildProtectedDataFromCiphertext(Guid.NewGuid(), new byte[0]); + badProtectedPayload = badProtectedPayload.Take(badProtectedPayload.Length - 1).ToArray(); // chop off the last byte + + // Act & assert + var ex = ExceptionAssert2.ThrowsCryptographicException(() => protector.Unprotect(badProtectedPayload)); + Assert.Equal(Resources.ProtectionProvider_BadMagicHeader, ex.Message); + } + + [Fact] + public void Unprotect_PayloadHasBadMagicHeader_ThrowsBadMagicHeader() + { + // Arrange + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: new Mock().Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + byte[] badProtectedPayload = BuildProtectedDataFromCiphertext(Guid.NewGuid(), new byte[0]); + badProtectedPayload[0]++; // corrupt the magic header + + // Act & assert + var ex = ExceptionAssert2.ThrowsCryptographicException(() => protector.Unprotect(badProtectedPayload)); + Assert.Equal(Resources.ProtectionProvider_BadMagicHeader, ex.Message); + } + + [Fact] + public void Unprotect_PayloadHasIncorrectVersionMarker_ThrowsNewerVersion() + { + // Arrange + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: new Mock().Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + byte[] badProtectedPayload = BuildProtectedDataFromCiphertext(Guid.NewGuid(), new byte[0]); + badProtectedPayload[3]++; // bump the version payload + + // Act & assert + var ex = ExceptionAssert2.ThrowsCryptographicException(() => protector.Unprotect(badProtectedPayload)); + Assert.Equal(Resources.ProtectionProvider_BadVersion, ex.Message); + } + + [Fact] + public void Unprotect_KeyNotFound_ThrowsKeyNotFound() + { + // Arrange + Guid notFoundKeyId = new Guid("654057ab-2491-4471-a72a-b3b114afda38"); + byte[] protectedData = BuildProtectedDataFromCiphertext( + keyId: notFoundKeyId, + ciphertext: new byte[0]); + + var mockDescriptor = new Mock(); + var mockEncryptorFactory = new Mock(); + mockEncryptorFactory.Setup(o => o.CreateEncryptorInstance(It.IsAny())).Returns(new Mock().Object); + var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + + // the keyring has only one key + Key key = new Key(Guid.Empty, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); + var keyRing = new KeyRing(key, new[] { key }); + var mockKeyRingProvider = new Mock(); + mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); + + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: mockKeyRingProvider.Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + // Act & assert + var ex = ExceptionAssert2.ThrowsCryptographicException(() => protector.Unprotect(protectedData)); + Assert.Equal(Error.Common_KeyNotFound(notFoundKeyId).Message, ex.Message); + } + + [Fact] + public void Unprotect_KeyRevoked_RevocationDisallowed_ThrowsKeyRevoked() + { + // Arrange + Guid keyId = new Guid("654057ab-2491-4471-a72a-b3b114afda38"); + byte[] protectedData = BuildProtectedDataFromCiphertext( + keyId: keyId, + ciphertext: new byte[0]); + + var mockDescriptor = new Mock(); + var mockEncryptorFactory = new Mock(); + mockEncryptorFactory.Setup(o => o.CreateEncryptorInstance(It.IsAny())).Returns(new Mock().Object); + + // the keyring has only one key + Key key = new Key(keyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); + key.SetRevoked(); + var keyRing = new KeyRing(key, new[] { key }); + var mockKeyRingProvider = new Mock(); + mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); + + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: mockKeyRingProvider.Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + // Act & assert + var ex = ExceptionAssert2.ThrowsCryptographicException(() => protector.Unprotect(protectedData)); + Assert.Equal(Error.Common_KeyRevoked(keyId).Message, ex.Message); + } + + [Fact] + public void Unprotect_KeyRevoked_RevocationAllowed_ReturnsOriginalData_SetsRevokedAndMigrationFlags() + { + // Arrange + Guid defaultKeyId = new Guid("ba73c9ce-d322-4e45-af90-341307e11c38"); + byte[] expectedCiphertext = new byte[] { 0x03, 0x05, 0x07, 0x11, 0x13, 0x17, 0x19 }; + byte[] protectedData = BuildProtectedDataFromCiphertext(defaultKeyId, expectedCiphertext); + byte[] expectedAad = BuildAadFromPurposeStrings(defaultKeyId, "purpose"); + byte[] expectedPlaintext = new byte[] { 0x23, 0x29, 0x31, 0x37 }; + + var mockEncryptor = new Mock(); + mockEncryptor + .Setup(o => o.Decrypt(It.IsAny>(), It.IsAny>())) + .Returns, ArraySegment>((actualCiphertext, actualAad) => + { + Assert.Equal(expectedCiphertext, actualCiphertext); + Assert.Equal(expectedAad, actualAad); + return expectedPlaintext; + }); + var mockDescriptor = new Mock(); + var mockEncryptorFactory = new Mock(); + mockEncryptorFactory.Setup(o => o.CreateEncryptorInstance(It.IsAny())).Returns(mockEncryptor.Object); + + Key defaultKey = new Key(defaultKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); + defaultKey.SetRevoked(); + var keyRing = new KeyRing(defaultKey, new[] { defaultKey }); + var mockKeyRingProvider = new Mock(); + mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); + + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: mockKeyRingProvider.Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + // Act + byte[] retVal = ((IPersistedDataProtector)protector).DangerousUnprotect(protectedData, + ignoreRevocationErrors: true, + requiresMigration: out var requiresMigration, + wasRevoked: out var wasRevoked); + + // Assert + Assert.Equal(expectedPlaintext, retVal); + Assert.True(requiresMigration); + Assert.True(wasRevoked); + } + + [Fact] + public void Unprotect_IsAlsoDefaultKey_Success_NoMigrationRequired() + { + // Arrange + Guid defaultKeyId = new Guid("ba73c9ce-d322-4e45-af90-341307e11c38"); + byte[] expectedCiphertext = new byte[] { 0x03, 0x05, 0x07, 0x11, 0x13, 0x17, 0x19 }; + byte[] protectedData = BuildProtectedDataFromCiphertext(defaultKeyId, expectedCiphertext); + byte[] expectedAad = BuildAadFromPurposeStrings(defaultKeyId, "purpose"); + byte[] expectedPlaintext = new byte[] { 0x23, 0x29, 0x31, 0x37 }; + + var mockEncryptor = new Mock(); + mockEncryptor + .Setup(o => o.Decrypt(It.IsAny>(), It.IsAny>())) + .Returns, ArraySegment>((actualCiphertext, actualAad) => + { + Assert.Equal(expectedCiphertext, actualCiphertext); + Assert.Equal(expectedAad, actualAad); + return expectedPlaintext; + }); + var mockDescriptor = new Mock(); + var mockEncryptorFactory = new Mock(); + mockEncryptorFactory.Setup(o => o.CreateEncryptorInstance(It.IsAny())).Returns(mockEncryptor.Object); + + Key defaultKey = new Key(defaultKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); + var keyRing = new KeyRing(defaultKey, new[] { defaultKey }); + var mockKeyRingProvider = new Mock(); + mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); + + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: mockKeyRingProvider.Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + // Act & assert - IDataProtector + byte[] retVal = protector.Unprotect(protectedData); + Assert.Equal(expectedPlaintext, retVal); + + // Act & assert - IPersistedDataProtector + retVal = ((IPersistedDataProtector)protector).DangerousUnprotect(protectedData, + ignoreRevocationErrors: false, + requiresMigration: out var requiresMigration, + wasRevoked: out var wasRevoked); + Assert.Equal(expectedPlaintext, retVal); + Assert.False(requiresMigration); + Assert.False(wasRevoked); + } + + [Fact] + public void Unprotect_IsNotDefaultKey_Success_RequiresMigration() + { + // Arrange + Guid defaultKeyId = new Guid("ba73c9ce-d322-4e45-af90-341307e11c38"); + Guid embeddedKeyId = new Guid("9b5d2db3-299f-4eac-89e9-e9067a5c1853"); + byte[] expectedCiphertext = new byte[] { 0x03, 0x05, 0x07, 0x11, 0x13, 0x17, 0x19 }; + byte[] protectedData = BuildProtectedDataFromCiphertext(embeddedKeyId, expectedCiphertext); + byte[] expectedAad = BuildAadFromPurposeStrings(embeddedKeyId, "purpose"); + byte[] expectedPlaintext = new byte[] { 0x23, 0x29, 0x31, 0x37 }; + + var mockEncryptor = new Mock(); + mockEncryptor + .Setup(o => o.Decrypt(It.IsAny>(), It.IsAny>())) + .Returns, ArraySegment>((actualCiphertext, actualAad) => + { + Assert.Equal(expectedCiphertext, actualCiphertext); + Assert.Equal(expectedAad, actualAad); + return expectedPlaintext; + }); + var mockDescriptor = new Mock(); + var mockEncryptorFactory = new Mock(); + mockEncryptorFactory.Setup(o => o.CreateEncryptorInstance(It.IsAny())).Returns(mockEncryptor.Object); + + Key defaultKey = new Key(defaultKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, new Mock().Object, new[] { mockEncryptorFactory.Object }); + Key embeddedKey = new Key(embeddedKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); + var keyRing = new KeyRing(defaultKey, new[] { defaultKey, embeddedKey }); + var mockKeyRingProvider = new Mock(); + mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); + + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: mockKeyRingProvider.Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + // Act & assert - IDataProtector + byte[] retVal = protector.Unprotect(protectedData); + Assert.Equal(expectedPlaintext, retVal); + + // Act & assert - IPersistedDataProtector + retVal = ((IPersistedDataProtector)protector).DangerousUnprotect(protectedData, + ignoreRevocationErrors: false, + requiresMigration: out var requiresMigration, + wasRevoked: out var wasRevoked); + Assert.Equal(expectedPlaintext, retVal); + Assert.True(requiresMigration); + Assert.False(wasRevoked); + } + + [Fact] + public void Protect_Unprotect_RoundTripsProperly() + { + // Arrange + byte[] plaintext = new byte[] { 0x10, 0x20, 0x30, 0x40, 0x50 }; + var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + Key key = new Key(Guid.NewGuid(), DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, new AuthenticatedEncryptorConfiguration().CreateNewDescriptor(), new[] { encryptorFactory }); + var keyRing = new KeyRing(key, new[] { key }); + var mockKeyRingProvider = new Mock(); + mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); + + var protector = new KeyRingBasedDataProtector( + keyRingProvider: mockKeyRingProvider.Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose"); + + // Act - protect + byte[] protectedData = protector.Protect(plaintext); + Assert.NotNull(protectedData); + Assert.NotEqual(plaintext, protectedData); + + // Act - unprotect + byte[] roundTrippedPlaintext = protector.Unprotect(protectedData); + Assert.Equal(plaintext, roundTrippedPlaintext); + } + + [Fact] + public void CreateProtector_ChainsPurposes() + { + // Arrange + Guid defaultKey = new Guid("ba73c9ce-d322-4e45-af90-341307e11c38"); + byte[] expectedPlaintext = new byte[] { 0x03, 0x05, 0x07, 0x11, 0x13, 0x17, 0x19 }; + byte[] expectedAad = BuildAadFromPurposeStrings(defaultKey, "purpose1", "purpose2"); + byte[] expectedProtectedData = BuildProtectedDataFromCiphertext(defaultKey, new byte[] { 0x23, 0x29, 0x31, 0x37 }); + + var mockEncryptor = new Mock(); + mockEncryptor + .Setup(o => o.Encrypt(It.IsAny>(), It.IsAny>())) + .Returns, ArraySegment>((actualPlaintext, actualAad) => + { + Assert.Equal(expectedPlaintext, actualPlaintext); + Assert.Equal(expectedAad, actualAad); + return new byte[] { 0x23, 0x29, 0x31, 0x37 }; // ciphertext + tag + }); + + var mockKeyRing = new Mock(MockBehavior.Strict); + mockKeyRing.Setup(o => o.DefaultKeyId).Returns(defaultKey); + mockKeyRing.Setup(o => o.DefaultAuthenticatedEncryptor).Returns(mockEncryptor.Object); + var mockKeyRingProvider = new Mock(); + mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(mockKeyRing.Object); + + IDataProtector protector = new KeyRingBasedDataProtector( + keyRingProvider: mockKeyRingProvider.Object, + logger: GetLogger(), + originalPurposes: null, + newPurpose: "purpose1").CreateProtector("purpose2"); + + // Act + byte[] retVal = protector.Protect(expectedPlaintext); + + // Assert + Assert.Equal(expectedProtectedData, retVal); + } + + private static byte[] BuildAadFromPurposeStrings(Guid keyId, params string[] purposes) + { + var expectedAad = new byte[] { 0x09, 0xF0, 0xC9, 0xF0 } // magic header + .Concat(keyId.ToByteArray()) // key id + .Concat(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(purposes.Length))); // purposeCount + + foreach (string purpose in purposes) + { + var memStream = new MemoryStream(); + var writer = new BinaryWriter(memStream, encoding: new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), leaveOpen: true); + writer.Write(purpose); // also writes 7-bit encoded int length + writer.Dispose(); + expectedAad = expectedAad.Concat(memStream.ToArray()); + } + + return expectedAad.ToArray(); + } + + private static byte[] BuildProtectedDataFromCiphertext(Guid keyId, byte[] ciphertext) + { + return new byte[] { 0x09, 0xF0, 0xC9, 0xF0 } // magic header + .Concat(keyId.ToByteArray()) // key id + .Concat(ciphertext).ToArray(); + + } + + private static ILogger GetLogger() + { + var loggerFactory = NullLoggerFactory.Instance; + return loggerFactory.CreateLogger(typeof(KeyRingBasedDataProtector)); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingProviderTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingProviderTests.cs new file mode 100644 index 0000000000..8582ed8359 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingProviderTests.cs @@ -0,0 +1,652 @@ +// 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.Collections.Generic; +using System.Globalization; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + public class KeyRingProviderTests + { + [Fact] + public void CreateCacheableKeyRing_NoGenerationRequired_DefaultKeyExpiresAfterRefreshPeriod() + { + // Arrange + var callSequence = new List(); + var expirationCts = new CancellationTokenSource(); + + var now = StringToDateTime("2015-03-01 00:00:00Z"); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); + var allKeys = new[] { key1, key2 }; + + var keyRingProvider = SetupCreateCacheableKeyRingTestAndCreateKeyManager( + callSequence: callSequence, + getCacheExpirationTokenReturnValues: new[] { expirationCts.Token }, + getAllKeysReturnValues: new[] { allKeys }, + createNewKeyCallbacks: null, + resolveDefaultKeyPolicyReturnValues: new[] + { + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys, new DefaultKeyResolution() + { + DefaultKey = key1, + ShouldGenerateNewKey = false + }) + }); + + // Act + var cacheableKeyRing = keyRingProvider.GetCacheableKeyRing(now); + + // Assert + Assert.Equal(key1.KeyId, cacheableKeyRing.KeyRing.DefaultKeyId); + AssertWithinJitterRange(cacheableKeyRing.ExpirationTimeUtc, now); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts.Cancel(); + Assert.False(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + Assert.Equal(new[] { "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy" }, callSequence); + } + + [Fact] + public void CreateCacheableKeyRing_NoGenerationRequired_DefaultKeyExpiresBeforeRefreshPeriod() + { + // Arrange + var callSequence = new List(); + var expirationCts = new CancellationTokenSource(); + + var now = StringToDateTime("2016-02-29 20:00:00Z"); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); + var allKeys = new[] { key1, key2 }; + + var keyRingProvider = SetupCreateCacheableKeyRingTestAndCreateKeyManager( + callSequence: callSequence, + getCacheExpirationTokenReturnValues: new[] { expirationCts.Token }, + getAllKeysReturnValues: new[] { allKeys }, + createNewKeyCallbacks: null, + resolveDefaultKeyPolicyReturnValues: new[] + { + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys, new DefaultKeyResolution() + { + DefaultKey = key1, + ShouldGenerateNewKey = false + }) + }); + + // Act + var cacheableKeyRing = keyRingProvider.GetCacheableKeyRing(now); + + // Assert + Assert.Equal(key1.KeyId, cacheableKeyRing.KeyRing.DefaultKeyId); + Assert.Equal(StringToDateTime("2016-03-01 00:00:00Z"), cacheableKeyRing.ExpirationTimeUtc); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts.Cancel(); + Assert.False(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + Assert.Equal(new[] { "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy" }, callSequence); + } + + [Fact] + public void CreateCacheableKeyRing_GenerationRequired_NoDefaultKey_CreatesNewKeyWithImmediateActivation() + { + // Arrange + var callSequence = new List(); + var expirationCts1 = new CancellationTokenSource(); + var expirationCts2 = new CancellationTokenSource(); + + var now = StringToDateTime("2015-03-01 00:00:00Z"); + var allKeys1 = new IKey[0]; + + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); + var allKeys2 = new[] { key1, key2 }; + + var keyRingProvider = SetupCreateCacheableKeyRingTestAndCreateKeyManager( + callSequence: callSequence, + getCacheExpirationTokenReturnValues: new[] { expirationCts1.Token, expirationCts2.Token }, + getAllKeysReturnValues: new[] { allKeys1, allKeys2 }, + createNewKeyCallbacks: new[] { + Tuple.Create((DateTimeOffset)now, (DateTimeOffset)now + TimeSpan.FromDays(90), CreateKey()) + }, + resolveDefaultKeyPolicyReturnValues: new[] + { + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys1, new DefaultKeyResolution() + { + DefaultKey = null, + ShouldGenerateNewKey = true + }), + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys2, new DefaultKeyResolution() + { + DefaultKey = key1, + ShouldGenerateNewKey = false + }) + }); + + // Act + var cacheableKeyRing = keyRingProvider.GetCacheableKeyRing(now); + + // Assert + Assert.Equal(key1.KeyId, cacheableKeyRing.KeyRing.DefaultKeyId); + AssertWithinJitterRange(cacheableKeyRing.ExpirationTimeUtc, now); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts1.Cancel(); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts2.Cancel(); + Assert.False(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + Assert.Equal(new[] { "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy", "CreateNewKey", "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy" }, callSequence); + } + + [Fact] + public void CreateCacheableKeyRing_GenerationRequired_NoDefaultKey_CreatesNewKeyWithImmediateActivation_StillNoDefaultKey_ReturnsNewlyCreatedKey() + { + // Arrange + var callSequence = new List(); + var expirationCts1 = new CancellationTokenSource(); + var expirationCts2 = new CancellationTokenSource(); + + var now = StringToDateTime("2015-03-01 00:00:00Z"); + var allKeys = new IKey[0]; + + var newlyCreatedKey = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + + var keyRingProvider = SetupCreateCacheableKeyRingTestAndCreateKeyManager( + callSequence: callSequence, + getCacheExpirationTokenReturnValues: new[] { expirationCts1.Token, expirationCts2.Token }, + getAllKeysReturnValues: new[] { allKeys, allKeys }, + createNewKeyCallbacks: new[] { + Tuple.Create((DateTimeOffset)now, (DateTimeOffset)now + TimeSpan.FromDays(90), newlyCreatedKey) + }, + resolveDefaultKeyPolicyReturnValues: new[] + { + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys, new DefaultKeyResolution() + { + DefaultKey = null, + ShouldGenerateNewKey = true + }), + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys, new DefaultKeyResolution() + { + DefaultKey = null, + ShouldGenerateNewKey = true + }) + }); + + // Act + var cacheableKeyRing = keyRingProvider.GetCacheableKeyRing(now); + + // Assert + Assert.Equal(newlyCreatedKey.KeyId, cacheableKeyRing.KeyRing.DefaultKeyId); + AssertWithinJitterRange(cacheableKeyRing.ExpirationTimeUtc, now); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts1.Cancel(); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts2.Cancel(); + Assert.False(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + Assert.Equal(new[] { "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy", "CreateNewKey", "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy" }, callSequence); + } + + [Fact] + public void CreateCacheableKeyRing_GenerationRequired_NoDefaultKey_KeyGenerationDisabled_Fails() + { + // Arrange + var callSequence = new List(); + + var now = StringToDateTime("2015-03-01 00:00:00Z"); + var allKeys = new IKey[0]; + + var keyRingProvider = SetupCreateCacheableKeyRingTestAndCreateKeyManager( + callSequence: callSequence, + getCacheExpirationTokenReturnValues: new[] { CancellationToken.None }, + getAllKeysReturnValues: new[] { allKeys }, + createNewKeyCallbacks: new[] { + Tuple.Create((DateTimeOffset)now, (DateTimeOffset)now + TimeSpan.FromDays(90), CreateKey()) + }, + resolveDefaultKeyPolicyReturnValues: new[] + { + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys, new DefaultKeyResolution() + { + DefaultKey = null, + ShouldGenerateNewKey = true + }) + }, + keyManagementOptions: new KeyManagementOptions() { AutoGenerateKeys = false }); + + // Act + var exception = Assert.Throws(() => keyRingProvider.GetCacheableKeyRing(now)); + + // Assert + Assert.Equal(Resources.KeyRingProvider_NoDefaultKey_AutoGenerateDisabled, exception.Message); + Assert.Equal(new[] { "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy" }, callSequence); + } + + [Fact] + public void CreateCacheableKeyRing_GenerationRequired_WithDefaultKey_CreatesNewKeyWithDeferredActivationAndExpirationBasedOnCreationTime() + { + // Arrange + var callSequence = new List(); + var expirationCts1 = new CancellationTokenSource(); + var expirationCts2 = new CancellationTokenSource(); + + var now = StringToDateTime("2016-02-01 00:00:00Z"); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var allKeys1 = new[] { key1 }; + + var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); + var allKeys2 = new[] { key1, key2 }; + + var keyRingProvider = SetupCreateCacheableKeyRingTestAndCreateKeyManager( + callSequence: callSequence, + getCacheExpirationTokenReturnValues: new[] { expirationCts1.Token, expirationCts2.Token }, + getAllKeysReturnValues: new[] { allKeys1, allKeys2 }, + createNewKeyCallbacks: new[] { + Tuple.Create(key1.ExpirationDate, (DateTimeOffset)now + TimeSpan.FromDays(90), CreateKey()) + }, + resolveDefaultKeyPolicyReturnValues: new[] + { + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys1, new DefaultKeyResolution() + { + DefaultKey = key1, + ShouldGenerateNewKey = true + }), + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys2, new DefaultKeyResolution() + { + DefaultKey = key2, + ShouldGenerateNewKey = false + }) + }); + + // Act + var cacheableKeyRing = keyRingProvider.GetCacheableKeyRing(now); + + // Assert + Assert.Equal(key2.KeyId, cacheableKeyRing.KeyRing.DefaultKeyId); + AssertWithinJitterRange(cacheableKeyRing.ExpirationTimeUtc, now); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts1.Cancel(); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts2.Cancel(); + Assert.False(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + Assert.Equal(new[] { "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy", "CreateNewKey", "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy" }, callSequence); + } + + [Fact] + public void CreateCacheableKeyRing_GenerationRequired_WithDefaultKey_KeyGenerationDisabled_DoesNotCreateDefaultKey() + { + // Arrange + var callSequence = new List(); + var expirationCts = new CancellationTokenSource(); + + var now = StringToDateTime("2016-02-01 00:00:00Z"); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); + var allKeys = new[] { key1 }; + + var keyRingProvider = SetupCreateCacheableKeyRingTestAndCreateKeyManager( + callSequence: callSequence, + getCacheExpirationTokenReturnValues: new[] { expirationCts.Token }, + getAllKeysReturnValues: new[] { allKeys }, + createNewKeyCallbacks: null, // empty + resolveDefaultKeyPolicyReturnValues: new[] + { + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys, new DefaultKeyResolution() + { + DefaultKey = key1, + ShouldGenerateNewKey = true + }) + }, + keyManagementOptions: new KeyManagementOptions() { AutoGenerateKeys = false }); + + // Act + var cacheableKeyRing = keyRingProvider.GetCacheableKeyRing(now); + + // Assert + Assert.Equal(key1.KeyId, cacheableKeyRing.KeyRing.DefaultKeyId); + AssertWithinJitterRange(cacheableKeyRing.ExpirationTimeUtc, now); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts.Cancel(); + Assert.False(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + Assert.Equal(new[] { "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy" }, callSequence); + } + + [Fact] + public void CreateCacheableKeyRing_GenerationRequired_WithFallbackKey_KeyGenerationDisabled_DoesNotCreateDefaultKey() + { + // Arrange + var callSequence = new List(); + var expirationCts = new CancellationTokenSource(); + + var now = StringToDateTime("2016-02-01 00:00:00Z"); + var key1 = CreateKey("2015-03-01 00:00:00Z", "2015-03-01 00:00:00Z"); + var allKeys = new[] { key1 }; + + var keyRingProvider = SetupCreateCacheableKeyRingTestAndCreateKeyManager( + callSequence: callSequence, + getCacheExpirationTokenReturnValues: new[] { expirationCts.Token }, + getAllKeysReturnValues: new[] { allKeys }, + createNewKeyCallbacks: null, // empty + resolveDefaultKeyPolicyReturnValues: new[] + { + Tuple.Create((DateTimeOffset)now, (IEnumerable)allKeys, new DefaultKeyResolution() + { + FallbackKey = key1, + ShouldGenerateNewKey = true + }) + }, + keyManagementOptions: new KeyManagementOptions() { AutoGenerateKeys = false }); + + // Act + var cacheableKeyRing = keyRingProvider.GetCacheableKeyRing(now); + + // Assert + Assert.Equal(key1.KeyId, cacheableKeyRing.KeyRing.DefaultKeyId); + AssertWithinJitterRange(cacheableKeyRing.ExpirationTimeUtc, now); + Assert.True(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + expirationCts.Cancel(); + Assert.False(CacheableKeyRing.IsValid(cacheableKeyRing, now)); + Assert.Equal(new[] { "GetCacheExpirationToken", "GetAllKeys", "ResolveDefaultKeyPolicy" }, callSequence); + } + + [Fact] + public void GetCurrentKeyRing_NoKeyRingCached_CachesAndReturns() + { + // Arrange + var now = StringToDateTime("2015-03-01 00:00:00Z"); + var expectedKeyRing = new Mock().Object; + var mockCacheableKeyRingProvider = new Mock(); + mockCacheableKeyRingProvider + .Setup(o => o.GetCacheableKeyRing(now)) + .Returns(new CacheableKeyRing( + expirationToken: CancellationToken.None, + expirationTime: StringToDateTime("2015-03-02 00:00:00Z"), + keyRing: expectedKeyRing)); + + var keyRingProvider = CreateKeyRingProvider(mockCacheableKeyRingProvider.Object); + + // Act + var retVal1 = keyRingProvider.GetCurrentKeyRingCore(now); + var retVal2 = keyRingProvider.GetCurrentKeyRingCore(now + TimeSpan.FromHours(1)); + + // Assert - underlying provider only should have been called once + Assert.Same(expectedKeyRing, retVal1); + Assert.Same(expectedKeyRing, retVal2); + mockCacheableKeyRingProvider.Verify(o => o.GetCacheableKeyRing(It.IsAny()), Times.Once); + } + + [Fact] + public void GetCurrentKeyRing_KeyRingCached_AfterExpiration_ClearsCache() + { + // Arrange + var now = StringToDateTime("2015-03-01 00:00:00Z"); + var expectedKeyRing1 = new Mock().Object; + var expectedKeyRing2 = new Mock().Object; + var mockCacheableKeyRingProvider = new Mock(); + mockCacheableKeyRingProvider + .Setup(o => o.GetCacheableKeyRing(now)) + .Returns(new CacheableKeyRing( + expirationToken: CancellationToken.None, + expirationTime: StringToDateTime("2015-03-01 00:30:00Z"), // expire in half an hour + keyRing: expectedKeyRing1)); + mockCacheableKeyRingProvider + .Setup(o => o.GetCacheableKeyRing(now + TimeSpan.FromHours(1))) + .Returns(new CacheableKeyRing( + expirationToken: CancellationToken.None, + expirationTime: StringToDateTime("2015-03-02 00:00:00Z"), + keyRing: expectedKeyRing2)); + + var keyRingProvider = CreateKeyRingProvider(mockCacheableKeyRingProvider.Object); + + // Act + var retVal1 = keyRingProvider.GetCurrentKeyRingCore(now); + var retVal2 = keyRingProvider.GetCurrentKeyRingCore(now + TimeSpan.FromHours(1)); + + // Assert - underlying provider only should have been called once + Assert.Same(expectedKeyRing1, retVal1); + Assert.Same(expectedKeyRing2, retVal2); + mockCacheableKeyRingProvider.Verify(o => o.GetCacheableKeyRing(It.IsAny()), Times.Exactly(2)); + } + + [Fact] + public void GetCurrentKeyRing_NoExistingKeyRing_HoldsAllThreadsUntilKeyRingCreated() + { + // Arrange + var now = StringToDateTime("2015-03-01 00:00:00Z"); + var expectedKeyRing = new Mock().Object; + var mockCacheableKeyRingProvider = new Mock(); + var keyRingProvider = CreateKeyRingProvider(mockCacheableKeyRingProvider.Object); + + // This test spawns a background thread which calls GetCurrentKeyRing then waits + // for the foreground thread to call GetCurrentKeyRing. When the foreground thread + // blocks (inside the lock), the background thread will return the cached keyring + // object, and the foreground thread should consume that same object instance. + + TimeSpan testTimeout = TimeSpan.FromSeconds(10); + + Thread foregroundThread = Thread.CurrentThread; + ManualResetEventSlim mreBackgroundThreadHasCalledGetCurrentKeyRing = new ManualResetEventSlim(); + ManualResetEventSlim mreForegroundThreadIsCallingGetCurrentKeyRing = new ManualResetEventSlim(); + var backgroundGetKeyRingTask = Task.Run(() => + { + mockCacheableKeyRingProvider + .Setup(o => o.GetCacheableKeyRing(now)) + .Returns(() => + { + mreBackgroundThreadHasCalledGetCurrentKeyRing.Set(); + Assert.True(mreForegroundThreadIsCallingGetCurrentKeyRing.Wait(testTimeout), "Test timed out."); + SpinWait.SpinUntil(() => (foregroundThread.ThreadState & ThreadState.WaitSleepJoin) != 0, testTimeout); + return new CacheableKeyRing( + expirationToken: CancellationToken.None, + expirationTime: StringToDateTime("2015-03-02 00:00:00Z"), + keyRing: expectedKeyRing); + }); + + return keyRingProvider.GetCurrentKeyRingCore(now); + }); + + Assert.True(mreBackgroundThreadHasCalledGetCurrentKeyRing.Wait(testTimeout), "Test timed out."); + mreForegroundThreadIsCallingGetCurrentKeyRing.Set(); + var foregroundRetVal = keyRingProvider.GetCurrentKeyRingCore(now); + backgroundGetKeyRingTask.Wait(testTimeout); + var backgroundRetVal = backgroundGetKeyRingTask.GetAwaiter().GetResult(); + + // Assert - underlying provider only should have been called once + Assert.Same(expectedKeyRing, foregroundRetVal); + Assert.Same(expectedKeyRing, backgroundRetVal); + mockCacheableKeyRingProvider.Verify(o => o.GetCacheableKeyRing(It.IsAny()), Times.Once); + } + + [Fact] + public void GetCurrentKeyRing_WithExpiredExistingKeyRing_AllowsOneThreadToUpdate_ReturnsExistingKeyRingToOtherCallersWithoutBlocking() + { + // Arrange + var originalKeyRing = new Mock().Object; + var originalKeyRingTime = StringToDateTime("2015-03-01 00:00:00Z"); + var updatedKeyRing = new Mock().Object; + var updatedKeyRingTime = StringToDateTime("2015-03-02 00:00:00Z"); + var mockCacheableKeyRingProvider = new Mock(); + var keyRingProvider = CreateKeyRingProvider(mockCacheableKeyRingProvider.Object); + + // In this test, the foreground thread acquires the critial section in GetCurrentKeyRing, + // and the background thread returns the original key ring rather than blocking while + // waiting for the foreground thread to update the key ring. + + TimeSpan testTimeout = TimeSpan.FromSeconds(10); + IKeyRing keyRingReturnedToBackgroundThread = null; + + mockCacheableKeyRingProvider.Setup(o => o.GetCacheableKeyRing(originalKeyRingTime)) + .Returns(new CacheableKeyRing(CancellationToken.None, StringToDateTime("2015-03-02 00:00:00Z"), originalKeyRing)); + mockCacheableKeyRingProvider.Setup(o => o.GetCacheableKeyRing(updatedKeyRingTime)) + .Returns(dto => + { + // at this point we're inside the critical section - spawn the background thread now + var backgroundGetKeyRingTask = Task.Run(() => + { + keyRingReturnedToBackgroundThread = keyRingProvider.GetCurrentKeyRingCore(updatedKeyRingTime); + }); + Assert.True(backgroundGetKeyRingTask.Wait(testTimeout), "Test timed out."); + + return new CacheableKeyRing(CancellationToken.None, StringToDateTime("2015-03-03 00:00:00Z"), updatedKeyRing); + }); + + // Assert - underlying provider only should have been called once with the updated time (by the foreground thread) + Assert.Same(originalKeyRing, keyRingProvider.GetCurrentKeyRingCore(originalKeyRingTime)); + Assert.Same(updatedKeyRing, keyRingProvider.GetCurrentKeyRingCore(updatedKeyRingTime)); + Assert.Same(originalKeyRing, keyRingReturnedToBackgroundThread); + mockCacheableKeyRingProvider.Verify(o => o.GetCacheableKeyRing(updatedKeyRingTime), Times.Once); + } + + [Fact] + public void GetCurrentKeyRing_WithExpiredExistingKeyRing_UpdateFails_ThrowsButCachesOldKeyRing() + { + // Arrange + var cts = new CancellationTokenSource(); + var mockCacheableKeyRingProvider = new Mock(); + var originalKeyRing = new Mock().Object; + var originalKeyRingTime = StringToDateTime("2015-03-01 00:00:00Z"); + mockCacheableKeyRingProvider.Setup(o => o.GetCacheableKeyRing(originalKeyRingTime)) + .Returns(new CacheableKeyRing(cts.Token, StringToDateTime("2015-03-02 00:00:00Z"), originalKeyRing)); + var throwKeyRingTime = StringToDateTime("2015-03-01 12:00:00Z"); + mockCacheableKeyRingProvider.Setup(o => o.GetCacheableKeyRing(throwKeyRingTime)).Throws(new Exception("How exceptional.")); + var updatedKeyRing = new Mock().Object; + var updatedKeyRingTime = StringToDateTime("2015-03-01 12:02:00Z"); + mockCacheableKeyRingProvider.Setup(o => o.GetCacheableKeyRing(updatedKeyRingTime)) + .Returns(new CacheableKeyRing(CancellationToken.None, StringToDateTime("2015-03-02 00:00:00Z"), updatedKeyRing)); + var keyRingProvider = CreateKeyRingProvider(mockCacheableKeyRingProvider.Object); + + // Act & assert + Assert.Same(originalKeyRing, keyRingProvider.GetCurrentKeyRingCore(originalKeyRingTime)); + cts.Cancel(); // invalidate the key ring + ExceptionAssert.Throws(() => keyRingProvider.GetCurrentKeyRingCore(throwKeyRingTime), "How exceptional."); + Assert.Same(originalKeyRing, keyRingProvider.GetCurrentKeyRingCore(throwKeyRingTime)); + Assert.Same(updatedKeyRing, keyRingProvider.GetCurrentKeyRingCore(updatedKeyRingTime)); + mockCacheableKeyRingProvider.Verify(o => o.GetCacheableKeyRing(originalKeyRingTime), Times.Once); + mockCacheableKeyRingProvider.Verify(o => o.GetCacheableKeyRing(throwKeyRingTime), Times.Once); + mockCacheableKeyRingProvider.Verify(o => o.GetCacheableKeyRing(updatedKeyRingTime), Times.Once); + } + + private static ICacheableKeyRingProvider SetupCreateCacheableKeyRingTestAndCreateKeyManager( + IList callSequence, + IEnumerable getCacheExpirationTokenReturnValues, + IEnumerable> getAllKeysReturnValues, + IEnumerable> createNewKeyCallbacks, + IEnumerable, DefaultKeyResolution>> resolveDefaultKeyPolicyReturnValues, + KeyManagementOptions keyManagementOptions = null) + { + var getCacheExpirationTokenReturnValuesEnumerator = getCacheExpirationTokenReturnValues.GetEnumerator(); + var mockKeyManager = new Mock(MockBehavior.Strict); + mockKeyManager.Setup(o => o.GetCacheExpirationToken()) + .Returns(() => + { + callSequence.Add("GetCacheExpirationToken"); + getCacheExpirationTokenReturnValuesEnumerator.MoveNext(); + return getCacheExpirationTokenReturnValuesEnumerator.Current; + }); + + var getAllKeysReturnValuesEnumerator = getAllKeysReturnValues.GetEnumerator(); + mockKeyManager.Setup(o => o.GetAllKeys()) + .Returns(() => + { + callSequence.Add("GetAllKeys"); + getAllKeysReturnValuesEnumerator.MoveNext(); + return getAllKeysReturnValuesEnumerator.Current; + }); + + if (createNewKeyCallbacks != null) + { + var createNewKeyCallbacksEnumerator = createNewKeyCallbacks.GetEnumerator(); + mockKeyManager.Setup(o => o.CreateNewKey(It.IsAny(), It.IsAny())) + .Returns((activationDate, expirationDate) => + { + callSequence.Add("CreateNewKey"); + createNewKeyCallbacksEnumerator.MoveNext(); + Assert.Equal(createNewKeyCallbacksEnumerator.Current.Item1, activationDate); + Assert.Equal(createNewKeyCallbacksEnumerator.Current.Item2, expirationDate); + return createNewKeyCallbacksEnumerator.Current.Item3; + }); + } + + var resolveDefaultKeyPolicyReturnValuesEnumerator = resolveDefaultKeyPolicyReturnValues.GetEnumerator(); + var mockDefaultKeyResolver = new Mock(MockBehavior.Strict); + mockDefaultKeyResolver.Setup(o => o.ResolveDefaultKeyPolicy(It.IsAny(), It.IsAny>())) + .Returns>((now, allKeys) => + { + callSequence.Add("ResolveDefaultKeyPolicy"); + resolveDefaultKeyPolicyReturnValuesEnumerator.MoveNext(); + Assert.Equal(resolveDefaultKeyPolicyReturnValuesEnumerator.Current.Item1, now); + Assert.Equal(resolveDefaultKeyPolicyReturnValuesEnumerator.Current.Item2, allKeys); + return resolveDefaultKeyPolicyReturnValuesEnumerator.Current.Item3; + }); + + return CreateKeyRingProvider(mockKeyManager.Object, mockDefaultKeyResolver.Object, keyManagementOptions); + } + + private static KeyRingProvider CreateKeyRingProvider(ICacheableKeyRingProvider cacheableKeyRingProvider) + { + var mockEncryptorFactory = new Mock(); + mockEncryptorFactory.Setup(m => m.CreateEncryptorInstance(It.IsAny())).Returns(new Mock().Object); + var options = new KeyManagementOptions(); + options.AuthenticatedEncryptorFactories.Add(mockEncryptorFactory.Object); + + return new KeyRingProvider( + keyManager: null, + keyManagementOptions: Options.Create(options), + defaultKeyResolver: null, + loggerFactory: NullLoggerFactory.Instance) + { + CacheableKeyRingProvider = cacheableKeyRingProvider + }; + } + + private static ICacheableKeyRingProvider CreateKeyRingProvider(IKeyManager keyManager, IDefaultKeyResolver defaultKeyResolver, KeyManagementOptions keyManagementOptions= null) + { + var mockEncryptorFactory = new Mock(); + mockEncryptorFactory.Setup(m => m.CreateEncryptorInstance(It.IsAny())).Returns(new Mock().Object); + keyManagementOptions = keyManagementOptions ?? new KeyManagementOptions(); + keyManagementOptions.AuthenticatedEncryptorFactories.Add(mockEncryptorFactory.Object); + + return new KeyRingProvider( + keyManager: keyManager, + keyManagementOptions: Options.Create(keyManagementOptions), + defaultKeyResolver: defaultKeyResolver, + loggerFactory: NullLoggerFactory.Instance); + } + + private static void AssertWithinJitterRange(DateTimeOffset actual, DateTimeOffset now) + { + // The jitter can cause the actual value to fall in the range [now + 80% of refresh period, now + 100% of refresh period) + Assert.InRange(actual, now + TimeSpan.FromHours(24 * 0.8), now + TimeSpan.FromHours(24)); + } + + private static DateTime StringToDateTime(string input) + { + return DateTimeOffset.ParseExact(input, "u", CultureInfo.InvariantCulture).UtcDateTime; + } + + private static IKey CreateKey() + { + var now = DateTimeOffset.Now; + return CreateKey( + string.Format(CultureInfo.InvariantCulture, "{0:u}", now), + string.Format(CultureInfo.InvariantCulture, "{0:u}", now.AddDays(90))); + } + + private static IKey CreateKey(string activationDate, string expirationDate, bool isRevoked = false) + { + var mockKey = new Mock(); + mockKey.Setup(o => o.KeyId).Returns(Guid.NewGuid()); + mockKey.Setup(o => o.ActivationDate).Returns(DateTimeOffset.ParseExact(activationDate, "u", CultureInfo.InvariantCulture)); + mockKey.Setup(o => o.ExpirationDate).Returns(DateTimeOffset.ParseExact(expirationDate, "u", CultureInfo.InvariantCulture)); + mockKey.Setup(o => o.IsRevoked).Returns(isRevoked); + mockKey.Setup(o => o.Descriptor).Returns(new Mock().Object); + mockKey.Setup(o => o.CreateEncryptor()).Returns(new Mock().Object); + return mockKey.Object; + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingTests.cs new file mode 100644 index 0000000000..177c7c5d63 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingTests.cs @@ -0,0 +1,126 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + public class KeyRingTests + { + [Fact] + public void DefaultAuthenticatedEncryptor_Prop_InstantiationIsDeferred() + { + // Arrange + var expectedEncryptorInstance = new Mock().Object; + + var key1 = new MyKey(expectedEncryptorInstance: expectedEncryptorInstance); + var key2 = new MyKey(); + + // Act + var keyRing = new KeyRing(key1, new[] { key1, key2 }); + + // Assert + Assert.Equal(0, key1.NumTimesCreateEncryptorInstanceCalled); + Assert.Same(expectedEncryptorInstance, keyRing.DefaultAuthenticatedEncryptor); + Assert.Equal(1, key1.NumTimesCreateEncryptorInstanceCalled); + Assert.Same(expectedEncryptorInstance, keyRing.DefaultAuthenticatedEncryptor); + Assert.Equal(1, key1.NumTimesCreateEncryptorInstanceCalled); // should've been cached + } + + [Fact] + public void DefaultKeyId_Prop() + { + // Arrange + var key1 = new MyKey(); + var key2 = new MyKey(); + + // Act + var keyRing = new KeyRing(key2, new[] { key1, key2 }); + + // Assert + Assert.Equal(key2.KeyId, keyRing.DefaultKeyId); + } + + [Fact] + public void DefaultKeyIdAndEncryptor_IfDefaultKeyNotPresentInAllKeys() + { + // Arrange + var key1 = new MyKey(); + var key2 = new MyKey(); + var key3 = new MyKey(expectedEncryptorInstance: new Mock().Object); + + // Act + var keyRing = new KeyRing(key3, new[] { key1, key2 }); + + // Assert + Assert.Equal(key3.KeyId, keyRing.DefaultKeyId); + Assert.Equal(key3.CreateEncryptor(), keyRing.GetAuthenticatedEncryptorByKeyId(key3.KeyId, out var _)); + } + + [Fact] + public void GetAuthenticatedEncryptorByKeyId_DefersInstantiation_AndReturnsRevocationInfo() + { + // Arrange + var expectedEncryptorInstance1 = new Mock().Object; + var expectedEncryptorInstance2 = new Mock().Object; + + var key1 = new MyKey(expectedEncryptorInstance: expectedEncryptorInstance1, isRevoked: true); + var key2 = new MyKey(expectedEncryptorInstance: expectedEncryptorInstance2); + + + // Act + var keyRing = new KeyRing(key2, new[] { key1, key2 }); + + // Assert + Assert.Equal(0, key1.NumTimesCreateEncryptorInstanceCalled); + Assert.Same(expectedEncryptorInstance1, keyRing.GetAuthenticatedEncryptorByKeyId(key1.KeyId, out var isRevoked)); + Assert.True(isRevoked); + Assert.Equal(1, key1.NumTimesCreateEncryptorInstanceCalled); + Assert.Same(expectedEncryptorInstance1, keyRing.GetAuthenticatedEncryptorByKeyId(key1.KeyId, out isRevoked)); + Assert.True(isRevoked); + Assert.Equal(1, key1.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(0, key2.NumTimesCreateEncryptorInstanceCalled); + Assert.Same(expectedEncryptorInstance2, keyRing.GetAuthenticatedEncryptorByKeyId(key2.KeyId, out isRevoked)); + Assert.False(isRevoked); + Assert.Equal(1, key2.NumTimesCreateEncryptorInstanceCalled); + Assert.Same(expectedEncryptorInstance2, keyRing.GetAuthenticatedEncryptorByKeyId(key2.KeyId, out isRevoked)); + Assert.False(isRevoked); + Assert.Equal(1, key2.NumTimesCreateEncryptorInstanceCalled); + Assert.Same(expectedEncryptorInstance2, keyRing.DefaultAuthenticatedEncryptor); + Assert.Equal(1, key2.NumTimesCreateEncryptorInstanceCalled); + } + + private sealed class MyKey : IKey + { + public int NumTimesCreateEncryptorInstanceCalled; + private readonly Func _encryptorFactory; + + public MyKey(bool isRevoked = false, IAuthenticatedEncryptor expectedEncryptorInstance = null) + { + CreationDate = DateTimeOffset.Now; + ActivationDate = CreationDate + TimeSpan.FromHours(1); + ExpirationDate = CreationDate + TimeSpan.FromDays(30); + IsRevoked = isRevoked; + KeyId = Guid.NewGuid(); + _encryptorFactory = () => expectedEncryptorInstance ?? new Mock().Object; + } + + public DateTimeOffset ActivationDate { get; } + public DateTimeOffset CreationDate { get; } + public DateTimeOffset ExpirationDate { get; } + public bool IsRevoked { get; } + public Guid KeyId { get; } + public IAuthenticatedEncryptorDescriptor Descriptor => throw new NotImplementedException(); + + public IAuthenticatedEncryptor CreateEncryptor() + { + NumTimesCreateEncryptorInstanceCalled++; + return _encryptorFactory(); + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyTests.cs new file mode 100644 index 0000000000..6aa691723d --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyTests.cs @@ -0,0 +1,50 @@ +// 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 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Moq; +using Xunit; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + public class KeyTests + { + [Fact] + public void Ctor_Properties() + { + // Arrange + var keyId = Guid.NewGuid(); + var creationDate = DateTimeOffset.Now; + var activationDate = creationDate.AddDays(2); + var expirationDate = creationDate.AddDays(90); + var descriptor = Mock.Of(); + var encryptorFactory = Mock.Of(); + + // Act + var key = new Key(keyId, creationDate, activationDate, expirationDate, descriptor, new[] { encryptorFactory }); + + // Assert + Assert.Equal(keyId, key.KeyId); + Assert.Equal(creationDate, key.CreationDate); + Assert.Equal(activationDate, key.ActivationDate); + Assert.Equal(expirationDate, key.ExpirationDate); + Assert.Same(descriptor, key.Descriptor); + } + + [Fact] + public void SetRevoked_Respected() + { + // Arrange + var now = DateTimeOffset.UtcNow; + var encryptorFactory = Mock.Of(); + var key = new Key(Guid.Empty, now, now, now, new Mock().Object, new[] { encryptorFactory }); + + // Act & assert + Assert.False(key.IsRevoked); + key.SetRevoked(); + Assert.True(key.IsRevoked); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/XmlKeyManagerTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/XmlKeyManagerTests.cs new file mode 100644 index 0000000000..c6a2e068a3 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/XmlKeyManagerTests.cs @@ -0,0 +1,770 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Xml; +using System.Xml.Linq; +using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; +using Microsoft.AspNetCore.DataProtection.Repositories; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement +{ + public class XmlKeyManagerTests + { + private static readonly XElement serializedDescriptor = XElement.Parse(@" + + + + + "); + + [Fact] + public void Ctor_WithoutEncryptorOrRepository_UsesFallback() + { + // Arrange + var options = Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = new Mock().Object, + XmlRepository = null, + XmlEncryptor = null + }); + + // Act + var keyManager = new XmlKeyManager(options, SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance); + + // Assert + Assert.NotNull(keyManager.KeyRepository); + + if (OSVersionUtil.IsWindows()) + { + Assert.NotNull(keyManager.KeyEncryptor); + } + } + + [Fact] + public void Ctor_WithEncryptorButNoRepository_IgnoresFallback_FailsWithServiceNotFound() + { + // Arrange + var options = Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = new Mock().Object, + XmlRepository = null, + XmlEncryptor = new Mock().Object + }); + + // Act & assert - we don't care about exception type, only exception message + Exception ex = Assert.ThrowsAny( + () => new XmlKeyManager(options, SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance)); + Assert.Contains("IXmlRepository", ex.Message); + } + + [Fact] + public void CreateNewKey_Internal_NoEscrowOrEncryption() + { + // Constants + var creationDate = new DateTimeOffset(2014, 01, 01, 0, 0, 0, TimeSpan.Zero); + var activationDate = new DateTimeOffset(2014, 02, 01, 0, 0, 0, TimeSpan.Zero); + var expirationDate = new DateTimeOffset(2014, 03, 01, 0, 0, 0, TimeSpan.Zero); + var keyId = new Guid("3d6d01fd-c0e7-44ae-82dd-013b996b4093"); + + // Arrange + XElement elementStoredInRepository = null; + string friendlyNameStoredInRepository = null; + var expectedAuthenticatedEncryptor = new Mock().Object; + var mockDescriptor = new Mock(); + mockDescriptor.Setup(o => o.ExportToXml()).Returns(new XmlSerializedDescriptorInfo(serializedDescriptor, typeof(MyDeserializer))); + var expectedDescriptor = mockDescriptor.Object; + var testEncryptorFactory = new TestEncryptorFactory(expectedDescriptor, expectedAuthenticatedEncryptor); + var mockConfiguration = new Mock(); + mockConfiguration.Setup(o => o.CreateNewDescriptor()).Returns(expectedDescriptor); + var mockXmlRepository = new Mock(); + mockXmlRepository + .Setup(o => o.StoreElement(It.IsAny(), It.IsAny())) + .Callback((el, friendlyName) => + { + elementStoredInRepository = el; + friendlyNameStoredInRepository = friendlyName; + }); + var options = Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = mockConfiguration.Object, + XmlRepository = mockXmlRepository.Object, + XmlEncryptor = null + }); + options.Value.AuthenticatedEncryptorFactories.Add(testEncryptorFactory); + + var keyManager = new XmlKeyManager(options, SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance); + + // Act & assert + + // The cancellation token should not already be fired + var firstCancellationToken = keyManager.GetCacheExpirationToken(); + Assert.False(firstCancellationToken.IsCancellationRequested); + + // After the call to CreateNewKey, the first CT should be fired, + // and we should've gotten a new CT. + var newKey = ((IInternalXmlKeyManager)keyManager).CreateNewKey( + keyId: keyId, + creationDate: creationDate, + activationDate: activationDate, + expirationDate: expirationDate); + var secondCancellationToken = keyManager.GetCacheExpirationToken(); + Assert.True(firstCancellationToken.IsCancellationRequested); + Assert.False(secondCancellationToken.IsCancellationRequested); + + // Does the IKey have the properties we requested? + Assert.Equal(keyId, newKey.KeyId); + Assert.Equal(creationDate, newKey.CreationDate); + Assert.Equal(activationDate, newKey.ActivationDate); + Assert.Equal(expirationDate, newKey.ExpirationDate); + Assert.Same(expectedDescriptor, newKey.Descriptor); + Assert.False(newKey.IsRevoked); + Assert.Same(expectedAuthenticatedEncryptor, testEncryptorFactory.CreateEncryptorInstance(newKey)); + + // Finally, was the correct element stored in the repository? + string expectedXml = string.Format(@" + + {1} + {2} + {3} + + + + + + + + ", + typeof(MyDeserializer).AssemblyQualifiedName, + new XElement("creationDate", creationDate), + new XElement("activationDate", activationDate), + new XElement("expirationDate", expirationDate)); + XmlAssert.Equal(expectedXml, elementStoredInRepository); + Assert.Equal("key-3d6d01fd-c0e7-44ae-82dd-013b996b4093", friendlyNameStoredInRepository); + } + + [Fact] + public void CreateNewKey_Internal_WithEscrowAndEncryption() + { + // Constants + var creationDate = new DateTimeOffset(2014, 01, 01, 0, 0, 0, TimeSpan.Zero); + var activationDate = new DateTimeOffset(2014, 02, 01, 0, 0, 0, TimeSpan.Zero); + var expirationDate = new DateTimeOffset(2014, 03, 01, 0, 0, 0, TimeSpan.Zero); + var keyId = new Guid("3d6d01fd-c0e7-44ae-82dd-013b996b4093"); + + // Arrange + XElement elementStoredInEscrow = null; + Guid? keyIdStoredInEscrow = null; + XElement elementStoredInRepository = null; + string friendlyNameStoredInRepository = null; + var expectedAuthenticatedEncryptor = new Mock().Object; + var mockDescriptor = new Mock(); + mockDescriptor.Setup(o => o.ExportToXml()).Returns(new XmlSerializedDescriptorInfo(serializedDescriptor, typeof(MyDeserializer))); + var expectedDescriptor = mockDescriptor.Object; + var testEncryptorFactory = new TestEncryptorFactory(expectedDescriptor, expectedAuthenticatedEncryptor); + var mockConfiguration = new Mock(); + mockConfiguration.Setup(o => o.CreateNewDescriptor()).Returns(expectedDescriptor); + var mockXmlRepository = new Mock(); + mockXmlRepository + .Setup(o => o.StoreElement(It.IsAny(), It.IsAny())) + .Callback((el, friendlyName) => + { + elementStoredInRepository = el; + friendlyNameStoredInRepository = friendlyName; + }); + var mockKeyEscrow = new Mock(); + mockKeyEscrow + .Setup(o => o.Store(It.IsAny(), It.IsAny())) + .Callback((innerKeyId, el) => + { + keyIdStoredInEscrow = innerKeyId; + elementStoredInEscrow = el; + }); + + var options = Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = mockConfiguration.Object, + XmlRepository = mockXmlRepository.Object, + XmlEncryptor = new NullXmlEncryptor() + }); + options.Value.AuthenticatedEncryptorFactories.Add(testEncryptorFactory); + options.Value.KeyEscrowSinks.Add(mockKeyEscrow.Object); + var keyManager = new XmlKeyManager(options, SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance); + + // Act & assert + + // The cancellation token should not already be fired + var firstCancellationToken = keyManager.GetCacheExpirationToken(); + Assert.False(firstCancellationToken.IsCancellationRequested); + + // After the call to CreateNewKey, the first CT should be fired, + // and we should've gotten a new CT. + var newKey = ((IInternalXmlKeyManager)keyManager).CreateNewKey( + keyId: keyId, + creationDate: creationDate, + activationDate: activationDate, + expirationDate: expirationDate); + var secondCancellationToken = keyManager.GetCacheExpirationToken(); + Assert.True(firstCancellationToken.IsCancellationRequested); + Assert.False(secondCancellationToken.IsCancellationRequested); + + // Does the IKey have the properties we requested? + Assert.Equal(keyId, newKey.KeyId); + Assert.Equal(creationDate, newKey.CreationDate); + Assert.Equal(activationDate, newKey.ActivationDate); + Assert.Equal(expirationDate, newKey.ExpirationDate); + Assert.Same(expectedDescriptor, newKey.Descriptor); + Assert.False(newKey.IsRevoked); + Assert.Same(expectedAuthenticatedEncryptor, testEncryptorFactory.CreateEncryptorInstance(newKey)); + + // Was the correct element stored in escrow? + // This should not have gone through the encryptor. + string expectedEscrowXml = string.Format(@" + + {1} + {2} + {3} + + + + + + + + ", + typeof(MyDeserializer).AssemblyQualifiedName, + new XElement("creationDate", creationDate), + new XElement("activationDate", activationDate), + new XElement("expirationDate", expirationDate)); + XmlAssert.Equal(expectedEscrowXml, elementStoredInEscrow); + Assert.Equal(keyId, keyIdStoredInEscrow.Value); + + // Finally, was the correct element stored in the repository? + // This should have gone through the encryptor (which we set to be the null encryptor in this test) + string expectedRepositoryXml = String.Format(@" + + {2} + {3} + {4} + + + + + + + + + + + + ", + typeof(MyDeserializer).AssemblyQualifiedName, + typeof(NullXmlDecryptor).AssemblyQualifiedName, + new XElement("creationDate", creationDate), + new XElement("activationDate", activationDate), + new XElement("expirationDate", expirationDate)); + XmlAssert.Equal(expectedRepositoryXml, elementStoredInRepository); + Assert.Equal("key-3d6d01fd-c0e7-44ae-82dd-013b996b4093", friendlyNameStoredInRepository); + } + + [Fact] + public void CreateNewKey_CallsInternalManager() + { + // Arrange + DateTimeOffset minCreationDate = DateTimeOffset.UtcNow; + DateTimeOffset? actualCreationDate = null; + DateTimeOffset activationDate = minCreationDate + TimeSpan.FromDays(7); + DateTimeOffset expirationDate = activationDate.AddMonths(1); + var mockInternalKeyManager = new Mock(); + mockInternalKeyManager + .Setup(o => o.CreateNewKey(It.IsAny(), It.IsAny(), activationDate, expirationDate)) + .Callback((innerKeyId, innerCreationDate, innerActivationDate, innerExpirationDate) => + { + actualCreationDate = innerCreationDate; + }); + + var options = Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = new Mock().Object, + XmlRepository = new Mock().Object, + XmlEncryptor = null + }); + var keyManager = new XmlKeyManager(options, SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance, mockInternalKeyManager.Object); + + // Act + keyManager.CreateNewKey(activationDate, expirationDate); + + // Assert + Assert.InRange(actualCreationDate.Value, minCreationDate, DateTimeOffset.UtcNow); + } + + [Fact] + public void GetAllKeys_Empty() + { + // Arrange + const string xml = @""; + var activator = new Mock().Object; + + // Act + var keys = RunGetAllKeysCore(xml, activator); + + // Assert + Assert.Equal(0, keys.Count); + } + + [Fact] + public void GetAllKeys_IgnoresUnknownElements() + { + // Arrange + const string xml = @" + + + 2015-01-01T00:00:00Z + 2015-02-01T00:00:00Z + 2015-03-01T00:00:00Z + + + + + + + + + 2015-04-01T00:00:00Z + 2015-05-01T00:00:00Z + 2015-06-01T00:00:00Z + + + + + "; + + var descriptorA = new Mock().Object; + var descriptorB = new Mock().Object; + var mockActivator = new Mock(); + mockActivator.ReturnDescriptorGivenDeserializerTypeNameAndInput("deserializer-A", "", descriptorA); + mockActivator.ReturnDescriptorGivenDeserializerTypeNameAndInput("deserializer-B", "", descriptorB); + + // Act + var keys = RunGetAllKeysCore(xml, mockActivator.Object).ToArray(); + + // Assert + Assert.Equal(2, keys.Length); + Assert.Equal(new Guid("62a72ad9-42d7-4e97-b3fa-05bad5d53d33"), keys[0].KeyId); + Assert.Equal(XmlConvert.ToDateTimeOffset("2015-01-01T00:00:00Z"), keys[0].CreationDate); + Assert.Equal(XmlConvert.ToDateTimeOffset("2015-02-01T00:00:00Z"), keys[0].ActivationDate); + Assert.Equal(XmlConvert.ToDateTimeOffset("2015-03-01T00:00:00Z"), keys[0].ExpirationDate); + Assert.False(keys[0].IsRevoked); + Assert.Same(descriptorA, keys[0].Descriptor); + Assert.Equal(new Guid("041be4c0-52d7-48b4-8d32-f8c0ff315459"), keys[1].KeyId); + Assert.Equal(XmlConvert.ToDateTimeOffset("2015-04-01T00:00:00Z"), keys[1].CreationDate); + Assert.Equal(XmlConvert.ToDateTimeOffset("2015-05-01T00:00:00Z"), keys[1].ActivationDate); + Assert.Equal(XmlConvert.ToDateTimeOffset("2015-06-01T00:00:00Z"), keys[1].ExpirationDate); + Assert.False(keys[1].IsRevoked); + Assert.Same(descriptorB, keys[1].Descriptor); + } + + [Fact] + public void GetAllKeys_UnderstandsRevocations() + { + // Arrange + const string xml = @" + + + 2015-01-01T00:00:00Z + 2015-02-01T00:00:00Z + 2015-03-01T00:00:00Z + + + + + + 2016-01-01T00:00:00Z + 2016-02-01T00:00:00Z + 2016-03-01T00:00:00Z + + + + + + 2017-01-01T00:00:00Z + 2017-02-01T00:00:00Z + 2017-03-01T00:00:00Z + + + + + + 2018-01-01T00:00:00Z + 2018-02-01T00:00:00Z + 2018-03-01T00:00:00Z + + + + + + + 2014-01-01T00:00:00Z + + + + + 2017-01-01T00:00:00Z + + + + + 2020-01-01T00:00:00Z + + + "; + + var mockActivator = new Mock(); + mockActivator.ReturnDescriptorGivenDeserializerTypeNameAndInput("theDeserializer", "", new Mock().Object); + + // Act + var keys = RunGetAllKeysCore(xml, mockActivator.Object).ToArray(); + + // Assert + Assert.Equal(4, keys.Length); + Assert.Equal(new Guid("67f9cdea-83ba-41ed-b160-2b1d0ea30251"), keys[0].KeyId); + Assert.True(keys[0].IsRevoked); + Assert.Equal(new Guid("0cf83742-d175-42a8-94b5-1ec049b354c3"), keys[1].KeyId); + Assert.True(keys[1].IsRevoked); + Assert.Equal(new Guid("21580ac4-c83a-493c-bde6-29a1cc97ca0f"), keys[2].KeyId); + Assert.False(keys[2].IsRevoked); + Assert.Equal(new Guid("6bd14f12-0bb8-4822-91d7-04b360de0497"), keys[3].KeyId); + Assert.True(keys[3].IsRevoked); + } + + [Fact] + public void GetAllKeys_PerformsDecryption() + { + // Arrange + const string xml = @" + + + 2015-01-01T00:00:00Z + 2015-02-01T00:00:00Z + 2015-03-01T00:00:00Z + + + + + + + "; + + var expectedDescriptor = new Mock().Object; + var mockActivator = new Mock(); + mockActivator.ReturnDecryptedElementGivenDecryptorTypeNameAndInput("theDecryptor", "", ""); + mockActivator.ReturnDescriptorGivenDeserializerTypeNameAndInput("theDeserializer", "", expectedDescriptor); + + // Act + var keys = RunGetAllKeysCore(xml, mockActivator.Object).ToArray(); + + // Assert + Assert.Single(keys); + Assert.Equal(new Guid("09712588-ba68-438a-a5ee-fe842b3453b2"), keys[0].KeyId); + Assert.Same(expectedDescriptor, keys[0].Descriptor); + } + + [Fact] + public void GetAllKeys_SwallowsKeyDeserializationErrors() + { + // Arrange + const string xml = @" + + + + 2015-01-01T00:00:00Z + 2015-02-01T00:00:00Z + NOT A VALID DATE + + + + + + + 2015-01-01T00:00:00Z + 2015-02-01T00:00:00Z + 2015-03-01T00:00:00Z + + + + + "; + + var expectedDescriptor = new Mock().Object; + var mockActivator = new Mock(); + mockActivator.ReturnDescriptorGivenDeserializerTypeNameAndInput("goodDeserializer", "", expectedDescriptor); + + // Act + var keys = RunGetAllKeysCore(xml, mockActivator.Object).ToArray(); + + // Assert + Assert.Single(keys); + Assert.Equal(new Guid("49c0cda9-0232-4d8c-a541-de20cc5a73d6"), keys[0].KeyId); + Assert.Same(expectedDescriptor, keys[0].Descriptor); + } + + [Fact] + public void GetAllKeys_WithKeyDeserializationError_LogLevelDebug_DoesNotWriteSensitiveInformation() + { + // Arrange + const string xml = @" + + + + 2015-01-01T00:00:00Z + 2015-02-01T00:00:00Z + NOT A VALID DATE + + + "; + + var loggerFactory = new StringLoggerFactory(LogLevel.Debug); + + // Act + RunGetAllKeysCore(xml, new Mock().Object, loggerFactory).ToArray(); + + // Assert + Assert.False(loggerFactory.ToString().Contains("1A2B3C4D"), "The secret '1A2B3C4D' should not have been logged."); + } + + [Fact] + public void GetAllKeys_WithKeyDeserializationError_LogLevelTrace_WritesSensitiveInformation() + { + // Arrange + const string xml = @" + + + + 2015-01-01T00:00:00Z + 2015-02-01T00:00:00Z + NOT A VALID DATE + + + "; + + var loggerFactory = new StringLoggerFactory(LogLevel.Trace); + + // Act + RunGetAllKeysCore(xml, new Mock().Object, loggerFactory).ToArray(); + + // Assert + Assert.True(loggerFactory.ToString().Contains("1A2B3C4D"), "The secret '1A2B3C4D' should have been logged."); + } + + [Fact] + public void GetAllKeys_SurfacesRevocationDeserializationErrors() + { + // Arrange + const string xml = @" + + + 2015-01-01T00:00:00Z + + + "; + + // Act & assert + // Bad GUID will lead to FormatException + Assert.Throws(() => RunGetAllKeysCore(xml, new Mock().Object)); + } + + private static IReadOnlyCollection RunGetAllKeysCore(string xml, IActivator activator, ILoggerFactory loggerFactory = null) + { + // Arrange + var mockXmlRepository = new Mock(); + mockXmlRepository.Setup(o => o.GetAllElements()).Returns(XElement.Parse(xml).Elements().ToArray()); + var options = Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = new Mock().Object, + XmlRepository = mockXmlRepository.Object, + XmlEncryptor = null + }); + var keyManager = new XmlKeyManager(options, activator, loggerFactory ?? NullLoggerFactory.Instance); + + // Act + return keyManager.GetAllKeys(); + } + + [Fact] + public void RevokeAllKeys() + { + // Arrange + XElement elementStoredInRepository = null; + string friendlyNameStoredInRepository = null; + var mockXmlRepository = new Mock(); + mockXmlRepository + .Setup(o => o.StoreElement(It.IsAny(), It.IsAny())) + .Callback((el, friendlyName) => + { + elementStoredInRepository = el; + friendlyNameStoredInRepository = friendlyName; + }); + + var options = Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = new Mock().Object, + XmlRepository = mockXmlRepository.Object, + XmlEncryptor = null + }); + var keyManager = new XmlKeyManager(options, SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance); + + var revocationDate = XmlConvert.ToDateTimeOffset("2015-03-01T19:13:19.7573854-08:00"); + + // Act & assert + + // The cancellation token should not already be fired + var firstCancellationToken = keyManager.GetCacheExpirationToken(); + Assert.False(firstCancellationToken.IsCancellationRequested); + + // After the call to RevokeAllKeys, the first CT should be fired, + // and we should've gotten a new CT. + keyManager.RevokeAllKeys(revocationDate, "Here's some reason text."); + var secondCancellationToken = keyManager.GetCacheExpirationToken(); + Assert.True(firstCancellationToken.IsCancellationRequested); + Assert.False(secondCancellationToken.IsCancellationRequested); + + // Was the correct element stored in the repository? + const string expectedRepositoryXml = @" + + 2015-03-01T19:13:19.7573854-08:00 + + + Here's some reason text. + "; + XmlAssert.Equal(expectedRepositoryXml, elementStoredInRepository); + Assert.Equal("revocation-20150302T0313197573854Z", friendlyNameStoredInRepository); + } + + [Fact] + public void RevokeSingleKey_Internal() + { + // Arrange - mocks + XElement elementStoredInRepository = null; + string friendlyNameStoredInRepository = null; + var mockXmlRepository = new Mock(); + mockXmlRepository + .Setup(o => o.StoreElement(It.IsAny(), It.IsAny())) + .Callback((el, friendlyName) => + { + elementStoredInRepository = el; + friendlyNameStoredInRepository = friendlyName; + }); + + var options = Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = new Mock().Object, + XmlRepository = mockXmlRepository.Object, + XmlEncryptor = null + }); + var keyManager = new XmlKeyManager(options, SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance); + + var revocationDate = new DateTimeOffset(2014, 01, 01, 0, 0, 0, TimeSpan.Zero); + + // Act & assert + + // The cancellation token should not already be fired + var firstCancellationToken = keyManager.GetCacheExpirationToken(); + Assert.False(firstCancellationToken.IsCancellationRequested); + + // After the call to RevokeKey, the first CT should be fired, + // and we should've gotten a new CT. + ((IInternalXmlKeyManager)keyManager).RevokeSingleKey( + keyId: new Guid("a11f35fc-1fed-4bd4-b727-056a63b70932"), + revocationDate: revocationDate, + reason: "Here's some reason text."); + var secondCancellationToken = keyManager.GetCacheExpirationToken(); + Assert.True(firstCancellationToken.IsCancellationRequested); + Assert.False(secondCancellationToken.IsCancellationRequested); + + // Was the correct element stored in the repository? + var expectedRepositoryXml = string.Format(@" + + {0} + + Here's some reason text. + ", + new XElement("revocationDate", revocationDate)); + XmlAssert.Equal(expectedRepositoryXml, elementStoredInRepository); + Assert.Equal("revocation-a11f35fc-1fed-4bd4-b727-056a63b70932", friendlyNameStoredInRepository); + } + + [Fact] + public void RevokeKey_CallsInternalManager() + { + // Arrange + var keyToRevoke = new Guid("a11f35fc-1fed-4bd4-b727-056a63b70932"); + DateTimeOffset minRevocationDate = DateTimeOffset.UtcNow; + DateTimeOffset? actualRevocationDate = null; + var mockInternalKeyManager = new Mock(); + mockInternalKeyManager + .Setup(o => o.RevokeSingleKey(keyToRevoke, It.IsAny(), "Here's some reason text.")) + .Callback((innerKeyId, innerRevocationDate, innerReason) => + { + actualRevocationDate = innerRevocationDate; + }); + + var options = Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = new Mock().Object, + XmlRepository = new Mock().Object, + XmlEncryptor = null + }); + var keyManager = new XmlKeyManager(options, SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance, mockInternalKeyManager.Object); + + // Act + keyManager.RevokeKey(keyToRevoke, "Here's some reason text."); + + // Assert + Assert.InRange(actualRevocationDate.Value, minRevocationDate, DateTimeOffset.UtcNow); + } + + private class MyDeserializer : IAuthenticatedEncryptorDescriptorDeserializer + { + public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) + { + throw new NotImplementedException(); + } + } + + private class TestEncryptorFactory : IAuthenticatedEncryptorFactory + { + private IAuthenticatedEncryptorDescriptor _associatedDescriptor; + private IAuthenticatedEncryptor _expectedEncryptor; + + public TestEncryptorFactory(IAuthenticatedEncryptorDescriptor associatedDescriptor = null, IAuthenticatedEncryptor expectedEncryptor = null) + { + _associatedDescriptor = associatedDescriptor; + _expectedEncryptor = expectedEncryptor; + } + + public IAuthenticatedEncryptor CreateEncryptorInstance(IKey key) + { + if (_associatedDescriptor != null && _associatedDescriptor != key.Descriptor) + { + return null; + } + + return _expectedEncryptor ?? new Mock().Object; + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Managed/ManagedAuthenticatedEncryptorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Managed/ManagedAuthenticatedEncryptorTests.cs new file mode 100644 index 0000000000..d279f73cf6 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Managed/ManagedAuthenticatedEncryptorTests.cs @@ -0,0 +1,112 @@ +// 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 System.Security.Cryptography; +using System.Text; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Managed +{ + public class ManagedAuthenticatedEncryptorTests + { + [Fact] + public void Encrypt_Decrypt_RoundTrips() + { + // Arrange + Secret kdk = new Secret(new byte[512 / 8]); + ManagedAuthenticatedEncryptor encryptor = new ManagedAuthenticatedEncryptor(kdk, + symmetricAlgorithmFactory: Aes.Create, + symmetricAlgorithmKeySizeInBytes: 256 / 8, + validationAlgorithmFactory: () => new HMACSHA256()); + ArraySegment plaintext = new ArraySegment(Encoding.UTF8.GetBytes("plaintext")); + ArraySegment aad = new ArraySegment(Encoding.UTF8.GetBytes("aad")); + + // Act + byte[] ciphertext = encryptor.Encrypt(plaintext, aad); + byte[] decipheredtext = encryptor.Decrypt(new ArraySegment(ciphertext), aad); + + // Assert + Assert.Equal(plaintext, decipheredtext); + } + + [Fact] + public void Encrypt_Decrypt_Tampering_Fails() + { + // Arrange + Secret kdk = new Secret(new byte[512 / 8]); + ManagedAuthenticatedEncryptor encryptor = new ManagedAuthenticatedEncryptor(kdk, + symmetricAlgorithmFactory: Aes.Create, + symmetricAlgorithmKeySizeInBytes: 256 / 8, + validationAlgorithmFactory: () => new HMACSHA256()); + ArraySegment plaintext = new ArraySegment(Encoding.UTF8.GetBytes("plaintext")); + ArraySegment aad = new ArraySegment(Encoding.UTF8.GetBytes("aad")); + byte[] validCiphertext = encryptor.Encrypt(plaintext, aad); + + // Act & assert - 1 + // Ciphertext is too short to be a valid payload + byte[] invalidCiphertext_tooShort = new byte[10]; + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(invalidCiphertext_tooShort), aad); + }); + + // Act & assert - 2 + // Ciphertext has been manipulated + byte[] invalidCiphertext_manipulated = (byte[])validCiphertext.Clone(); + invalidCiphertext_manipulated[0] ^= 0x01; + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(invalidCiphertext_manipulated), aad); + }); + + // Act & assert - 3 + // Ciphertext is too long + byte[] invalidCiphertext_tooLong = validCiphertext.Concat(new byte[] { 0 }).ToArray(); + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(invalidCiphertext_tooLong), aad); + }); + + // Act & assert - 4 + // AAD is incorrect + Assert.Throws(() => + { + encryptor.Decrypt(new ArraySegment(validCiphertext), new ArraySegment(Encoding.UTF8.GetBytes("different aad"))); + }); + } + + [Fact] + public void Encrypt_KnownKey() + { + // Arrange + Secret kdk = new Secret(Encoding.UTF8.GetBytes("master key")); + ManagedAuthenticatedEncryptor encryptor = new ManagedAuthenticatedEncryptor(kdk, + symmetricAlgorithmFactory: Aes.Create, + symmetricAlgorithmKeySizeInBytes: 256 / 8, + validationAlgorithmFactory: () => new HMACSHA256(), + genRandom: new SequentialGenRandom()); + ArraySegment plaintext = new ArraySegment(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }, 2, 3); + ArraySegment aad = new ArraySegment(new byte[] { 7, 6, 5, 4, 3, 2, 1, 0 }, 1, 4); + + // Act + byte[] retVal = encryptor.Encrypt( + plaintext: plaintext, + additionalAuthenticatedData: aad); + + // Assert + + // retVal := 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F (keyModifier) + // | 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F (IV) + // | B7 EA 3E 32 58 93 A3 06 03 89 C6 66 03 63 08 4B (encryptedData) + // | 9D 8A 85 C7 0F BD 98 D8 7F 72 E7 72 3E B5 A6 26 (HMAC) + // | 6C 38 77 F7 66 19 A2 C9 2C BB AD DA E7 62 00 00 + + string retValAsString = Convert.ToBase64String(retVal); + Assert.Equal("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh+36j4yWJOjBgOJxmYDYwhLnYqFxw+9mNh/cudyPrWmJmw4d/dmGaLJLLut2udiAAA=", retValAsString); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Microsoft.AspNetCore.DataProtection.Test.csproj b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Microsoft.AspNetCore.DataProtection.Test.csproj new file mode 100644 index 0000000000..bf45498fbf --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Microsoft.AspNetCore.DataProtection.Test.csproj @@ -0,0 +1,22 @@ + + + + $(StandardTestTfms) + true + + + + + + + + + + + + + + + + + diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/MockExtensions.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/MockExtensions.cs new file mode 100644 index 0000000000..76f5dc94e6 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/MockExtensions.cs @@ -0,0 +1,62 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Moq; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal static class MockExtensions + { + /// + /// Sets up a mock such that given the name of a deserializer class and the XML node that class's + /// Import method should expect returns a descriptor which produces the given authenticator. + /// + public static void ReturnDescriptorGivenDeserializerTypeNameAndInput(this Mock mockActivator, string typeName, string xml, IAuthenticatedEncryptorDescriptor descriptor) + { + mockActivator + .Setup(o => o.CreateInstance(typeof(IAuthenticatedEncryptorDescriptorDeserializer), typeName)) + .Returns(() => + { + var mockDeserializer = new Mock(); + mockDeserializer + .Setup(o => o.ImportFromXml(It.IsAny())) + .Returns(el => + { + // Only return the descriptor if the XML matches + XmlAssert.Equal(xml, el); + return descriptor; + }); + return mockDeserializer.Object; + }); + } + + /// + /// Sets up a mock such that given the name of a decryptor class and the XML node that class's + /// Decrypt method should expect returns the specified XML elmeent. + /// + public static void ReturnDecryptedElementGivenDecryptorTypeNameAndInput(this Mock mockActivator, string typeName, string expectedInputXml, string outputXml) + { + mockActivator + .Setup(o => o.CreateInstance(typeof(IXmlDecryptor), typeName)) + .Returns(() => + { + var mockDecryptor = new Mock(); + mockDecryptor + .Setup(o => o.Decrypt(It.IsAny())) + .Returns(el => + { + // Only return the descriptor if the XML matches + XmlAssert.Equal(expectedInputXml, el); + return XElement.Parse(outputXml); + }); + return mockDecryptor.Object; + }); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Properties/AssemblyInfo.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..3adbc7af4e --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// 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.Runtime.CompilerServices; + +// for unit testing +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/RegistryPolicyResolverTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/RegistryPolicyResolverTests.cs new file mode 100644 index 0000000000..d10fd872cd --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/RegistryPolicyResolverTests.cs @@ -0,0 +1,314 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Microsoft.Win32; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class RegistryPolicyResolverTests + { + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void ResolvePolicy_NoEntries_ResultsInNoPolicies() + { + // Arrange + var registryEntries = new Dictionary(); + + // Act + var context = RunTestWithRegValues(registryEntries); + + // Assert + Assert.Null(context.EncryptorConfiguration); + Assert.Null(context.DefaultKeyLifetime); + Assert.Empty(context.KeyEscrowSinks); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void ResolvePolicy_KeyEscrowSinks() + { + // Arrange + var registryEntries = new Dictionary() + { + ["KeyEscrowSinks"] = String.Join(" ;; ; ", new Type[] { typeof(MyKeyEscrowSink1), typeof(MyKeyEscrowSink2) }.Select(t => t.AssemblyQualifiedName)) + }; + + // Act + var context = RunTestWithRegValues(registryEntries); + + // Assert + var actualKeyEscrowSinks = context.KeyEscrowSinks.ToArray(); + Assert.Equal(2, actualKeyEscrowSinks.Length); + Assert.IsType(actualKeyEscrowSinks[0]); + Assert.IsType(actualKeyEscrowSinks[1]); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void ResolvePolicy_DefaultKeyLifetime() + { + // Arrange + var registryEntries = new Dictionary() + { + ["DefaultKeyLifetime"] = 1024 // days + }; + + // Act + var context = RunTestWithRegValues(registryEntries); + + // Assert + Assert.Equal(1024, context.DefaultKeyLifetime); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void ResolvePolicy_CngCbcEncryption_WithoutExplicitSettings() + { + // Arrange + var registryEntries = new Dictionary() + { + ["EncryptionType"] = "cng-cbc" + }; + var expectedConfiguration = new CngCbcAuthenticatedEncryptorConfiguration(); + + // Act + var context = RunTestWithRegValues(registryEntries); + + // Assert + var actualConfiguration = (CngCbcAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration; + + Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider); + Assert.Equal(expectedConfiguration.HashAlgorithm, actualConfiguration.HashAlgorithm); + Assert.Equal(expectedConfiguration.HashAlgorithmProvider, actualConfiguration.HashAlgorithmProvider); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void ResolvePolicy_CngCbcEncryption_WithExplicitSettings() + { + // Arrange + var registryEntries = new Dictionary() + { + ["EncryptionType"] = "cng-cbc", + ["EncryptionAlgorithm"] = "enc-alg", + ["EncryptionAlgorithmKeySize"] = 2048, + ["EncryptionAlgorithmProvider"] = "my-enc-alg-provider", + ["HashAlgorithm"] = "hash-alg", + ["HashAlgorithmProvider"] = "my-hash-alg-provider" + }; + var expectedConfiguration = new CngCbcAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = "enc-alg", + EncryptionAlgorithmKeySize = 2048, + EncryptionAlgorithmProvider = "my-enc-alg-provider", + HashAlgorithm = "hash-alg", + HashAlgorithmProvider = "my-hash-alg-provider" + }; + + // Act + var context = RunTestWithRegValues(registryEntries); + + // Assert + var actualConfiguration = (CngCbcAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration; + + Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider); + Assert.Equal(expectedConfiguration.HashAlgorithm, actualConfiguration.HashAlgorithm); + Assert.Equal(expectedConfiguration.HashAlgorithmProvider, actualConfiguration.HashAlgorithmProvider); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void ResolvePolicy_CngGcmEncryption_WithoutExplicitSettings() + { + // Arrange + var registryEntries = new Dictionary() + { + ["EncryptionType"] = "cng-gcm" + }; + var expectedConfiguration = new CngGcmAuthenticatedEncryptorConfiguration(); + + // Act + var context = RunTestWithRegValues(registryEntries); + + // Assert + var actualConfiguration = (CngGcmAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration; + + Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void ResolvePolicy_CngGcmEncryption_WithExplicitSettings() + { + // Arrange + var registryEntries = new Dictionary() + { + ["EncryptionType"] = "cng-gcm", + ["EncryptionAlgorithm"] = "enc-alg", + ["EncryptionAlgorithmKeySize"] = 2048, + ["EncryptionAlgorithmProvider"] = "my-enc-alg-provider" + }; + var expectedConfiguration = new CngGcmAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithm = "enc-alg", + EncryptionAlgorithmKeySize = 2048, + EncryptionAlgorithmProvider = "my-enc-alg-provider" + }; + + // Act + var context = RunTestWithRegValues(registryEntries); + + // Assert + var actualConfiguration = (CngGcmAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration; + + Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void ResolvePolicy_ManagedEncryption_WithoutExplicitSettings() + { + // Arrange + var registryEntries = new Dictionary() + { + ["EncryptionType"] = "managed" + }; + var expectedConfiguration = new ManagedAuthenticatedEncryptorConfiguration(); + + // Act + var context = RunTestWithRegValues(registryEntries); + + // Assert + var actualConfiguration = (ManagedAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration; + + Assert.Equal(expectedConfiguration.EncryptionAlgorithmType, actualConfiguration.EncryptionAlgorithmType); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize); + Assert.Equal(expectedConfiguration.ValidationAlgorithmType, actualConfiguration.ValidationAlgorithmType); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void ResolvePolicy_ManagedEncryption_WithExplicitSettings() + { + // Arrange + var registryEntries = new Dictionary() + { + ["EncryptionType"] = "managed", + ["EncryptionAlgorithmType"] = typeof(TripleDES).AssemblyQualifiedName, + ["EncryptionAlgorithmKeySize"] = 2048, + ["ValidationAlgorithmType"] = typeof(HMACSHA1).AssemblyQualifiedName + }; + var expectedConfiguration = new ManagedAuthenticatedEncryptorConfiguration() + { + EncryptionAlgorithmType = typeof(TripleDES), + EncryptionAlgorithmKeySize = 2048, + ValidationAlgorithmType = typeof(HMACSHA1) + }; + + // Act + var context = RunTestWithRegValues(registryEntries); + + // Assert + var actualConfiguration = (ManagedAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration; + + Assert.Equal(expectedConfiguration.EncryptionAlgorithmType, actualConfiguration.EncryptionAlgorithmType); + Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize); + Assert.Equal(expectedConfiguration.ValidationAlgorithmType, actualConfiguration.ValidationAlgorithmType); + } + + private static RegistryPolicy RunTestWithRegValues(Dictionary regValues) + { + return WithUniqueTempRegKey(registryKey => + { + foreach (var entry in regValues) + { + registryKey.SetValue(entry.Key, entry.Value); + } + + var policyResolver = new RegistryPolicyResolver( + registryKey, + activator: SimpleActivator.DefaultWithoutServices); + + return policyResolver.ResolvePolicy(); + }); + } + + /// + /// Runs a test and cleans up the registry key afterward. + /// + private static RegistryPolicy WithUniqueTempRegKey(Func testCode) + { + string uniqueName = Guid.NewGuid().ToString(); + var uniqueSubkey = LazyHkcuTempKey.Value.CreateSubKey(uniqueName); + try + { + return testCode(uniqueSubkey); + } + finally + { + // clean up when test is done + LazyHkcuTempKey.Value.DeleteSubKeyTree(uniqueName, throwOnMissingSubKey: false); + } + } + + private static readonly Lazy LazyHkcuTempKey = new Lazy(() => + { + try + { + return Registry.CurrentUser.CreateSubKey(@"SOFTWARE\Microsoft\ASP.NET\temp"); + } + catch + { + // swallow all failures + return null; + } + }); + + private class ConditionalRunTestOnlyIfHkcuRegistryAvailable : Attribute, ITestCondition + { + public bool IsMet => (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && LazyHkcuTempKey.Value != null); + + public string SkipReason { get; } = "HKCU registry couldn't be opened."; + } + + private class MyKeyEscrowSink1 : IKeyEscrowSink + { + public void Store(Guid keyId, XElement element) + { + throw new NotImplementedException(); + } + } + + private class MyKeyEscrowSink2 : IKeyEscrowSink + { + public void Store(Guid keyId, XElement element) + { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Repositories/EphemeralXmlRepositoryTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Repositories/EphemeralXmlRepositoryTests.cs new file mode 100644 index 0000000000..b903267415 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Repositories/EphemeralXmlRepositoryTests.cs @@ -0,0 +1,40 @@ +// 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.Xml.Linq; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Repositories +{ + public class EphemeralXmlRepositoryTests + { + [Fact] + public void GetAllElements_Empty() + { + // Arrange + var repository = new EphemeralXmlRepository(NullLoggerFactory.Instance); + + // Act & assert + Assert.Empty(repository.GetAllElements()); + } + + [Fact] + public void Store_Then_Get() + { + // Arrange + var element1 = XElement.Parse(@""); + var element2 = XElement.Parse(@""); + var element3 = XElement.Parse(@""); + var repository = new EphemeralXmlRepository(NullLoggerFactory.Instance); + + // Act & assert + repository.StoreElement(element1, "Invalid friendly name."); // nobody should care about the friendly name + repository.StoreElement(element2, "abcdefg"); + Assert.Equal(new[] { element1, element2 }, repository.GetAllElements(), XmlAssert.EqualityComparer); + repository.StoreElement(element3, null); + Assert.Equal(new[] { element1, element2, element3 }, repository.GetAllElements(), XmlAssert.EqualityComparer); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Repositories/FileSystemXmlRepositoryTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Repositories/FileSystemXmlRepositoryTests.cs new file mode 100644 index 0000000000..4bc2e10171 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Repositories/FileSystemXmlRepositoryTests.cs @@ -0,0 +1,182 @@ +// 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.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Xml.Linq; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Repositories +{ + public class FileSystemXmlRepositoryTests + { + [Fact] + public void DefaultKeyStorageDirectory_Property() + { + var baseDir = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ASP.NET") + : Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".aspnet"); + var expectedDir = new DirectoryInfo(Path.Combine(baseDir, "DataProtection-Keys")).FullName; + + // Act + var defaultDirInfo = FileSystemXmlRepository.DefaultKeyStorageDirectory; + + // Assert + Assert.Equal(expectedDir, defaultDirInfo.FullName); + } + + [Fact] + public void Directory_Property() + { + WithUniqueTempDirectory(dirInfo => + { + // Arrange + var repository = new FileSystemXmlRepository(dirInfo, NullLoggerFactory.Instance); + + // Act + var retVal = repository.Directory; + + // Assert + Assert.Equal(dirInfo, retVal); + }); + } + + [Fact] + public void GetAllElements_EmptyOrNonexistentDirectory_ReturnsEmptyCollection() + { + WithUniqueTempDirectory(dirInfo => + { + // Arrange + var repository = new FileSystemXmlRepository(dirInfo, NullLoggerFactory.Instance); + + // Act + var allElements = repository.GetAllElements(); + + // Assert + Assert.Equal(0, allElements.Count); + }); + } + + [Fact] + public void StoreElement_WithValidFriendlyName_UsesFriendlyName() + { + WithUniqueTempDirectory(dirInfo => + { + // Arrange + var element = XElement.Parse(""); + var repository = new FileSystemXmlRepository(dirInfo, NullLoggerFactory.Instance); + + // Act + repository.StoreElement(element, "valid-friendly-name"); + + // Assert + var fileInfos = dirInfo.GetFiles(); + var fileInfo = fileInfos.Single(); // only one file should've been created + + // filename should be "valid-friendly-name.xml" + Assert.Equal("valid-friendly-name.xml", fileInfo.Name, StringComparer.OrdinalIgnoreCase); + + // file contents should be "" + var parsedElement = XElement.Parse(File.ReadAllText(fileInfo.FullName)); + XmlAssert.Equal("", parsedElement); + }); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + [InlineData("..")] + [InlineData("not*friendly")] + public void StoreElement_WithInvalidFriendlyName_CreatesNewGuidAsName(string friendlyName) + { + WithUniqueTempDirectory(dirInfo => + { + // Arrange + var element = XElement.Parse(""); + var repository = new FileSystemXmlRepository(dirInfo, NullLoggerFactory.Instance); + + // Act + repository.StoreElement(element, friendlyName); + + // Assert + var fileInfos = dirInfo.GetFiles(); + var fileInfo = fileInfos.Single(); // only one file should've been created + + // filename should be "{GUID}.xml" + var filename = fileInfo.Name; + Assert.EndsWith(".xml", filename, StringComparison.OrdinalIgnoreCase); + var filenameNoSuffix = filename.Substring(0, filename.Length - ".xml".Length); + Guid parsedGuid = Guid.Parse(filenameNoSuffix); + Assert.NotEqual(Guid.Empty, parsedGuid); + + // file contents should be "" + var parsedElement = XElement.Parse(File.ReadAllText(fileInfo.FullName)); + XmlAssert.Equal("", parsedElement); + }); + } + + [Fact] + public void StoreElements_ThenRetrieve_SeesAllElements() + { + WithUniqueTempDirectory(dirInfo => + { + // Arrange + var repository = new FileSystemXmlRepository(dirInfo, NullLoggerFactory.Instance); + + // Act + repository.StoreElement(new XElement("element1"), friendlyName: null); + repository.StoreElement(new XElement("element2"), friendlyName: null); + repository.StoreElement(new XElement("element3"), friendlyName: null); + var allElements = repository.GetAllElements(); + + // Assert + var orderedNames = allElements.Select(el => el.Name.LocalName).OrderBy(name => name); + Assert.Equal(new[] { "element1", "element2", "element3" }, orderedNames); + }); + } + + [ConditionalFact] + [DockerOnly] + [Trait("Docker", "true")] + public void Logs_DockerEphemeralFolders() + { + // Arrange + var loggerFactory = new StringLoggerFactory(LogLevel.Warning); + WithUniqueTempDirectory(dirInfo => + { + // Act + var repo = new FileSystemXmlRepository(dirInfo, loggerFactory); + + // Assert + Assert.Contains(Resources.FormatFileSystem_EphemeralKeysLocationInContainer(dirInfo.FullName), loggerFactory.ToString()); + }); + } + + /// + /// Runs a test and cleans up the temp directory afterward. + /// + private static void WithUniqueTempDirectory(Action testCode) + { + string uniqueTempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + var dirInfo = new DirectoryInfo(uniqueTempPath); + try + { + testCode(dirInfo); + } + finally + { + // clean up when test is done + if (dirInfo.Exists) + { + dirInfo.Delete(recursive: true); + } + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Repositories/RegistryXmlRepositoryTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Repositories/RegistryXmlRepositoryTests.cs new file mode 100644 index 0000000000..11f0060ca3 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/Repositories/RegistryXmlRepositoryTests.cs @@ -0,0 +1,168 @@ +// 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 System.Runtime.InteropServices; +using System.Xml.Linq; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Win32; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Repositories +{ + public class RegistryXmlRepositoryTests + { + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void RegistryKey_Property() + { + WithUniqueTempRegKey(regKey => + { + // Arrange + var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance); + + // Act + var retVal = repository.RegistryKey; + + // Assert + Assert.Equal(regKey, retVal); + }); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void GetAllElements_EmptyOrNonexistentDirectory_ReturnsEmptyCollection() + { + WithUniqueTempRegKey(regKey => + { + // Arrange + var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance); + + // Act + var allElements = repository.GetAllElements(); + + // Assert + Assert.Equal(0, allElements.Count); + }); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void StoreElement_WithValidFriendlyName_UsesFriendlyName() + { + WithUniqueTempRegKey(regKey => + { + // Arrange + var element = XElement.Parse(""); + var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance); + + // Act + repository.StoreElement(element, "valid-friendly-name"); + + // Assert + var valueNames = regKey.GetValueNames(); + var valueName = valueNames.Single(); // only one value should've been created + + // value name should be "valid-friendly-name" + Assert.Equal("valid-friendly-name", valueName, StringComparer.OrdinalIgnoreCase); + + // value contents should be "" + var parsedElement = XElement.Parse(regKey.GetValue(valueName) as string); + XmlAssert.Equal("", parsedElement); + }); + } + + [ConditionalTheory] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + [InlineData("..")] + [InlineData("not*friendly")] + public void StoreElement_WithInvalidFriendlyName_CreatesNewGuidAsName(string friendlyName) + { + WithUniqueTempRegKey(regKey => + { + // Arrange + var element = XElement.Parse(""); + var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance); + + // Act + repository.StoreElement(element, friendlyName); + + // Assert + var valueNames = regKey.GetValueNames(); + var valueName = valueNames.Single(); // only one value should've been created + + // value name should be "{GUID}" + Guid parsedGuid = Guid.Parse(valueName as string); + Assert.NotEqual(Guid.Empty, parsedGuid); + + // value contents should be "" + var parsedElement = XElement.Parse(regKey.GetValue(valueName) as string); + XmlAssert.Equal("", parsedElement); + }); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] + public void StoreElements_ThenRetrieve_SeesAllElements() + { + WithUniqueTempRegKey(regKey => + { + // Arrange + var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance); + + // Act + repository.StoreElement(new XElement("element1"), friendlyName: null); + repository.StoreElement(new XElement("element2"), friendlyName: null); + repository.StoreElement(new XElement("element3"), friendlyName: null); + var allElements = repository.GetAllElements(); + + // Assert + var orderedNames = allElements.Select(el => el.Name.LocalName).OrderBy(name => name); + Assert.Equal(new[] { "element1", "element2", "element3" }, orderedNames); + }); + } + + /// + /// Runs a test and cleans up the registry key afterward. + /// + private static void WithUniqueTempRegKey(Action testCode) + { + string uniqueName = Guid.NewGuid().ToString(); + var uniqueSubkey = LazyHkcuTempKey.Value.CreateSubKey(uniqueName); + try + { + testCode(uniqueSubkey); + } + finally + { + // clean up when test is done + LazyHkcuTempKey.Value.DeleteSubKeyTree(uniqueName, throwOnMissingSubKey: false); + } + } + + private static readonly Lazy LazyHkcuTempKey = new Lazy(() => + { + try + { + return Registry.CurrentUser.CreateSubKey(@"SOFTWARE\Microsoft\ASP.NET\temp"); + } + catch + { + // swallow all failures + return null; + } + }); + + private class ConditionalRunTestOnlyIfHkcuRegistryAvailable : Attribute, ITestCondition + { + public bool IsMet => (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && LazyHkcuTempKey.Value != null); + + public string SkipReason { get; } = "HKCU registry couldn't be opened."; + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SP800_108/SP800_108Tests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SP800_108/SP800_108Tests.cs new file mode 100644 index 0000000000..871ca83f5b --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SP800_108/SP800_108Tests.cs @@ -0,0 +1,173 @@ +// 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.Security.Cryptography; +using System.Text; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.SP800_108 +{ + public unsafe class SP800_108Tests + { + private delegate ISP800_108_CTR_HMACSHA512Provider ProviderFactory(byte* pbKdk, uint cbKdk); + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [Theory] + [InlineData(512 / 8 - 1, "V47WmHzPSkdC2vkLAomIjCzZlDOAetll3yJLcSvon7LJFjJpEN+KnSNp+gIpeydKMsENkflbrIZ/3s6GkEaH")] + [InlineData(512 / 8 + 0, "mVaFM4deXLl610CmnCteNzxgbM/VkmKznAlPauHcDBn0le06uOjAKLHx0LfoU2/Ttq9nd78Y6Nk6wArmdwJgJg==")] + [InlineData(512 / 8 + 1, "GaHPeqdUxriFpjRtkYQYWr5/iqneD/+hPhVJQt4rXblxSpB1UUqGqL00DMU/FJkX0iMCfqUjQXtXyfks+p++Ev4=")] + public void DeriveKeyWithContextHeader_Normal_Managed(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = Encoding.UTF8.GetBytes("kdk"); + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert + TestManagedKeyDerivation(kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [ConditionalTheory] + [ConditionalRunTestOnlyOnWindows] + [InlineData(512 / 8 - 1, "V47WmHzPSkdC2vkLAomIjCzZlDOAetll3yJLcSvon7LJFjJpEN+KnSNp+gIpeydKMsENkflbrIZ/3s6GkEaH")] + [InlineData(512 / 8 + 0, "mVaFM4deXLl610CmnCteNzxgbM/VkmKznAlPauHcDBn0le06uOjAKLHx0LfoU2/Ttq9nd78Y6Nk6wArmdwJgJg==")] + [InlineData(512 / 8 + 1, "GaHPeqdUxriFpjRtkYQYWr5/iqneD/+hPhVJQt4rXblxSpB1UUqGqL00DMU/FJkX0iMCfqUjQXtXyfks+p++Ev4=")] + public void DeriveKeyWithContextHeader_Normal_Win7(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = Encoding.UTF8.GetBytes("kdk"); + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert + TestCngKeyDerivation((pbKdk, cbKdk) => new Win7SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk), kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [ConditionalTheory] + [ConditionalRunTestOnlyOnWindows8OrLater] + [InlineData(512 / 8 - 1, "V47WmHzPSkdC2vkLAomIjCzZlDOAetll3yJLcSvon7LJFjJpEN+KnSNp+gIpeydKMsENkflbrIZ/3s6GkEaH")] + [InlineData(512 / 8 + 0, "mVaFM4deXLl610CmnCteNzxgbM/VkmKznAlPauHcDBn0le06uOjAKLHx0LfoU2/Ttq9nd78Y6Nk6wArmdwJgJg==")] + [InlineData(512 / 8 + 1, "GaHPeqdUxriFpjRtkYQYWr5/iqneD/+hPhVJQt4rXblxSpB1UUqGqL00DMU/FJkX0iMCfqUjQXtXyfks+p++Ev4=")] + public void DeriveKeyWithContextHeader_Normal_Win8(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = Encoding.UTF8.GetBytes("kdk"); + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert + TestCngKeyDerivation((pbKdk, cbKdk) => new Win8SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk), kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [Theory] + [InlineData(512 / 8 - 1, "rt2hM6kkQ8hAXmkHx0TU4o3Q+S7fie6b3S1LAq107k++P9v8uSYA2G+WX3pJf9ZkpYrTKD7WUIoLkgA1R9lk")] + [InlineData(512 / 8 + 0, "RKiXmHSrWq5gkiRSyNZWNJrMR0jDyYHJMt9odOayRAE5wLSX2caINpQmfzTH7voJQi3tbn5MmD//dcspghfBiw==")] + [InlineData(512 / 8 + 1, "KedXO0zAIZ3AfnPqY1NnXxpC3HDHIxefG4bwD3g6nWYEc5+q7pjbam71Yqj0zgHMNC9Z7BX3wS1/tajFocRWZUk=")] + public void DeriveKeyWithContextHeader_LongKey_Managed(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = new byte[50000]; // CNG can't normally handle a 50,000 byte KDK, but we coerce it into working :) + for (int i = 0; i < kdk.Length; i++) + { + kdk[i] = (byte)i; + } + + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert + TestManagedKeyDerivation(kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [ConditionalTheory] + [ConditionalRunTestOnlyOnWindows] + [InlineData(512 / 8 - 1, "rt2hM6kkQ8hAXmkHx0TU4o3Q+S7fie6b3S1LAq107k++P9v8uSYA2G+WX3pJf9ZkpYrTKD7WUIoLkgA1R9lk")] + [InlineData(512 / 8 + 0, "RKiXmHSrWq5gkiRSyNZWNJrMR0jDyYHJMt9odOayRAE5wLSX2caINpQmfzTH7voJQi3tbn5MmD//dcspghfBiw==")] + [InlineData(512 / 8 + 1, "KedXO0zAIZ3AfnPqY1NnXxpC3HDHIxefG4bwD3g6nWYEc5+q7pjbam71Yqj0zgHMNC9Z7BX3wS1/tajFocRWZUk=")] + public void DeriveKeyWithContextHeader_LongKey_Win7(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = new byte[50000]; // CNG can't normally handle a 50,000 byte KDK, but we coerce it into working :) + for (int i = 0; i < kdk.Length; i++) + { + kdk[i] = (byte)i; + } + + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert + TestCngKeyDerivation((pbKdk, cbKdk) => new Win7SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk), kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [ConditionalTheory] + [ConditionalRunTestOnlyOnWindows8OrLater] + [InlineData(512 / 8 - 1, "rt2hM6kkQ8hAXmkHx0TU4o3Q+S7fie6b3S1LAq107k++P9v8uSYA2G+WX3pJf9ZkpYrTKD7WUIoLkgA1R9lk")] + [InlineData(512 / 8 + 0, "RKiXmHSrWq5gkiRSyNZWNJrMR0jDyYHJMt9odOayRAE5wLSX2caINpQmfzTH7voJQi3tbn5MmD//dcspghfBiw==")] + [InlineData(512 / 8 + 1, "KedXO0zAIZ3AfnPqY1NnXxpC3HDHIxefG4bwD3g6nWYEc5+q7pjbam71Yqj0zgHMNC9Z7BX3wS1/tajFocRWZUk=")] + public void DeriveKeyWithContextHeader_LongKey_Win8(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = new byte[50000]; // CNG can't normally handle a 50,000 byte KDK, but we coerce it into working :) + for (int i = 0; i < kdk.Length; i++) + { + kdk[i] = (byte)i; + } + + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert + TestCngKeyDerivation((pbKdk, cbKdk) => new Win8SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk), kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + private static void TestCngKeyDerivation(ProviderFactory factory, byte[] kdk, byte[] label, byte[] contextHeader, byte[] context, int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + byte[] derivedSubkey = new byte[numDerivedBytes]; + + fixed (byte* pbKdk = kdk) + fixed (byte* pbLabel = label) + fixed (byte* pbContext = context) + fixed (byte* pbDerivedSubkey = derivedSubkey) + { + ISP800_108_CTR_HMACSHA512Provider provider = factory(pbKdk, (uint)kdk.Length); + provider.DeriveKeyWithContextHeader(pbLabel, (uint)label.Length, contextHeader, pbContext, (uint)context.Length, pbDerivedSubkey, (uint)derivedSubkey.Length); + } + + Assert.Equal(expectedDerivedSubkeyAsBase64, Convert.ToBase64String(derivedSubkey)); + } + + private static void TestManagedKeyDerivation(byte[] kdk, byte[] label, byte[] contextHeader, byte[] context, int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + var labelSegment = new ArraySegment(new byte[label.Length + 10], 3, label.Length); + Buffer.BlockCopy(label, 0, labelSegment.Array, labelSegment.Offset, labelSegment.Count); + var contextSegment = new ArraySegment(new byte[context.Length + 10], 5, context.Length); + Buffer.BlockCopy(context, 0, contextSegment.Array, contextSegment.Offset, contextSegment.Count); + var derivedSubkeySegment = new ArraySegment(new byte[numDerivedBytes + 10], 4, numDerivedBytes); + + ManagedSP800_108_CTR_HMACSHA512.DeriveKeysWithContextHeader(kdk, labelSegment, contextHeader, contextSegment, + bytes => new HMACSHA512(bytes), derivedSubkeySegment); + Assert.Equal(expectedDerivedSubkeyAsBase64, Convert.ToBase64String(derivedSubkeySegment.AsStandaloneArray())); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SecretAssert.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SecretAssert.cs new file mode 100644 index 0000000000..d3fb1cbc70 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SecretAssert.cs @@ -0,0 +1,45 @@ +// 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 Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Helpful ISecret-based assertions. + /// + public static class SecretAssert + { + /// + /// Asserts that two instances contain the same material. + /// + public static void Equal(ISecret secret1, ISecret secret2) + { + Assert.Equal(SecretToBase64String(secret1), SecretToBase64String(secret2)); + } + + /// + /// Asserts that has the length specified by . + /// + public static void LengthIs(int expectedLengthInBits, ISecret secret) + { + Assert.Equal(expectedLengthInBits, checked(secret.Length * 8)); + } + + /// + /// Asserts that two instances do not contain the same material. + /// + public static void NotEqual(ISecret secret1, ISecret secret2) + { + Assert.NotEqual(SecretToBase64String(secret1), SecretToBase64String(secret2)); + } + + private static string SecretToBase64String(ISecret secret) + { + byte[] secretBytes = new byte[secret.Length]; + secret.WriteSecretIntoBuffer(new ArraySegment(secretBytes)); + return Convert.ToBase64String(secretBytes); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SecretTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SecretTests.cs new file mode 100644 index 0000000000..b9342ad765 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SecretTests.cs @@ -0,0 +1,269 @@ +// 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 Microsoft.AspNetCore.Testing; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public unsafe class SecretTests + { + [Fact] + public void Ctor_ArraySegment_Default_Throws() + { + // Act & assert + ExceptionAssert.ThrowsArgument( + testCode: () => new Secret(default(ArraySegment)), + paramName: "array", + exceptionMessage: null); + } + + [Fact] + public void Ctor_ArraySegment_Success() + { + // Arrange + var input = new ArraySegment(new byte[] { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, 1, 3); + + // Act + var secret = new Secret(input); + input.Array[2] = 0xFF; // mutate original array - secret shouldn't be modified + + // Assert - length + Assert.Equal(3, secret.Length); + + // Assert - managed buffer + var outputSegment = new ArraySegment(new byte[7], 2, 3); + secret.WriteSecretIntoBuffer(outputSegment); + Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputSegment.AsStandaloneArray()); + + // Assert - unmanaged buffer + var outputBuffer = new byte[3]; + fixed (byte* pOutputBuffer = outputBuffer) + { + secret.WriteSecretIntoBuffer(pOutputBuffer, 3); + } + Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputBuffer); + } + + [Fact] + public void Ctor_Buffer_Success() + { + // Arrange + var input = new byte[] { 0x20, 0x30, 0x40 }; + + // Act + var secret = new Secret(input); + input[1] = 0xFF; // mutate original array - secret shouldn't be modified + + // Assert - length + Assert.Equal(3, secret.Length); + + // Assert - managed buffer + var outputSegment = new ArraySegment(new byte[7], 2, 3); + secret.WriteSecretIntoBuffer(outputSegment); + Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputSegment.AsStandaloneArray()); + + // Assert - unmanaged buffer + var outputBuffer = new byte[3]; + fixed (byte* pOutputBuffer = outputBuffer) + { + secret.WriteSecretIntoBuffer(pOutputBuffer, 3); + } + Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputBuffer); + } + + [Fact] + public void Ctor_Buffer_ZeroLength_Success() + { + // Act + var secret = new Secret(new byte[0]); + + // Assert - none of these methods should throw + Assert.Equal(0, secret.Length); + secret.WriteSecretIntoBuffer(new ArraySegment(new byte[0])); + byte dummy; + secret.WriteSecretIntoBuffer(&dummy, 0); + } + + [Fact] + public void Ctor_Pointer_WithNullPointer_ThrowsArgumentNull() + { + // Act & assert + ExceptionAssert.ThrowsArgumentNull( + testCode: () => new Secret(null, 0), + paramName: "secret"); + } + + [Fact] + public void Ctor_Pointer_WithNegativeLength_ThrowsArgumentOutOfRange() + { + // Act & assert + ExceptionAssert.ThrowsArgumentOutOfRange( + testCode: () => + { + byte dummy; + new Secret(&dummy, -1); + }, + paramName: "secretLength", + exceptionMessage: Resources.Common_ValueMustBeNonNegative); + } + + [Fact] + public void Ctor_Pointer_ZeroLength_Success() + { + // Arrange + byte input; + + // Act + var secret = new Secret(&input, 0); + + // Assert - none of these methods should throw + Assert.Equal(0, secret.Length); + secret.WriteSecretIntoBuffer(new ArraySegment(new byte[0])); + byte dummy; + secret.WriteSecretIntoBuffer(&dummy, 0); + } + + [Fact] + public void Ctor_Pointer_Success() + { + // Arrange + byte* input = stackalloc byte[3]; + input[0] = 0x20; + input[1] = 0x30; + input[2] = 0x40; + + // Act + var secret = new Secret(input, 3); + input[1] = 0xFF; // mutate original buffer - secret shouldn't be modified + + // Assert - length + Assert.Equal(3, secret.Length); + + // Assert - managed buffer + var outputSegment = new ArraySegment(new byte[7], 2, 3); + secret.WriteSecretIntoBuffer(outputSegment); + Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputSegment.AsStandaloneArray()); + + // Assert - unmanaged buffer + var outputBuffer = new byte[3]; + fixed (byte* pOutputBuffer = outputBuffer) + { + secret.WriteSecretIntoBuffer(pOutputBuffer, 3); + } + Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputBuffer); + } + + [Fact] + public void Random_ZeroLength_Success() + { + // Act + var secret = Secret.Random(0); + + // Assert + Assert.Equal(0, secret.Length); + } + + [Fact] + public void Random_LengthIsMultipleOf16_Success() + { + // Act + var secret = Secret.Random(32); + + // Assert + Assert.Equal(32, secret.Length); + Guid* pGuids = stackalloc Guid[2]; + secret.WriteSecretIntoBuffer((byte*)pGuids, 32); + Assert.NotEqual(Guid.Empty, pGuids[0]); + Assert.NotEqual(Guid.Empty, pGuids[1]); + Assert.NotEqual(pGuids[0], pGuids[1]); + } + + [Fact] + public void Random_LengthIsNotMultipleOf16_Success() + { + // Act + var secret = Secret.Random(31); + + // Assert + Assert.Equal(31, secret.Length); + Guid* pGuids = stackalloc Guid[2]; + secret.WriteSecretIntoBuffer((byte*)pGuids, 31); + Assert.NotEqual(Guid.Empty, pGuids[0]); + Assert.NotEqual(Guid.Empty, pGuids[1]); + Assert.NotEqual(pGuids[0], pGuids[1]); + Assert.Equal(0, ((byte*)pGuids)[31]); // last byte shouldn't have been overwritten + } + + [Fact] + public void WriteSecretIntoBuffer_ArraySegment_IncorrectlySizedBuffer_Throws() + { + // Arrange + var secret = Secret.Random(16); + + // Act & assert + ExceptionAssert.ThrowsArgument( + testCode: () => secret.WriteSecretIntoBuffer(new ArraySegment(new byte[100])), + paramName: "buffer", + exceptionMessage: Resources.FormatCommon_BufferIncorrectlySized(100, 16)); + } + + [Fact] + public void WriteSecretIntoBuffer_ArraySegment_Disposed_Throws() + { + // Arrange + var secret = Secret.Random(16); + secret.Dispose(); + + // Act & assert + Assert.Throws( + testCode: () => secret.WriteSecretIntoBuffer(new ArraySegment(new byte[16]))); + } + + [Fact] + public void WriteSecretIntoBuffer_Pointer_NullBuffer_Throws() + { + // Arrange + var secret = Secret.Random(16); + + // Act & assert + ExceptionAssert.ThrowsArgumentNull( + testCode: () => secret.WriteSecretIntoBuffer(null, 100), + paramName: "buffer"); + } + + [Fact] + public void WriteSecretIntoBuffer_Pointer_IncorrectlySizedBuffer_Throws() + { + // Arrange + var secret = Secret.Random(16); + + // Act & assert + ExceptionAssert.ThrowsArgument( + testCode: () => + { + byte* pBuffer = stackalloc byte[100]; + secret.WriteSecretIntoBuffer(pBuffer, 100); + }, + paramName: "bufferLength", + exceptionMessage: Resources.FormatCommon_BufferIncorrectlySized(100, 16)); + } + + [Fact] + public void WriteSecretIntoBuffer_Pointer_Disposed_Throws() + { + // Arrange + var secret = Secret.Random(16); + secret.Dispose(); + + // Act & assert + Assert.Throws( + testCode: () => + { + byte* pBuffer = stackalloc byte[16]; + secret.WriteSecretIntoBuffer(pBuffer, 16); + }); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SequentialGenRandom.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SequentialGenRandom.cs new file mode 100644 index 0000000000..c37462ef97 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/SequentialGenRandom.cs @@ -0,0 +1,32 @@ +// 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 Microsoft.AspNetCore.DataProtection.Cng; +using Microsoft.AspNetCore.DataProtection.Managed; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal unsafe class SequentialGenRandom : IBCryptGenRandom, IManagedGenRandom + { + private byte _value; + + public byte[] GenRandom(int numBytes) + { + byte[] bytes = new byte[numBytes]; + for (int i = 0; i < bytes.Length; i++) + { + bytes[i] = _value++; + } + return bytes; + } + + public void GenRandom(byte* pbBuffer, uint cbBuffer) + { + for (uint i = 0; i < cbBuffer; i++) + { + pbBuffer[i] = _value++; + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/ServiceCollectionTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/ServiceCollectionTests.cs new file mode 100644 index 0000000000..ad05973c0b --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/ServiceCollectionTests.cs @@ -0,0 +1,67 @@ +// 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 Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class ServiceCollectionTests + { + [Fact] + public void AddsOptions() + { + var services = new ServiceCollection() + .AddDataProtection() + .Services + .BuildServiceProvider(); + + Assert.NotNull(services.GetService>()); + } + + [Fact] + public void DoesNotOverrideLogging() + { + var services1 = new ServiceCollection() + .AddLogging() + .AddDataProtection() + .Services + .BuildServiceProvider(); + + var services2 = new ServiceCollection() + .AddDataProtection() + .Services + .AddLogging() + .BuildServiceProvider(); + + Assert.Equal( + services1.GetRequiredService().GetType(), + services2.GetRequiredService().GetType()); + } + + [Fact] + public void CanResolveAllRegisteredServices() + { + var serviceCollection = new ServiceCollection() + .AddDataProtection() + .Services; + var services = serviceCollection.BuildServiceProvider(validateScopes: true); + + Assert.Null(services.GetService()); + + foreach (var descriptor in serviceCollection) + { + if (descriptor.ServiceType.Assembly.GetName().Name == "Microsoft.Extensions.Options") + { + // ignore any descriptors added by the call to .AddOptions() + continue; + } + + Assert.NotNull(services.GetService(descriptor.ServiceType)); + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/StringLoggerFactory.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/StringLoggerFactory.cs new file mode 100644 index 0000000000..8d2b146b27 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/StringLoggerFactory.cs @@ -0,0 +1,82 @@ +// 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.Globalization; +using System.Text; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.DataProtection +{ + internal sealed class StringLoggerFactory : ILoggerFactory + { + private readonly StringBuilder _log = new StringBuilder(); + + public StringLoggerFactory(LogLevel logLevel) + { + MinimumLevel = logLevel; + } + + public LogLevel MinimumLevel { get; set; } + + public void AddProvider(ILoggerProvider provider) + { + // no-op + } + + public ILogger CreateLogger(string name) + { + return new StringLogger(name, this); + } + + public void Dispose() + { + } + + public override string ToString() + { + return _log.ToString(); + } + + private sealed class StringLogger : ILogger + { + private readonly StringLoggerFactory _factory; + private readonly string _name; + + public StringLogger(string name, StringLoggerFactory factory) + { + _name = name; + _factory = factory; + } + + public IDisposable BeginScope(TState state) + { + return new DummyDisposable(); + } + + public bool IsEnabled(LogLevel logLevel) + { + return (logLevel >= _factory.MinimumLevel); + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + string message = string.Format(CultureInfo.InvariantCulture, + "Provider: {0}" + Environment.NewLine + + "Log level: {1}" + Environment.NewLine + + "Event id: {2}" + Environment.NewLine + + "Exception: {3}" + Environment.NewLine + + "Message: {4}", _name, logLevel, eventId, exception?.ToString(), formatter(state, exception)); + _factory._log.AppendLine(message); + } + + private sealed class DummyDisposable : IDisposable + { + public void Dispose() + { + // no-op + } + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TestFiles/TestCert1.PublicKeyOnly.cer b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TestFiles/TestCert1.PublicKeyOnly.cer new file mode 100644 index 0000000000..329c90a83b Binary files /dev/null and b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TestFiles/TestCert1.PublicKeyOnly.cer differ diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TestFiles/TestCert1.pfx b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TestFiles/TestCert1.pfx new file mode 100644 index 0000000000..8bf695f1d6 Binary files /dev/null and b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TestFiles/TestCert1.pfx differ diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TestFiles/TestCert2.pfx b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TestFiles/TestCert2.pfx new file mode 100644 index 0000000000..a54c93ba34 Binary files /dev/null and b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TestFiles/TestCert2.pfx differ diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TypeForwardingActivatorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TypeForwardingActivatorTests.cs new file mode 100644 index 0000000000..c9a68ff746 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/TypeForwardingActivatorTests.cs @@ -0,0 +1,172 @@ +// 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.Collections.Generic; +using System.Reflection; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + public class TypeForwardingActivatorTests : MarshalByRefObject + { + [Fact] + public void CreateInstance_ForwardsToNewNamespaceIfExists() + { + // Arrange + var serviceCollection = new ServiceCollection(); + serviceCollection.AddDataProtection(); + var services = serviceCollection.BuildServiceProvider(); + var activator = services.GetActivator(); + + // Act + var name = "Microsoft.AspNet.DataProtection.TypeForwardingActivatorTests+ClassWithParameterlessCtor, Microsoft.AspNet.DataProtection.Test, Version=1.0.0.0"; + var instance = activator.CreateInstance(name); + + // Assert + Assert.IsType(instance); + } + + [Fact] + public void CreateInstance_DoesNotForwardIfClassDoesNotExist() + { + // Arrange + var serviceCollection = new ServiceCollection(); + serviceCollection.AddDataProtection(); + var services = serviceCollection.BuildServiceProvider(); + var activator = services.GetActivator(); + + // Act & Assert + var name = "Microsoft.AspNet.DataProtection.TypeForwardingActivatorTests+NonExistentClassWithParameterlessCtor, Microsoft.AspNet.DataProtection.Test"; + var exception = Assert.ThrowsAny(() => activator.CreateInstance(name)); + + Assert.Contains("Microsoft.AspNet.DataProtection.Test", exception.Message); + } + + [Theory] + [InlineData(typeof(GenericType>))] + [InlineData(typeof(GenericType))] + [InlineData(typeof(GenericType>))] + [InlineData(typeof(GenericType>))] + [InlineData(typeof(GenericType))] + [InlineData(typeof(GenericType))] + [InlineData(typeof(List))] + public void CreateInstance_Generics(Type type) + { + // Arrange + var activator = new TypeForwardingActivator(null); + var name = type.AssemblyQualifiedName; + + // Act & Assert + Assert.IsType(type, activator.CreateInstance(name)); + } + + [Theory] + [InlineData(typeof(GenericType<>))] + [InlineData(typeof(GenericType<,>))] + public void CreateInstance_ThrowsForOpenGenerics(Type type) + { + // Arrange + var activator = new TypeForwardingActivator(null); + var name = type.AssemblyQualifiedName; + + // Act & Assert + Assert.Throws(() => activator.CreateInstance(name)); + } + + [Theory] + [InlineData( + "System.Tuple`1[[Some.Type, Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + "System.Tuple`1[[Some.Type, Microsoft.AspNetCore.DataProtection, Culture=neutral]], mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [InlineData( + "Some.Type`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral", + "Some.Type`1[[System.Int32, mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Microsoft.AspNetCore.DataProtection, Culture=neutral")] + [InlineData( + "System.Tuple`1[[System.Tuple`1[[Some.Type, Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + "System.Tuple`1[[System.Tuple`1[[Some.Type, Microsoft.AspNetCore.DataProtection, Culture=neutral]], mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + public void ParsesFullyQualifiedTypeName(string typeName, string expected) + { + Assert.Equal(expected, new MockTypeForwardingActivator().Parse(typeName)); + } + + [Theory] + [InlineData(typeof(List))] + [InlineData(typeof(FactAttribute))] + public void CreateInstance_DoesNotForwardingTypesExternalTypes(Type type) + { + new TypeForwardingActivator(null).CreateInstance(typeof(object), type.AssemblyQualifiedName, out var forwarded); + Assert.False(forwarded, "Should not have forwarded types that are not in Microsoft.AspNetCore.DataProjection"); + } + + [Theory] + [MemberData(nameof(AssemblyVersions))] + public void CreateInstance_ForwardsAcrossVersionChanges(Version version) + { +#if NET461 + // run this test in an appdomain without testhost's custom assembly resolution hooks + var setupInfo = new AppDomainSetup + { + ApplicationBase = AppDomain.CurrentDomain.BaseDirectory, + ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, + }; + var domain = AppDomain.CreateDomain("TestDomain", null, setupInfo); + var wrappedTestClass = (TypeForwardingActivatorTests)domain.CreateInstanceAndUnwrap(GetType().Assembly.FullName, typeof(TypeForwardingActivatorTests).FullName); + wrappedTestClass.CreateInstance_ForwardsAcrossVersionChangesImpl(version); +#elif NETCOREAPP3_0 + CreateInstance_ForwardsAcrossVersionChangesImpl(version); +#else +#error Target framework should be updated +#endif + } + + private void CreateInstance_ForwardsAcrossVersionChangesImpl(Version newVersion) + { + var activator = new TypeForwardingActivator(null); + + var typeInfo = typeof(ClassWithParameterlessCtor).GetTypeInfo(); + var typeName = typeInfo.FullName; + var assemblyName = typeInfo.Assembly.GetName(); + + assemblyName.Version = newVersion; + var newName = $"{typeName}, {assemblyName}"; + + Assert.NotEqual(typeInfo.AssemblyQualifiedName, newName); + Assert.IsType(activator.CreateInstance(typeof(object), newName, out var forwarded)); + Assert.True(forwarded, "Should have forwarded this type to new version or namespace"); + } + + public static TheoryData AssemblyVersions + { + get + { + var current = typeof(ActivatorTests).Assembly.GetName().Version; + return new TheoryData + { + new Version(Math.Max(0, current.Major - 1), 0, 0, 0), + new Version(current.Major + 1, 0, 0, 0), + new Version(current.Major, current.Minor + 1, 0, 0), + new Version(current.Major, current.Minor, current.Build + 1, 0), + }; + } + } + + private class MockTypeForwardingActivator : TypeForwardingActivator + { + public MockTypeForwardingActivator() : base(null) { } + public string Parse(string typeName) => RemoveVersionFromAssemblyName(typeName); + } + + private class ClassWithParameterlessCtor + { + } + + private class GenericType + { + } + + private class GenericType + { + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlAssert.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlAssert.cs new file mode 100644 index 0000000000..3bd5ccdc16 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlAssert.cs @@ -0,0 +1,151 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection +{ + /// + /// Helpful XML-based assertions. + /// + public static class XmlAssert + { + public static readonly IEqualityComparer EqualityComparer = new CallbackBasedEqualityComparer(Core.AreEqual); + + /// + /// Asserts that a and an are semantically equivalent. + /// + public static void Equal(string expected, XElement actual) + { + Assert.NotNull(expected); + Assert.NotNull(actual); + Equal(XElement.Parse(expected), actual); + } + + /// + /// Asserts that two instances are semantically equivalent. + /// + public static void Equal(XElement expected, XElement actual) + { + Assert.NotNull(expected); + Assert.NotNull(actual); + + if (!Core.AreEqual(expected, actual)) + { + Assert.True(false, + "Expected element:" + Environment.NewLine + + expected.ToString() + Environment.NewLine + + "Actual element:" + Environment.NewLine + + actual.ToString()); + } + } + + private static class Core + { + private static readonly IEqualityComparer AttributeEqualityComparer = new CallbackBasedEqualityComparer(AreEqual); + + private static bool AreEqual(XElement expected, XElement actual) + { + return expected.Name == actual.Name + && AreEqual(expected.Attributes(), actual.Attributes()) + && AreEqual(expected.Nodes(), actual.Nodes()); + } + + private static bool AreEqual(IEnumerable expected, IEnumerable actual) + { + List filteredExpected = expected.Where(ShouldIncludeNodeDuringComparison).ToList(); + List filteredActual = actual.Where(ShouldIncludeNodeDuringComparison).ToList(); + return filteredExpected.SequenceEqual(filteredActual, EqualityComparer); + } + + internal static bool AreEqual(XNode expected, XNode actual) + { + if (expected is XText && actual is XText) + { + return AreEqual((XText)expected, (XText)actual); + } + else if (expected is XElement && actual is XElement) + { + return AreEqual((XElement)expected, (XElement)actual); + } + else + { + return false; + } + } + + private static bool AreEqual(XText expected, XText actual) + { + return expected.Value == actual.Value; + } + + private static bool AreEqual(IEnumerable expected, IEnumerable actual) + { + List orderedExpected = expected + .Where(ShouldIncludeAttributeDuringComparison) + .OrderBy(attr => attr.Name.ToString()) + .ToList(); + + List orderedActual = actual + .Where(ShouldIncludeAttributeDuringComparison) + .OrderBy(attr => attr.Name.ToString()) + .ToList(); + + return orderedExpected.SequenceEqual(orderedActual, AttributeEqualityComparer); + } + + private static bool AreEqual(XAttribute expected, XAttribute actual) + { + return expected.Name == actual.Name + && expected.Value == actual.Value; + } + + private static bool ShouldIncludeAttributeDuringComparison(XAttribute attribute) + { + // exclude 'xmlns' attributes since they're already considered in the + // actual element and attribute names + return attribute.Name != (XName)"xmlns" + && attribute.Name.Namespace != XNamespace.Xmlns; + } + + private static bool ShouldIncludeNodeDuringComparison(XNode node) + { + if (node is XComment) + { + return false; // not contextually relevant + } + + if (node is XText /* includes XCData */ || node is XElement) + { + return true; // relevant + } + + throw new NotSupportedException(string.Format("Node of type '{0}' is not supported.", node.GetType().Name)); + } + } + + private sealed class CallbackBasedEqualityComparer : IEqualityComparer + { + private readonly Func _equalityCheck; + + public CallbackBasedEqualityComparer(Func equalityCheck) + { + _equalityCheck = equalityCheck; + } + + public bool Equals(T x, T y) + { + return _equalityCheck(x, y); + } + + public int GetHashCode(T obj) + { + return obj.ToString().GetHashCode(); + } + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/CertificateXmlEncryptionTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/CertificateXmlEncryptionTests.cs new file mode 100644 index 0000000000..425e15f51c --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/CertificateXmlEncryptionTests.cs @@ -0,0 +1,61 @@ +// 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.Security.Cryptography; +using System.Security.Cryptography.Xml; +using System.Xml; +using System.Xml.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + public class CertificateXmlEncryptorTests + { + [Fact] + public void Encrypt_Decrypt_RoundTrips() + { + // Arrange + var symmetricAlgorithm = new TripleDESCryptoServiceProvider(); + symmetricAlgorithm.GenerateKey(); + + var mockInternalEncryptor = new Mock(); + mockInternalEncryptor.Setup(o => o.PerformEncryption(It.IsAny(), It.IsAny())) + .Returns((encryptedXml, element) => + { + encryptedXml.AddKeyNameMapping("theKey", symmetricAlgorithm); // use symmetric encryption + return encryptedXml.Encrypt(element, "theKey"); + }); + + var mockInternalDecryptor = new Mock(); + mockInternalDecryptor.Setup(o => o.PerformPreDecryptionSetup(It.IsAny())) + .Callback(encryptedXml => + { + encryptedXml.AddKeyNameMapping("theKey", symmetricAlgorithm); // use symmetric encryption + }); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(mockInternalDecryptor.Object); + + var services = serviceCollection.BuildServiceProvider(); + var encryptor = new CertificateXmlEncryptor(NullLoggerFactory.Instance, mockInternalEncryptor.Object); + var decryptor = new EncryptedXmlDecryptor(services); + + var originalXml = XElement.Parse(@""); + + // Act & assert - run through encryptor and make sure we get back element + var encryptedXmlInfo = encryptor.Encrypt(originalXml); + Assert.Equal(typeof(EncryptedXmlDecryptor), encryptedXmlInfo.DecryptorType); + Assert.Equal(XName.Get("EncryptedData", "http://www.w3.org/2001/04/xmlenc#"), encryptedXmlInfo.EncryptedElement.Name); + Assert.Equal("http://www.w3.org/2001/04/xmlenc#Element", (string)encryptedXmlInfo.EncryptedElement.Attribute("Type")); + Assert.DoesNotContain("265ee4ea-ade2-43b1-b706-09b259e58b6b", encryptedXmlInfo.EncryptedElement.ToString(), StringComparison.OrdinalIgnoreCase); + + // Act & assert - run through decryptor and make sure we get back the original value + var roundTrippedElement = decryptor.Decrypt(encryptedXmlInfo.EncryptedElement); + XmlAssert.Equal(originalXml, roundTrippedElement); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/DpapiNGXmlEncryptionTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/DpapiNGXmlEncryptionTests.cs new file mode 100644 index 0000000000..6b16c638a8 --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/DpapiNGXmlEncryptionTests.cs @@ -0,0 +1,34 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + public class DpapiNGXmlEncryptionTests + { + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows8OrLater] + public void Encrypt_Decrypt_RoundTrips() + { + // Arrange + var originalXml = XElement.Parse(@""); + var encryptor = new DpapiNGXmlEncryptor("LOCAL=user", DpapiNGProtectionDescriptorFlags.None, NullLoggerFactory.Instance); + var decryptor = new DpapiNGXmlDecryptor(); + + // Act & assert - run through encryptor and make sure we get back an obfuscated element + var encryptedXmlInfo = encryptor.Encrypt(originalXml); + Assert.Equal(typeof(DpapiNGXmlDecryptor), encryptedXmlInfo.DecryptorType); + Assert.DoesNotContain("265ee4ea-ade2-43b1-b706-09b259e58b6b", encryptedXmlInfo.EncryptedElement.ToString(), StringComparison.OrdinalIgnoreCase); + + // Act & assert - run through decryptor and make sure we get back the original value + var roundTrippedElement = decryptor.Decrypt(encryptedXmlInfo.EncryptedElement); + XmlAssert.Equal(originalXml, roundTrippedElement); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/DpapiXmlEncryptionTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/DpapiXmlEncryptionTests.cs new file mode 100644 index 0000000000..7274d846ad --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/DpapiXmlEncryptionTests.cs @@ -0,0 +1,61 @@ +// 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.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.Test.Shared; +using Microsoft.AspNetCore.Testing; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + public class DpapiXmlEncryptionTests + { + [ConditionalTheory] + [ConditionalRunTestOnlyOnWindows] + [InlineData(true)] + [InlineData(false)] + public void Encrypt_CurrentUserOrLocalMachine_Decrypt_RoundTrips(bool protectToLocalMachine) + { + // Arrange + var originalXml = XElement.Parse(@""); + var encryptor = new DpapiXmlEncryptor(protectToLocalMachine, NullLoggerFactory.Instance); + var decryptor = new DpapiXmlDecryptor(); + + // Act & assert - run through encryptor and make sure we get back an obfuscated element + var encryptedXmlInfo = encryptor.Encrypt(originalXml); + Assert.Equal(typeof(DpapiXmlDecryptor), encryptedXmlInfo.DecryptorType); + Assert.DoesNotContain("265ee4ea-ade2-43b1-b706-09b259e58b6b", encryptedXmlInfo.EncryptedElement.ToString(), StringComparison.OrdinalIgnoreCase); + + // Act & assert - run through decryptor and make sure we get back the original value + var roundTrippedElement = decryptor.Decrypt(encryptedXmlInfo.EncryptedElement); + XmlAssert.Equal(originalXml, roundTrippedElement); + } + +#if NET461 + [ConditionalFact] + [ConditionalRunTestOnlyOnWindows] + public void Encrypt_CurrentUser_Decrypt_ImpersonatedAsAnonymous_Fails() + { + // Arrange + var originalXml = XElement.Parse(@""); + var encryptor = new DpapiXmlEncryptor(protectToLocalMachine: false, loggerFactory: NullLoggerFactory.Instance); + var decryptor = new DpapiXmlDecryptor(); + + // Act & assert - run through encryptor and make sure we get back an obfuscated element + var encryptedXmlInfo = encryptor.Encrypt(originalXml); + Assert.Equal(typeof(DpapiXmlDecryptor), encryptedXmlInfo.DecryptorType); + Assert.DoesNotContain("265ee4ea-ade2-43b1-b706-09b259e58b6b", encryptedXmlInfo.EncryptedElement.ToString(), StringComparison.OrdinalIgnoreCase); + + // Act & assert - run through decryptor (while impersonated as anonymous) and verify failure + ExceptionAssert2.ThrowsCryptographicException(() => + AnonymousImpersonation.Run(() => decryptor.Decrypt(encryptedXmlInfo.EncryptedElement))); + } +#elif NETCOREAPP3_0 +#else +#error Target framework needs to be updated +#endif + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/EncryptedXmlDecryptorTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/EncryptedXmlDecryptorTests.cs new file mode 100644 index 0000000000..5d3bb6943a --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/EncryptedXmlDecryptorTests.cs @@ -0,0 +1,91 @@ +// 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.IO; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.Test.XmlEncryption +{ + public class EncryptedXmlDecryptorTests + { + [Fact] + public void ThrowsIfCannotDecrypt() + { + var testCert1 = new X509Certificate2(Path.Combine(AppContext.BaseDirectory, "TestFiles", "TestCert1.pfx"), "password"); + var encryptor = new CertificateXmlEncryptor(testCert1, NullLoggerFactory.Instance); + var data = new XElement("SampleData", "Lorem ipsum"); + var encryptedXml = encryptor.Encrypt(data); + var decryptor = new EncryptedXmlDecryptor(); + + var ex = Assert.Throws(() => + decryptor.Decrypt(encryptedXml.EncryptedElement)); + Assert.Equal("Unable to retrieve the decryption key.", ex.Message); + } + + [Fact] + public void ThrowsIfProvidedCertificateDoesNotMatch() + { + var testCert1 = new X509Certificate2(Path.Combine(AppContext.BaseDirectory, "TestFiles", "TestCert1.pfx"), "password"); + var testCert2 = new X509Certificate2(Path.Combine(AppContext.BaseDirectory, "TestFiles", "TestCert2.pfx"), "password"); + var services = new ServiceCollection() + .Configure(o => o.AddKeyDecryptionCertificate(testCert2)) + .BuildServiceProvider(); + var encryptor = new CertificateXmlEncryptor(testCert1, NullLoggerFactory.Instance); + var data = new XElement("SampleData", "Lorem ipsum"); + var encryptedXml = encryptor.Encrypt(data); + var decryptor = new EncryptedXmlDecryptor(services); + + var ex = Assert.Throws(() => + decryptor.Decrypt(encryptedXml.EncryptedElement)); + Assert.Equal("Unable to retrieve the decryption key.", ex.Message); + } + + [Fact] + public void ThrowsIfProvidedCertificateDoesHavePrivateKey() + { + var fullCert = new X509Certificate2(Path.Combine(AppContext.BaseDirectory, "TestFiles", "TestCert1.pfx"), "password"); + var publicKeyOnly = new X509Certificate2(Path.Combine(AppContext.BaseDirectory, "TestFiles", "TestCert1.PublicKeyOnly.cer"), ""); + var services = new ServiceCollection() + .Configure(o => o.AddKeyDecryptionCertificate(publicKeyOnly)) + .BuildServiceProvider(); + var encryptor = new CertificateXmlEncryptor(fullCert, NullLoggerFactory.Instance); + var data = new XElement("SampleData", "Lorem ipsum"); + var encryptedXml = encryptor.Encrypt(data); + var decryptor = new EncryptedXmlDecryptor(services); + + var ex = Assert.Throws(() => + decryptor.Decrypt(encryptedXml.EncryptedElement)); + Assert.Equal("Unable to retrieve the decryption key.", ex.Message); + } + + [Fact] + public void XmlCanRoundTrip() + { + var testCert1 = new X509Certificate2(Path.Combine(AppContext.BaseDirectory, "TestFiles", "TestCert1.pfx"), "password"); + var testCert2 = new X509Certificate2(Path.Combine(AppContext.BaseDirectory, "TestFiles", "TestCert2.pfx"), "password"); + var services = new ServiceCollection() + .Configure(o => + { + o.AddKeyDecryptionCertificate(testCert1); + o.AddKeyDecryptionCertificate(testCert2); + }) + .BuildServiceProvider(); + var encryptor = new CertificateXmlEncryptor(testCert1, NullLoggerFactory.Instance); + var data = new XElement("SampleData", "Lorem ipsum"); + var encryptedXml = encryptor.Encrypt(data); + var decryptor = new EncryptedXmlDecryptor(services); + + var decrypted = decryptor.Decrypt(encryptedXml.EncryptedElement); + + Assert.Equal("SampleData", decrypted.Name); + Assert.Equal("Lorem ipsum", decrypted.Value); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/NullXmlEncryptionTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/NullXmlEncryptionTests.cs new file mode 100644 index 0000000000..8f4433d78c --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/NullXmlEncryptionTests.cs @@ -0,0 +1,39 @@ +// 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.Xml.Linq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + public class NullXmlEncryptionTests + { + [Fact] + public void NullDecryptor_ReturnsOriginalElement() + { + // Arrange + var decryptor = new NullXmlDecryptor(); + + // Act + var retVal = decryptor.Decrypt(XElement.Parse("")); + + // Assert + XmlAssert.Equal("", retVal); + } + + [Fact] + public void NullEncryptor_ReturnsOriginalElement() + { + // Arrange + var encryptor = new NullXmlEncryptor(); + + // Act + var retVal = encryptor.Encrypt(XElement.Parse("")); + + // Assert + Assert.Equal(typeof(NullXmlDecryptor), retVal.DecryptorType); + XmlAssert.Equal("", retVal.EncryptedElement); + } + } +} diff --git a/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/XmlEncryptionExtensionsTests.cs b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/XmlEncryptionExtensionsTests.cs new file mode 100644 index 0000000000..bf3c455b5a --- /dev/null +++ b/src/DataProtection/test/Microsoft.AspNetCore.DataProtection.Test/XmlEncryption/XmlEncryptionExtensionsTests.cs @@ -0,0 +1,235 @@ +// 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 System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.Internal; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Xunit; + +namespace Microsoft.AspNetCore.DataProtection.XmlEncryption +{ + public class XmlEncryptionExtensionsTests + { + [Fact] + public void DecryptElement_NothingToDecrypt_ReturnsOriginalElement() + { + // Arrange + var original = XElement.Parse(@""); + + // Act + var retVal = original.DecryptElement(activator: null); + + // Assert + Assert.Same(original, retVal); + XmlAssert.Equal("", original); // unmutated + } + + [Fact] + public void DecryptElement_RootNodeRequiresDecryption_Success() + { + // Arrange + var original = XElement.Parse(@" + + + "); + + var mockActivator = new Mock(); + mockActivator.ReturnDecryptedElementGivenDecryptorTypeNameAndInput("theDecryptor", "", ""); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(mockActivator.Object); + var services = serviceCollection.BuildServiceProvider(); + var activator = services.GetActivator(); + + // Act + var retVal = original.DecryptElement(activator); + + // Assert + XmlAssert.Equal("", retVal); + } + + [Fact] + public void DecryptElement_MultipleNodesRequireDecryption_AvoidsRecursion_Success() + { + // Arrange + var original = XElement.Parse(@" + + + + + + + + + + + "); + + var expected = @" + + + nested + + + + + nested + + + "; + + var mockDecryptor = new Mock(); + mockDecryptor + .Setup(o => o.Decrypt(It.IsAny())) + .Returns(el => new XElement(el.Name.LocalName + "_decrypted", new XElement(XmlConstants.EncryptedSecretElementName, "nested"))); + + var mockActivator = new Mock(); + mockActivator.Setup(o => o.CreateInstance(typeof(IXmlDecryptor), "myDecryptor")).Returns(mockDecryptor.Object); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(mockActivator.Object); + var services = serviceCollection.BuildServiceProvider(); + var activator = services.GetActivator(); + + // Act + var retVal = original.DecryptElement(activator); + + // Assert + XmlAssert.Equal(expected, retVal); + } + + [Fact] + public void EncryptIfNecessary_NothingToEncrypt_ReturnsNull() + { + // Arrange + var original = XElement.Parse(@""); + var xmlEncryptor = new Mock(MockBehavior.Strict).Object; + + // Act + var retVal = xmlEncryptor.EncryptIfNecessary(original); + + // Assert + Assert.Null(retVal); + XmlAssert.Equal("", original); // unmutated + } + + [Fact] + public void EncryptIfNecessary_RootNodeRequiresEncryption_Success() + { + // Arrange + var original = XElement.Parse(@""); + var mockXmlEncryptor = new Mock(); + mockXmlEncryptor.Setup(o => o.Encrypt(It.IsAny())).Returns(new EncryptedXmlInfo(new XElement("theElement"), typeof(MyXmlDecryptor))); + + // Act + var retVal = mockXmlEncryptor.Object.EncryptIfNecessary(original); + + // Assert + XmlAssert.Equal(@"", original); // unmutated + Assert.Equal(XmlConstants.EncryptedSecretElementName, retVal.Name); + Assert.Equal(typeof(MyXmlDecryptor).AssemblyQualifiedName, (string)retVal.Attribute(XmlConstants.DecryptorTypeAttributeName)); + XmlAssert.Equal("", retVal.Descendants().Single()); + } + + [Fact] + public void EncryptIfNecessary_MultipleNodesRequireEncryption_Success() + { + // Arrange + var original = XElement.Parse(@" + + + + + + + + + + + "); + + var expected = string.Format(@" + + + + + + + + + + + ", + typeof(MyXmlDecryptor).AssemblyQualifiedName); + + var mockXmlEncryptor = new Mock(); + mockXmlEncryptor + .Setup(o => o.Encrypt(It.IsAny())) + .Returns(element => new EncryptedXmlInfo(new XElement(element.Name.LocalName + "_encrypted"), typeof(MyXmlDecryptor))); + + // Act + var retVal = mockXmlEncryptor.Object.EncryptIfNecessary(original); + + // Assert + XmlAssert.Equal(expected, retVal); + } + + [Fact] + public void EncryptIfNecessary_NullEncryptorWithRecursion_NoStackDive_Success() + { + // Arrange + var original = XElement.Parse(@" + + + + + + + + + + + "); + + var expected = string.Format(@" + + + + + + + + + + + + + + + ", + typeof(MyXmlDecryptor).AssemblyQualifiedName); + + var mockXmlEncryptor = new Mock(); + mockXmlEncryptor + .Setup(o => o.Encrypt(It.IsAny())) + .Returns(element => new EncryptedXmlInfo(new XElement(element), typeof(MyXmlDecryptor))); + + // Act + var retVal = mockXmlEncryptor.Object.EncryptIfNecessary(original); + + // Assert + XmlAssert.Equal(expected, retVal); + } + + private sealed class MyXmlDecryptor : IXmlDecryptor + { + public XElement Decrypt(XElement encryptedElement) + { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/DataProtection/test/shared/ConditionalRunTestOnlyWindows8OrLaterAttribute.cs b/src/DataProtection/test/shared/ConditionalRunTestOnlyWindows8OrLaterAttribute.cs new file mode 100644 index 0000000000..d5ef4730f6 --- /dev/null +++ b/src/DataProtection/test/shared/ConditionalRunTestOnlyWindows8OrLaterAttribute.cs @@ -0,0 +1,16 @@ +// 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 Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Testing.xunit; + +namespace Microsoft.AspNetCore.DataProtection.Test.Shared +{ + public class ConditionalRunTestOnlyOnWindows8OrLaterAttribute : Attribute, ITestCondition + { + public bool IsMet => OSVersionUtil.IsWindows8OrLater(); + + public string SkipReason { get; } = "Test requires Windows 8 / Windows Server 2012 or higher."; + } +} diff --git a/src/DataProtection/test/shared/ConditionalRunTestOnlyWindowsAttribute.cs b/src/DataProtection/test/shared/ConditionalRunTestOnlyWindowsAttribute.cs new file mode 100644 index 0000000000..5033b3e38e --- /dev/null +++ b/src/DataProtection/test/shared/ConditionalRunTestOnlyWindowsAttribute.cs @@ -0,0 +1,16 @@ +// 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 Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.Testing.xunit; + +namespace Microsoft.AspNetCore.DataProtection.Test.Shared +{ + public class ConditionalRunTestOnlyOnWindowsAttribute : Attribute, ITestCondition + { + public bool IsMet => OSVersionUtil.IsWindows(); + + public string SkipReason { get; } = "Test requires Windows 7 / Windows Server 2008 R2 or higher."; + } +} diff --git a/src/DataProtection/test/shared/ExceptionAssert2.cs b/src/DataProtection/test/shared/ExceptionAssert2.cs new file mode 100644 index 0000000000..ccc596b48c --- /dev/null +++ b/src/DataProtection/test/shared/ExceptionAssert2.cs @@ -0,0 +1,23 @@ +// 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.Security.Cryptography; +using Xunit; + +namespace Microsoft.AspNetCore.Testing +{ + internal static class ExceptionAssert2 + { + /// + /// Verifies that the code throws a . + /// + /// A delegate to the code to be tested + /// The that was thrown, when successful + /// Thrown when an exception was not thrown, or when an exception of the incorrect type is thrown + public static CryptographicException ThrowsCryptographicException(Action testCode) + { + return Assert.Throws(testCode); + } + } +} diff --git a/src/DataProtection/version.props b/src/DataProtection/version.props new file mode 100644 index 0000000000..71a78cddd8 --- /dev/null +++ b/src/DataProtection/version.props @@ -0,0 +1,12 @@ + + + 3.0.0 + alpha1 + $(VersionPrefix) + $(VersionPrefix)-$(VersionSuffix)-final + t000 + a- + $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) + $(VersionSuffix)-$(BuildNumber) + + diff --git a/src/Installers/Debian/build.sh b/src/Installers/Debian/build.sh new file mode 100755 index 0000000000..6bd678c8ef --- /dev/null +++ b/src/Installers/Debian/build.sh @@ -0,0 +1,272 @@ +#!/usr/bin/env bash +# +# 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. +# +set -e + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +## Load Functions ## +source $SCRIPT_DIR/scripts/debian_build_lib.sh + +## Debian Package Creation Functions ## +execute(){ + if ! parse_args_and_set_env_vars "$@"; then + exit 1 + fi + + # Exit if required validation fails + if ! validate_inputs; then + exit 1 + fi + + parse_config_and_set_env_vars + clean_or_create_build_dirs + package_all + generate_all + create_source_tarball + + # Actually Build Package Files + (cd ${PACKAGE_SOURCE_DIR}; debuild -us -uc) + + copy_files_to_output +} + +parse_args_and_set_env_vars(){ + OPTIND=1 # Reset in case getopts has been used previously in the shell. + + while getopts ":n:v:i:o:h" opt; do + case $opt in + n) + export PACKAGE_NAME="$OPTARG" + ;; + v) + export PACKAGE_VERSION="$OPTARG" + ;; + i) + export INPUT_DIR="$OPTARG" + ;; + o) + export OUTPUT_DIR="$OPTARG" + ;; + h) + print_help + return 1 + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + return 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + return 1 + ;; + esac + done + + # Special Input Directories + Paths + ABSOLUTE_PLACEMENT_DIR="${INPUT_DIR}/\$" + PACKAGE_ROOT_PLACEMENT_DIR="${INPUT_DIR}/package_root" + CONFIG="$INPUT_DIR/debian_config.json" + + return 0 +} + +print_help(){ + echo "Usage: package_tool [-i ] [-o ] + [-n ] [-v ] [-h] + + REQUIRED: + -i : Input directory conforming to package_tool conventions and debian_config.json + -o : Output directory for debian package and other artifacts + + OPTIONAL: + -n : name of created package, will override value in debian_config.json + -v : version of created package, will override value in debian_config.json + -h: Show this message + + NOTES: + See Readme for more information on package_tool conventions and debian_config.json format + https://github.com/dotnet/cli/tree/master/packaging/debian/package_tool + " +} + +validate_inputs(){ + local ret=0 + if [[ -z "$INPUT_DIR" ]]; then + echo "ERROR: -i Not Specified" + ret=1 + fi + + if [[ -z "$OUTPUT_DIR" ]]; then + echo "ERROR: -o Not Specified." + ret=1 + fi + + if [[ ! -d "$PACKAGE_ROOT_PLACEMENT_DIR" ]]; then + echo "ERROR: package_root directory does not exist" + echo $PACKAGE_ROOT_PLACEMENT_DIR + ret=1 + fi + + if [[ ! -f "$CONFIG" ]]; then + echo "ERROR: debian_config.json file does not exist" + echo $CONFIG + ret=1 + fi + + return $ret +} + +parse_config_and_set_env_vars(){ + extract_base_cmd="python $SCRIPT_DIR/scripts/extract_json_value.py" + + # Arguments Take Precedence over Config + [ -z "$PACKAGE_VERSION" ] && PACKAGE_VERSION="$($extract_base_cmd $CONFIG "release.package_version")" + [ -z "$PACKAGE_NAME" ] && PACKAGE_NAME="$($extract_base_cmd $CONFIG "package_name")" + + # Inputs + INPUT_SAMPLES_DIR="$INPUT_DIR/samples" + INPUT_DOCS_DIR="$INPUT_DIR/docs" + DOCS_JSON_PATH="$INPUT_DIR/docs.json" + + PACKAGE_SOURCE_DIR="${OUTPUT_DIR}/${PACKAGE_NAME}-${PACKAGE_VERSION}" + + if ! INSTALL_ROOT="$($extract_base_cmd $CONFIG "install_root")"; then + INSTALL_ROOT="/usr/share/$PACKAGE_NAME" + fi + + DEBIAN_DIR="${PACKAGE_SOURCE_DIR}/debian" + DOCS_DIR="${PACKAGE_SOURCE_DIR}/docs" +} + +clean_or_create_build_dirs(){ + rm -rf ${PACKAGE_SOURCE_DIR} + mkdir -p $DEBIAN_DIR +} + +package_all(){ + package_static_files + package_package_root_placement + package_absolute_placement + package_samples + package_docs + package_install_scripts +} + +generate_all(){ + generate_config_templates + generate_manpages + generate_manpage_manifest + generate_sample_manifest + write_debian_install_file +} + +create_source_tarball(){ + rm -f ${OUTPUT_DIR}/${PACKAGE_NAME}_${PACKAGE_VERSION}.orig.tar.gz + tar -cvzf ${OUTPUT_DIR}/${PACKAGE_NAME}_${PACKAGE_VERSION}.orig.tar.gz -C $PACKAGE_SOURCE_DIR . +} + +copy_files_to_output(){ + # .deb, .dsc, etc.. Already in output dir + # Copy Test files + + cp $SCRIPT_DIR/test/integration_tests/test_package.bats $OUTPUT_DIR +} + +## Packaging Functions ## +package_static_files(){ + cp -a $SCRIPT_DIR/package_files/debian/* ${PACKAGE_SOURCE_DIR}/debian +} + +package_package_root_placement(){ + add_dir_to_install ${PACKAGE_ROOT_PLACEMENT_DIR} "" +} + +package_absolute_placement(){ + if [[ -d "$ABSOLUTE_PLACEMENT_DIR" ]]; then + abs_in_package_dir="\$" + + add_dir_to_install ${ABSOLUTE_PLACEMENT_DIR} $abs_in_package_dir + + # Get List of all files in directory tree, relative to ABSOLUTE_PLACEMENT_DIR + abs_files=( $(_get_files_in_dir_tree $ABSOLUTE_PLACEMENT_DIR) ) + + # For each file add a a system placement + for abs_file in ${abs_files[@]} + do + parent_dir=$(dirname $abs_file) + filename=$(basename $abs_file) + + add_system_file_placement "$abs_in_package_dir/$abs_file" "/$parent_dir" + done + fi +} + +package_samples(){ + if [[ -d "$INPUT_SAMPLES_DIR" ]]; then + cp -a $INPUT_SAMPLES_DIR/. $PACKAGE_SOURCE_DIR + fi +} + +package_docs(){ + if [[ -d "$INPUT_DOCS_DIR" ]]; then + mkdir -p $DOCS_DIR + cp -a $INPUT_DOCS_DIR/. $DOCS_DIR + fi +} + +package_install_scripts(){ + # copy scripts for the package's control section like preinst, postint, etc + if [[ -d "$INPUT_DIR/debian" ]]; then + cp -a "$INPUT_DIR/debian/." $DEBIAN_DIR + fi +} + +## Generation Functions ## +generate_config_templates(){ + python ${SCRIPT_DIR}/scripts/config_template_generator.py $CONFIG $SCRIPT_DIR/templates/debian $DEBIAN_DIR $PACKAGE_NAME $PACKAGE_VERSION +} + +generate_manpages(){ + if [[ -f "$DOCS_JSON_PATH" ]]; then + mkdir -p $DOCS_DIR + + # Generate the manpages from json spec + python ${SCRIPT_DIR}/scripts/manpage_generator.py ${DOCS_JSON_PATH} ${DOCS_DIR} + fi +} + +generate_manpage_manifest(){ + # Get a list of files generated relative to $DOCS_DIR + generated_manpages=( $(_get_files_in_dir_tree $DOCS_DIR) ) + + # Get path relative to $PACKAGE_SOURCE_DIR to prepend to each filename + # This syntax is bash substring removal + docs_rel_path=${DOCS_DIR#${PACKAGE_SOURCE_DIR}/} + + # Remove any existing manifest + rm -f ${DEBIAN_DIR}/${PACKAGE_NAME}.manpages + + for manpage in ${generated_manpages[@]} + do + echo "${docs_rel_path}/${manpage}" >> "${DEBIAN_DIR}/${PACKAGE_NAME}.manpages" + done +} + +generate_sample_manifest(){ + if [[ -d "$INPUT_SAMPLES_DIR" ]]; then + generated_manpages=( $(_get_files_in_dir_tree $INPUT_SAMPLES_DIR) ) + + rm -f sample_manifest + for sample in ${samples[@]} + do + echo "$sample" >> "${DEBIAN_DIR}/${PACKAGE_NAME}.examples" + done + else + echo "Provide a 'samples' directory in INPUT_DIR to package samples" + fi +} + +execute "$@" diff --git a/src/Installers/Debian/package_files/debian/compat b/src/Installers/Debian/package_files/debian/compat new file mode 100755 index 0000000000..ec635144f6 --- /dev/null +++ b/src/Installers/Debian/package_files/debian/compat @@ -0,0 +1 @@ +9 diff --git a/src/Installers/Debian/package_files/debian/source/format b/src/Installers/Debian/package_files/debian/source/format new file mode 100755 index 0000000000..163aaf8d82 --- /dev/null +++ b/src/Installers/Debian/package_files/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/src/Installers/Debian/scripts/config_template_generator.py b/src/Installers/Debian/scripts/config_template_generator.py new file mode 100755 index 0000000000..86f19df461 --- /dev/null +++ b/src/Installers/Debian/scripts/config_template_generator.py @@ -0,0 +1,267 @@ +#!/usr/bin/python +# +# 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. +# + +# Parses debian_config.json and generates appropriate templates +# Where optional defaults exist, they are defined in the template_dict +# of the appropriate generation function + +import os +import sys +import json +import datetime + +FILE_CHANGELOG = 'changelog' +FILE_CONTROL = 'control' +FILE_COPYRIGHT = 'copyright' +FILE_SYMLINK_FORMAT = '{package_name}.links' +FILE_RULES = 'rules' + +PACKAGE_ROOT_FORMAT = "usr/share/{package_name}" +CHANGELOG_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S %z" + +# UTC Timezone for Changelog date +class UTC(datetime.tzinfo): + def utcoffset(self, dt): + return datetime.timedelta(0) + + def tzname(self, dt): + return "UTC" + + def dst(self, dt): + return datetime.timedelta(0) + +# Generation Functions +def generate_and_write_all(config_data, template_dir, output_dir, package_name=None, package_version=None): + try: + changelog_contents = generate_changelog( + config_data, + template_dir, + package_name=package_name, + package_version=package_version) + + control_contents = generate_control(config_data, template_dir, package_name=package_name) + copyright_contents = generate_copyright(config_data, template_dir) + symlink_contents = generate_symlinks(config_data, package_name=package_name) + rules_contents = generate_rules(config_data, template_dir) + except Exception as exc: + print exc + help_and_exit("Error: Generation Failed, check your config file.") + + write_file(changelog_contents, output_dir, FILE_CHANGELOG) + write_file(control_contents, output_dir, FILE_CONTROL) + write_file(copyright_contents, output_dir, FILE_COPYRIGHT) + write_file(rules_contents, output_dir, FILE_RULES) + + # Symlink File is optional + if symlink_contents: + symlink_filename = get_symlink_filename(config_data, package_name=package_name) + write_file(symlink_contents, output_dir, symlink_filename) + + return + +def generate_rules(config_data, template_dir): + template = get_template(template_dir, FILE_RULES) + + ignored_dependency_packages = config_data.get("debian_ignored_dependencies", None) + override_text = "" + + if ignored_dependency_packages != None: + override_text = "override_dh_shlibdeps:\n\tdh_shlibdeps --dpkg-shlibdeps-params=\"" + + for package in ignored_dependency_packages: + override_text += "-x{0} ".format(package) + + override_text += "\"" + + return template.format(overrides=override_text) + +def generate_changelog(config_data, template_dir, package_version=None, package_name=None): + template = get_template(template_dir, FILE_CHANGELOG) + + release_data = config_data["release"] + + # Allow for Version Override + config_package_version = release_data["package_version"] + package_version = package_version or config_package_version + + template_dict = dict(\ + PACKAGE_VERSION=package_version, + PACKAGE_REVISION=release_data["package_revision"], + CHANGELOG_MESSAGE=release_data["changelog_message"], + URGENCY=release_data.get("urgency", "low"), + + PACKAGE_NAME=package_name or config_data["package_name"], + MAINTAINER_NAME=config_data["maintainer_name"], + MAINTAINER_EMAIL=config_data["maintainer_email"], + DATE=datetime.datetime.now(UTC()).strftime(CHANGELOG_DATE_FORMAT) + ) + + contents = template.format(**template_dict) + + return contents + +def generate_control(config_data, template_dir, package_name=None): + template = get_template(template_dir, FILE_CONTROL) + + dependency_data = config_data.get("debian_dependencies", None) + dependency_str = get_dependendent_packages_string(dependency_data) + + conflict_data = config_data.get("package_conflicts", []) + conflict_str = ', '.join(conflict_data) + + # Default to empty dict, so we don't explode on nested optional values + control_data = config_data.get("control", dict()) + + template_dict = dict(\ + SHORT_DESCRIPTION=config_data["short_description"], + LONG_DESCRIPTION=config_data["long_description"], + HOMEPAGE=config_data.get("homepage", ""), + + SECTION=control_data.get("section", "misc"), + PRIORITY=control_data.get("priority", "low"), + ARCH=control_data.get("architecture", "all"), + + DEPENDENT_PACKAGES=dependency_str, + CONFLICT_PACKAGES=conflict_str, + + PACKAGE_NAME=package_name or config_data["package_name"], + MAINTAINER_NAME=config_data["maintainer_name"], + MAINTAINER_EMAIL=config_data["maintainer_email"] + ) + + contents = template.format(**template_dict) + + return contents + +def generate_copyright(config_data, template_dir): + template = get_template(template_dir, FILE_COPYRIGHT) + + license_data = config_data["license"] + + template_dict = dict(\ + COPYRIGHT_TEXT=config_data["copyright"], + LICENSE_NAME=license_data["type"], + LICENSE_TEXT=license_data["full_text"] + ) + + contents = template.format(**template_dict) + + return contents + +def generate_symlinks(config_data, package_name=None): + symlink_entries = [] + package_root_path = get_package_root(config_data, package_name=package_name) + + symlink_data = config_data.get("symlinks", dict()) + + for package_rel_path, symlink_path in symlink_data.iteritems(): + + package_abs_path = os.path.join(package_root_path, package_rel_path) + + symlink_entries.append( '%s %s' % (package_abs_path, symlink_path) ) + + return '\n'.join(symlink_entries) + +# Helper Functions +def get_package_root(config_data, package_name=None): + config_install_root = config_data.get("install_root", None) + package_name = package_name or config_data["package_name"] + + return config_install_root or PACKAGE_ROOT_FORMAT.format(package_name=package_name) + +def get_symlink_filename(config_data, package_name=None): + package_name = package_name or config_data["package_name"] + return FILE_SYMLINK_FORMAT.format(package_name=package_name) + +def get_dependendent_packages_string(debian_dependency_data): + if debian_dependency_data is None: + return "" + + dependencies = [] + + for debian_package_name in debian_dependency_data: + dep_str = debian_package_name + + if debian_dependency_data[debian_package_name].get("package_version", None): + debian_package_version = debian_dependency_data[debian_package_name].get("package_version") + + dep_str += " (>= %s)" % debian_package_version + + dependencies.append(dep_str) + + # Leading Comma is important here + return ', ' + ', '.join(dependencies) + + +def load_json(json_path): + json_data = None + with open(json_path, 'r') as json_file: + json_data = json.load(json_file) + + return json_data + +def get_template(template_dir, name): + path = os.path.join(template_dir, name) + template_contents = None + + with open(path, 'r') as template_file: + template_contents = template_file.read() + + return template_contents + +def write_file(contents, output_dir, name): + path = os.path.join(output_dir, name) + + with open(path, 'w') as out_file: + out_file.write(contents) + + return + +# Tool Functions +def help_and_exit(msg): + print msg + sys.exit(1) + +def print_usage(): + print "Usage: config_template_generator.py [config file path] [template directory path] [output directory] (package name) (package version)" + +def parse_and_validate_args(): + if len(sys.argv) < 4: + print_usage() + help_and_exit("Error: Invalid Arguments") + + config_path = sys.argv[1] + template_dir = sys.argv[2] + output_dir = sys.argv[3] + name_override = None + version_override = None + + if len(sys.argv) >= 5: + name_override = sys.argv[4] + + if len(sys.argv) >= 6: + version_override = sys.argv[5] + + if not os.path.isfile(config_path): + help_and_exit("Error: Invalid config file path") + + if not os.path.isdir(template_dir): + help_and_exit("Error: Invalid template directory path") + + if not os.path.isdir(output_dir): + help_and_exit("Error: Invalid output directory path") + + return (config_path, template_dir, output_dir, name_override, version_override) + +def execute(): + config_path, template_dir, output_dir, name_override, version_override = parse_and_validate_args() + + config_data = load_json(config_path) + + generate_and_write_all(config_data, template_dir, output_dir, package_name = name_override, package_version=version_override) + +if __name__ == "__main__": + execute() diff --git a/src/Installers/Debian/scripts/debian_build_lib.sh b/src/Installers/Debian/scripts/debian_build_lib.sh new file mode 100755 index 0000000000..8aa53420f9 --- /dev/null +++ b/src/Installers/Debian/scripts/debian_build_lib.sh @@ -0,0 +1,170 @@ +# +# 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. +# + +# This file is not intended to be executed directly +# Import these functions using source +# +# Relies on these environment variables: +# PACKAGE_SOURCE_DIR :: Package Source Staging Directory +# INSTALL_ROOT :: Absolute path of package installation root + +# write_debian_install_file +# Summary: Writes the contents of the "install_placement" array to the debian/install +# This array is populated by calls to the "add_system_file_placement" function +# Usage: write_debian_install_file +write_debian_install_file(){ + # Remove any existing install file, we need to overwrite it + rm -f ${PACKAGE_SOURCE_DIR}/debian/install + + for i in "${install_placement[@]}" + do + echo "${i}" >> "${PACKAGE_SOURCE_DIR}/debian/install" + done +} + +# add_system_file_placement +# Summary: Registers a file placement on the filesystem from the package by populating the "install_placement" array +# Usage: add_system_file_placement {local path of file in package} {absolute path of directory to place file in} +add_system_file_placement(){ + #Initialize placement_index variable + if [[ -z "$placement_index" ]]; then + placement_index=0 + fi + + install_placement[${placement_index}]="${1} ${2}" + placement_index=$((${placement_index}+1)) +} + +# add_system_dir_placement +# Summary: Registers a directory placement on the post-installation package from an in-package path +add_system_dir_placement(){ + + in_package_dir=$1 + abs_installation_dir=$2 + + dir_files=( $(_get_files_in_dir_tree $PACKAGE_SOURCE_DIR/$in_package_dir) ) + + # If in_package_dir isn't empty include a slash + if [ ! -z "$in_package_dir" ]; then + in_package_dir="${in_package_dir}/" + fi + + for rel_filepath in ${dir_files[@]} + do + local parent_path=$(dirname $rel_filepath) + + # If there is no parent, parent_path = "." + if [[ "$parent_path" == "." ]]; then + add_system_file_placement "${in_package_dir}${rel_filepath}" "${abs_installation_dir}" + else + add_system_file_placement "${in_package_dir}${rel_filepath}" "${abs_installation_dir}/${parent_path}" + fi + + done +} + +# add_file_to_install +# Summary: Adds a file from the local filesystem to the package and installs it rooted at INSTALL_ROOT +# Usage: add_install_file {relative path to local file} {relative path to INSTALL_ROOT to place file} +add_file_to_install(){ + copy_from_file=$1 + rel_install_path=$2 + + local filename=$(basename $copy_from_file) + local parent_dir=$(dirname $copy_from_file) + + # Create Relative Copy From Path + rel_copy_from_file=${copy_from_file#$parent_dir/} + + # Delete any existing file and ensure path exists + rm -f ./${PACKAGE_SOURCE_DIR}/${rel_install_path}/${filename} + mkdir -p ./${PACKAGE_SOURCE_DIR}/${rel_install_path} + + dir_files=( "$rel_copy_from_file" ) + + _copy_files_to_package $parent_dir $rel_install_path "${dir_files[@]}" + + add_system_file_placement "${rel_install_path}/${filename}" "${INSTALL_ROOT}/$rel_install_path" +} + +# add_dir_to_install +# Summary: Adds contents of a directory on the local filesystem to the package and installs them rooted at INSTALL_ROOT +# Note: Does not install the directory passed, only its contents +# Usage: add_dir_to_install {relative path of directory to copy} {relative path to INSTALL_ROOT to place directory tree} +add_dir_to_install(){ + + copy_from_dir=$1 + rel_install_path=$2 + + # Delete and Create any existing directory + mkdir -p ${PACKAGE_SOURCE_DIR}/${rel_install_path} + + dir_files=( $(_get_files_in_dir_tree $copy_from_dir) ) + + _copy_files_to_package "$copy_from_dir" "$rel_install_path" "${dir_files[@]}" + + for file in "${dir_files[@]}" + do + file_rel_dir="$(dirname $file)" + add_system_file_placement "${rel_install_path}/${file}" "${INSTALL_ROOT}/$rel_install_path/${file_rel_dir}" + done +} + +# Usage: _copy_files_to_package {local files root directory} {relative directory in package to copy to} "${filepath_array[@]}" +# Note: The specific syntax on the parameter shows how to pass an array +_copy_files_to_package(){ + local_root_dir=$1 + package_dest_dir=$2 + + # Consume the remaining input as an array + shift; shift; + rel_filepath_list=( $@ ) + + for rel_filepath in ${rel_filepath_list[@]} + do + local parent_dir=$(dirname $rel_filepath) + local filename=$(basename $rel_filepath) + + mkdir -p ${PACKAGE_SOURCE_DIR}/${package_dest_dir}/${parent_dir} + + # Ignore $parent_dir if it there isn't one + if [[ "$parent_dir" == "." ]]; then + cp "${local_root_dir}/${rel_filepath}" "${PACKAGE_SOURCE_DIR}/${package_dest_dir}" + else + cp "${local_root_dir}/${rel_filepath}" "${PACKAGE_SOURCE_DIR}/${package_dest_dir}/${parent_dir}" + fi + + done +} + +# Usage: _get_files_in_dir_tree {path of directory} +_get_files_in_dir_tree(){ + + root_dir=$1 + + # Use Globstar expansion to enumerate all directories and files in the tree + shopt -s globstar + shopt -s dotglob + dir_tree_list=( "${root_dir}/"** ) + + # Build a new array with only the Files contained in $dir_tree_list + local index=0 + for file_path in "${dir_tree_list[@]}" + do + if [ -f $file_path ]; then + dir_tree_file_list[${index}]=$file_path + index=$(($index+1)) + fi + done + + # Remove $root_dir prefix from each path in dir_tree_file_list + # This is confusing syntax, so here's a reference link (Substring Removal) + # http://wiki.bash-hackers.org/syntax/pe + dir_tree_file_list=( "${dir_tree_file_list[@]#${root_dir}/}" ) + + # Echo is the return mechanism + echo "${dir_tree_file_list[@]}" +} + diff --git a/src/Installers/Debian/scripts/extract_json_value.py b/src/Installers/Debian/scripts/extract_json_value.py new file mode 100755 index 0000000000..c7d290bf1f --- /dev/null +++ b/src/Installers/Debian/scripts/extract_json_value.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# +# 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. +# + +# Extract Json Value +# +# Very simple tool to ease extracting json values from the cmd line. +import os +import sys +import json + +def print_usage(): + print """ + Usage: extract_json_value.py [json file path] [key of value to extract] + For nested keys, use . separator + """ + +def help_and_exit(msg=None): + print msg + print_usage() + sys.exit(1) + +def parse_and_validate_args(): + + if len(sys.argv) < 3: + help_and_exit(msg="Error: Invalid Args") + + json_path = sys.argv[1] + json_key = sys.argv[2] + + if not os.path.isfile(json_path): + help_and_exit("Error: Invalid json file path") + + return json_path, json_key + +def extract_key(json_path, json_key): + json_data = None + + with open(json_path, 'r') as json_file: + json_data = json.load(json_file) + + nested_keys = json_key.split('.') + json_context = json_data + + for key in nested_keys: + json_context = json_context.get(key, None) + + if json_context is None: + help_and_exit("Error: Invalid json key") + + return str(json_context) + +def execute(): + json_path, json_key = parse_and_validate_args() + + value = extract_key(json_path, json_key) + + return value + +if __name__ == "__main__": + print execute() + diff --git a/src/Installers/Debian/scripts/manpage_generator.py b/src/Installers/Debian/scripts/manpage_generator.py new file mode 100755 index 0000000000..3ba7afb8a6 --- /dev/null +++ b/src/Installers/Debian/scripts/manpage_generator.py @@ -0,0 +1,303 @@ +#!/usr/bin/python +# +# 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. +# + +# manpage_generator +# Converts top level docs.json format command info to +# nroff manpage format. Done in python for easy json parsing. +# +# Usage: argv[1] = path to docs.json; argv[2] = output path + +import sys +import os +import json +import datetime + +SECTION_SEPARATOR = "\n.P \n" +MANPAGE_EXTENSION = ".1" + +# For now this is a magic number +# See https://www.debian.org/doc/manuals/maint-guide/dother.en.html#manpage +SECTION_NUMBER = 1 + +def generate_man_pages(doc_path, output_dir): + + with open(doc_path) as doc_file: + doc_json = None + try: + doc_json = json.load(doc_file) + except: + raise Exception("Failed to load json file. Check formatting.") + + tools = doc_json.get("tools", None) + + if tools is None: + raise Exception("No tool sections in doc.json") + + for tool_name in tools: + tool_data = tools[tool_name] + + man_page_content = generate_man_page(tool_name, tool_data) + man_page_path = get_output_path(tool_name, output_dir) + + write_man_page(man_page_path, man_page_content) + +def get_output_path(toolname, output_dir): + out_filename = toolname + MANPAGE_EXTENSION + + return os.path.join(output_dir, out_filename) + +def write_man_page(path, content): + with open(path, 'w') as man_file: + man_file.write(content) + + #Build Fails without a final newline + man_file.write('\n') + +def generate_man_page(tool_name, tool_data): + + sections = [ + generate_header_section(tool_name, tool_data), + generate_name_section(tool_name, tool_data), + generate_synopsis_section(tool_name, tool_data), + generate_description_section(tool_name, tool_data), + generate_options_section(tool_name, tool_data), + generate_author_section(tool_name, tool_data), + generate_copyright_section(tool_name, tool_data) + ] + + return SECTION_SEPARATOR.join(sections) + +def generate_header_section(tool_name, tool_data):# + roff_text_builder = [] + + header_format = ".TH {program_name} {section_number} {center_footer} {left_footer} {center_header}" + + today = datetime.date.today() + today_string = today.strftime("%B %d, %Y") + + format_args = { + "program_name" : tool_name, + "section_number" : SECTION_NUMBER, + "center_footer" : "", # Omitted + "left_footer" : "", # Omitted + "center_header" : "" # Omitted + } + + roff_text_builder.append(header_format.format(**format_args)) + + return SECTION_SEPARATOR.join(roff_text_builder) + +def generate_name_section(tool_name, tool_data):# + roff_text_builder = [] + roff_text_builder.append(".SH NAME") + + tool_short_description = tool_data.get("short_description", "") + name_format = ".B {program_name} - {short_description}" + + name_format_args = { + "program_name": tool_name, + "short_description" : tool_short_description + } + + roff_text_builder.append(name_format.format(**name_format_args)) + + return SECTION_SEPARATOR.join(roff_text_builder) + +def generate_synopsis_section(tool_name, tool_data):# + roff_text_builder = [] + roff_text_builder.append(".SH SYNOPSIS") + + synopsis_format = '.B {program_name} {command_name} \n.RI {options} " "\n.I "{argument_list_name}"' + + tool_commands = tool_data.get("commands", []) + for command_name in tool_commands: + command_data = tool_commands[command_name] + + # Default options to empty list so the loop doesn't blow up + options = command_data.get("options", []) + argument_list = command_data.get("argumentlist", None) + + # Construct Option Strings + option_string_list = [] + argument_list_name = "" + + for option_name in options: + option_data = options[option_name] + + specifier_short = option_data.get("short", None) + specifier_long = option_data.get("long", None) + parameter = option_data.get("parameter", None) + + option_string = _option_string_helper(specifier_short, specifier_long, parameter) + + option_string_list.append(option_string) + + # Populate Argument List Name + if argument_list: + argument_list_name = argument_list.get("name", "") + + cmd_format_args = { + 'program_name' : tool_name, + 'command_name' : command_name, + 'options' : '" "'.join(option_string_list), + 'argument_list_name' : argument_list_name + } + + cmd_string = synopsis_format.format(**cmd_format_args) + + roff_text_builder.append(cmd_string) + + return SECTION_SEPARATOR.join(roff_text_builder) + +def generate_description_section(tool_name, tool_data):# + roff_text_builder = [] + roff_text_builder.append(".SH DESCRIPTION") + + # Tool Description + long_description = tool_data.get("long_description", "") + roff_text_builder.append(".PP {0}".format(long_description)) + + # Command Descriptions + cmd_description_format = ".B {program_name} {command_name}\n{command_description}" + + tool_commands = tool_data.get("commands", []) + for command_name in tool_commands: + command_data = tool_commands[command_name] + + command_description = command_data.get("description", "") + + format_args = { + "program_name" : tool_name, + "command_name" : command_name, + "command_description" : command_description + } + + cmd_string = cmd_description_format.format(**format_args) + + roff_text_builder.append(cmd_string) + + return SECTION_SEPARATOR.join(roff_text_builder) + +def generate_options_section(tool_name, tool_data):# + roff_text_builder = [] + roff_text_builder.append(".SH OPTIONS") + + options_format = '.TP\n.B {option_specifiers}\n{option_description}' + + tool_commands = tool_data.get("commands", []) + for command_name in tool_commands: + command_data = tool_commands[command_name] + + # Default to empty list so the loop doesn't blow up + options = command_data.get("options", []) + + for option_name in options: + option_data = options[option_name] + + specifier_short = option_data.get("short", None) + specifier_long = option_data.get("long", None) + parameter = option_data.get("parameter", None) + description = option_data.get("description", "") + + option_specifiers_string = _option_string_helper(specifier_short, + specifier_long, + parameter, + include_brackets = False, + delimiter=' ", " ') + + format_args = { + "option_specifiers": option_specifiers_string, + "option_description" : description + } + + roff_text_builder.append(options_format.format(**format_args)) + + return SECTION_SEPARATOR.join(roff_text_builder) + +def generate_author_section(tool_name, tool_data):# + roff_text_builder = [] + roff_text_builder.append(".SH AUTHOR") + + author_format = '.B "{author_name}" " " \n.RI ( "{author_email}" )' + + author_name = tool_data.get("author", "") + author_email = tool_data.get("author_email", "") + + format_args = { + "author_name" : author_name, + "author_email" : author_email + } + + roff_text_builder.append(author_format.format(**format_args)) + + return SECTION_SEPARATOR.join(roff_text_builder) + +def generate_copyright_section(tool_name, tool_data):# + roff_text_builder = [] + roff_text_builder.append(".SH COPYRIGHT") + + copyright_data = tool_data.get("copyright") + + roff_text_builder.append('.B "{0}"'.format(copyright_data)) + + return SECTION_SEPARATOR.join(roff_text_builder) + +def _option_string_helper(specifier_short, specifier_long, parameter, include_brackets = True, delimiter = " | "): + option_string = "" + + if include_brackets: + option_string = " [ " + + if specifier_short: + option_string += ' "{0}" '.format(specifier_short) + + if specifier_short and specifier_long: + option_string += delimiter + + if specifier_long: + option_string += ' "{0}" '.format(specifier_long) + + if parameter: + option_string += ' " " ' + option_string += ' "{0}" '.format(parameter) + + if include_brackets: + option_string += " ] " + + return option_string + + +def print_usage(): + print "Usage: argv[1] = path to docs.json; argv[2] = output path" + print "Example: manpage_generator.py ../docs.json ./dotnet-1.0/debian" + +def parse_args(): + doc_path = sys.argv[1] + output_dir = sys.argv[2] + + return (doc_path, output_dir) + +def validate_args(doc_path, output_dir): + if not os.path.isfile(doc_path): + raise Exception("Docs.json path is not valid.") + + if not os.path.isdir(output_dir): + raise Exception("Output Directory Path is not valid.") + +def execute_command_line(): + try: + doc_path, output_dir = parse_args() + + validate_args(doc_path, output_dir) + + generate_man_pages(doc_path, output_dir) + + except Exception as exc: + print "Error: ", exc + print_usage() + +if __name__ == "__main__": + execute_command_line() diff --git a/src/Installers/Debian/setup/build_setup.sh b/src/Installers/Debian/setup/build_setup.sh new file mode 100755 index 0000000000..269aff50ef --- /dev/null +++ b/src/Installers/Debian/setup/build_setup.sh @@ -0,0 +1,20 @@ +# +# 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. +# + +install_dependencies(){ + # Add LLdb 3.6 package source + echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.6 main" | tee /etc/apt/sources.list.d/llvm.list + wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | apt-key add - + + #Install Deps + apt-get update + apt-get install -y debhelper build-essential devscripts git liblttng-ust-dev lldb-3.6-dev +} + +setup(){ + install_dependencies +} + +setup \ No newline at end of file diff --git a/src/Installers/Debian/setup/test_setup.sh b/src/Installers/Debian/setup/test_setup.sh new file mode 100755 index 0000000000..47442fd603 --- /dev/null +++ b/src/Installers/Debian/setup/test_setup.sh @@ -0,0 +1,27 @@ +# +# 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. +# + +install_dependencies(){ + # Add LLdb 3.6 package source + echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.6 main" | tee /etc/apt/sources.list.d/llvm.list + wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | apt-key add - + + #Install Deps + apt-get update + apt-get install -y debhelper build-essential devscripts git liblttng-ust-dev lldb-3.6-dev +} + +install_bats(){ + git clone https://github.com/sstephenson/bats.git + cd bats + ./install.sh /usr/local +} + +setup(){ + install_dependencies + install_bats +} + +setup \ No newline at end of file diff --git a/src/Installers/Debian/templates/debian/changelog b/src/Installers/Debian/templates/debian/changelog new file mode 100755 index 0000000000..8eccaab397 --- /dev/null +++ b/src/Installers/Debian/templates/debian/changelog @@ -0,0 +1,5 @@ +{PACKAGE_NAME} ({PACKAGE_VERSION}-{PACKAGE_REVISION}) unstable; urgency={URGENCY} + + * {CHANGELOG_MESSAGE} + + -- {MAINTAINER_NAME} <{MAINTAINER_EMAIL}> {DATE} diff --git a/src/Installers/Debian/templates/debian/control b/src/Installers/Debian/templates/debian/control new file mode 100755 index 0000000000..49fb2b994a --- /dev/null +++ b/src/Installers/Debian/templates/debian/control @@ -0,0 +1,19 @@ +# +# 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. +# + +Source: {PACKAGE_NAME} +Maintainer: {MAINTAINER_NAME} <{MAINTAINER_EMAIL}> +Section: {SECTION} +Priority: {PRIORITY} +Standards-Version: 3.9.2 +Build-Depends: debhelper (>=9) +Homepage: {HOMEPAGE} + +Package: {PACKAGE_NAME} +Architecture: {ARCH} +Depends: ${{shlibs:Depends}}, ${{misc:Depends}}{DEPENDENT_PACKAGES} +Conflicts: {CONFLICT_PACKAGES} +Description: {SHORT_DESCRIPTION} + {LONG_DESCRIPTION} diff --git a/src/Installers/Debian/templates/debian/copyright b/src/Installers/Debian/templates/debian/copyright new file mode 100755 index 0000000000..1fe22df1b7 --- /dev/null +++ b/src/Installers/Debian/templates/debian/copyright @@ -0,0 +1,10 @@ +Comment: 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. + +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ + +Files: * +Copyright: {COPYRIGHT_TEXT} +License: {LICENSE_NAME} + +License: {LICENSE_NAME} + {LICENSE_TEXT} \ No newline at end of file diff --git a/src/Installers/Debian/templates/debian/rules b/src/Installers/Debian/templates/debian/rules new file mode 100755 index 0000000000..103057ac7a --- /dev/null +++ b/src/Installers/Debian/templates/debian/rules @@ -0,0 +1,11 @@ +#!/usr/bin/make -f +# +# 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. +# + +{overrides} + +%: + dh $@ + diff --git a/src/Installers/Debian/test.sh b/src/Installers/Debian/test.sh new file mode 100755 index 0000000000..9adde436f4 --- /dev/null +++ b/src/Installers/Debian/test.sh @@ -0,0 +1,41 @@ +# +# 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. +# + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +current_user=$(whoami) +if [ $current_user != "root" ]; then + echo "test.sh requires superuser privileges to run" + exit 1 +fi + +run_unit_tests(){ + bats $DIR/test/unit_tests/test_debian_build_lib.bats + bats $DIR/test/unit_tests/test_scripts.bats +} + +run_integration_tests(){ + input_dir=$DIR/test/test_assets/test_package_layout + output_dir=$DIR/bin + + # Create output dir + mkdir -p $output_dir + + # Build the actual package + $DIR/package_tool -i $input_dir -o $output_dir + + # Integration Test Entrypoint placed by package_tool + bats $output_dir/test_package.bats + + # Cleanup output dir + rm -rf $DIR/test/test_assets/test_package_output +} + +run_all(){ + run_unit_tests + run_integration_tests +} + +run_all diff --git a/src/Installers/Debian/test/integration_tests/test_package.bats b/src/Installers/Debian/test/integration_tests/test_package.bats new file mode 100755 index 0000000000..8f4c750538 --- /dev/null +++ b/src/Installers/Debian/test/integration_tests/test_package.bats @@ -0,0 +1,80 @@ +#!/bin/bash +# +# 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. +# +# This script is used to test the debian package after it's creation. +# The package tool will drop it next to the .deb file it creates. +# Environment Variables: +# LAST_VERSION_URL: Url for last version .deb (to test upgrades) [required for upgrade test] + +#Ensure running with superuser privileges +current_user=$(whoami) +if [ $current_user != "root" ]; then + echo "WARNING: test_package.bats requires superuser privileges to run, trying sudo..." + SUDO_PREFIX="sudo" +fi + +setup(){ + DIR="$BATS_TEST_DIRNAME" + + PACKAGE_FILENAME="$(ls $DIR | grep .deb -m 1)" + PACKAGE_PATH="$DIR/*.deb" + + # Get Package name from package path, + PACKAGE_NAME=${PACKAGE_FILENAME%%_*} +} + +install_package(){ + $SUDO_PREFIX dpkg -i $PACKAGE_PATH +} + +remove_package(){ + $SUDO_PREFIX dpkg -r $PACKAGE_NAME +} + +purge_package(){ + $SUDO_PREFIX dpkg -P $PACKAGE_NAME +} + +install_last_version(){ + $SUDO_PREFIX dpkg -i "$DIR/last_version.deb" +} + +download_and_install_last_version(){ + curl "$LAST_VERSION_URL" -o "$DIR/last_version.deb" + + install_last_version +} + +delete_last_version(){ + rm -f "$DIR/last_version.deb" +} + +teardown(){ + delete_last_version +} + +@test "package install + removal test" { + install_package + remove_package +} + +@test "package install + purge test" { + install_package + purge_package +} + +# Ultimate Package Test +# https://www.debian.org/doc/manuals/maint-guide/checkit.en.html#pmaintscripts +@test "package install + upgrade + purge + install + remove + install + purge test" { + if [ ! -z "$LAST_VERSION_URL" ]; then + download_and_install_last_version + install_package + purge_package + install_package + remove_package + install_package + purge_package + fi +} diff --git a/src/Installers/Debian/test/test_assets/lkgtestman.1 b/src/Installers/Debian/test/test_assets/lkgtestman.1 new file mode 100755 index 0000000000..57915b0a61 --- /dev/null +++ b/src/Installers/Debian/test/test_assets/lkgtestman.1 @@ -0,0 +1,99 @@ +.TH tool1 1 +.P +.SH NAME +.P +.B tool1 - A tool to Vestibulum lacinia arcu eget nulla. +.P +.SH SYNOPSIS +.P +.B tool1 noOptionsCommand +.RI " " +.I "argument list stuff" +.P +.B tool1 noArgumentListFullOptions +.RI [ "-t" | "--target" " " "TARGET" ] " " [ "--noshortparam" ] " " [ "-l" ] " " [ "-p" | "--noparam" ] " " [ "-n" " " "NOLONG" ] " " [ "--noshort" " " "NOSHORT" ] " " [ "-a" | "--another" " " "ANOTHER" ] " " +.I "" +.P +.B tool1 fullcommand1 +.RI [ "-t" | "--target" " " "TARGET" ] " " [ "--noshortparam" ] " " [ "-l" ] " " [ "-p" | "--noparam" ] " " [ "-n" " " "NOLONG" ] " " [ "--noshort" " " "NOSHORT" ] " " [ "-a" | "--another" " " "ANOTHER" ] " " +.I "argument list stuff" +.P +.SH DESCRIPTION +.P +.PP Tool1 is a really great Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. +.P +.B tool1 noOptionsCommand +builds a native executable from specified source files +.P +.B tool1 noArgumentListFullOptions +builds a native executable from specified source files +.P +.B tool1 fullcommand1 +builds a native executable from specified source files +.P +.SH OPTIONS +.P +.TP +.B "-t" ", " "--target" " " "TARGET" +Specifies target binary output type. EXE or DLL +.P +.TP +.B "--noshortparam" +Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra +.P +.TP +.B "-l" +Specifies noparam nolong congue elementum. Morbi in ipsum sit amet pede facilisis laoreet +.P +.TP +.B "-p" ", " "--noparam" +Specifies noparam metus vitae pharetra auctor, sem +.P +.TP +.B "-n" " " "NOLONG" +Specifies nolong Nunc feugiat mi a tellus consequat +.P +.TP +.B "--noshort" " " "NOSHORT" +Specifies noshortNam nec ante. Sed lacinia, urna non tincidunt +.P +.TP +.B "-a" ", " "--another" " " "ANOTHER" +Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra +.P +.TP +.B "-t" ", " "--target" " " "TARGET" +Specifies target binary output type. EXE or DLL +.P +.TP +.B "--noshortparam" +Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra +.P +.TP +.B "-l" +Specifies noparam nolong congue elementum. Morbi in ipsum sit amet pede facilisis laoreet +.P +.TP +.B "-p" ", " "--noparam" +Specifies noparam metus vitae pharetra auctor, sem +.P +.TP +.B "-n" " " "NOLONG" +Specifies nolong Nunc feugiat mi a tellus consequat +.P +.TP +.B "--noshort" " " "NOSHORT" +Specifies noshortNam nec ante. Sed lacinia, urna non tincidunt +.P +.TP +.B "-a" ", " "--another" " " "ANOTHER" +Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra +.P +.SH AUTHOR +.P +.B "Test Author" " " +.RI ( "testing@testing.com" ) +.P +.SH COPYRIGHT +.P +.B "This is the copyright of tool1." diff --git a/src/Installers/Debian/test/test_assets/test_package_layout/debian_config.json b/src/Installers/Debian/test/test_assets/test_package_layout/debian_config.json new file mode 100755 index 0000000000..db873c7162 --- /dev/null +++ b/src/Installers/Debian/test/test_assets/test_package_layout/debian_config.json @@ -0,0 +1,40 @@ +{ + "maintainer_name":"Microsoft", + "maintainer_email": "optimus@service.microsoft.com", + + "package_name": "packagetooltest", + + "short_description": "This is a test package", + "long_description": "This is a longer description of the test package", + "homepage": "http://testpackage.com", + + "release":{ + "package_version":"0.1", + "package_revision":"1", + "urgency" : "low", + "changelog_message" : "some stuff here" + }, + + "control": { + "priority":"standard", + "section":"devel", + "architecture":"any" + }, + + "copyright": "2015 Microsoft", + "license": { + "type": "some_license", + "full_text": "full license text here" + }, + + "debian_dependencies" : { + "curl": { + "package_version" : "0.5.3" + }, + "python":{} + }, + + "symlinks": { + "path_relative_to_package_root/test_exe.sh" : "usr/bin/test_exe.sh" + } +} \ No newline at end of file diff --git a/src/Installers/Debian/test/test_assets/test_package_layout/docs.json b/src/Installers/Debian/test/test_assets/test_package_layout/docs.json new file mode 100755 index 0000000000..e35fdb3bfd --- /dev/null +++ b/src/Installers/Debian/test/test_assets/test_package_layout/docs.json @@ -0,0 +1,108 @@ +{ + "tools": { + "tool1": { + "copyright": "This is the copyright of tool1.", + "license" : "This is the license of tool1", + "author":"Test Author", + "author_email":"testing@testing.com", + "short_description":"A tool to Vestibulum lacinia arcu eget nulla.", + "long_description":"Tool1 is a really great Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. ", + "commands": { + "fullcommand1":{ + "description":"builds a native executable from specified source files", + "options" : { + "target": { + "short": "-t", + "long":"--target", + "description":"Specifies target binary output type. EXE or DLL", + "parameter":"TARGET" + }, + "target2": { + "short": "-a", + "long":"--another", + "description":"Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra", + "parameter":"ANOTHER" + }, + "noshort": { + "long":"--noshort", + "description":"Specifies noshortNam nec ante. Sed lacinia, urna non tincidunt", + "parameter":"NOSHORT" + }, + "nolong": { + "short": "-n", + "description":"Specifies nolong Nunc feugiat mi a tellus consequat ", + "parameter":"NOLONG" + }, + "noparam": { + "short": "-p", + "long":"--noparam", + "description":"Specifies noparam metus vitae pharetra auctor, sem" + }, + "noParamNoShort": { + "long":"--noshortparam", + "description":"Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra" + }, + "noParamNoLong": { + "short": "-l", + "description":"Specifies noparam nolong congue elementum. Morbi in ipsum sit amet pede facilisis laoreet" + } + }, + "argumentlist" : { + "name":"argument list stuff", + "description":"ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;" + } + + }, + "noOptionsCommand":{ + "description":"builds a native executable from specified source files", + "argumentlist" : { + "name":"argument list stuff", + "description":"ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;" + } + + }, + "noArgumentListFullOptions":{ + "description":"builds a native executable from specified source files", + "options" : { + "target": { + "short": "-t", + "long":"--target", + "description":"Specifies target binary output type. EXE or DLL", + "parameter":"TARGET" + }, + "target2": { + "short": "-a", + "long":"--another", + "description":"Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra", + "parameter":"ANOTHER" + }, + "noshort": { + "long":"--noshort", + "description":"Specifies noshortNam nec ante. Sed lacinia, urna non tincidunt", + "parameter":"NOSHORT" + }, + "nolong": { + "short": "-n", + "description":"Specifies nolong Nunc feugiat mi a tellus consequat ", + "parameter":"NOLONG" + }, + "noparam": { + "short": "-p", + "long":"--noparam", + "description":"Specifies noparam metus vitae pharetra auctor, sem" + }, + "noParamNoShort": { + "long":"--noshortparam", + "description":"Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra" + }, + "noParamNoLong": { + "short": "-l", + "description":"Specifies noparam nolong congue elementum. Morbi in ipsum sit amet pede facilisis laoreet" + } + } + } + } + + } + } +} diff --git a/src/Installers/Debian/test/test_assets/test_package_layout/docs/testdocs.1 b/src/Installers/Debian/test/test_assets/test_package_layout/docs/testdocs.1 new file mode 100755 index 0000000000..57915b0a61 --- /dev/null +++ b/src/Installers/Debian/test/test_assets/test_package_layout/docs/testdocs.1 @@ -0,0 +1,99 @@ +.TH tool1 1 +.P +.SH NAME +.P +.B tool1 - A tool to Vestibulum lacinia arcu eget nulla. +.P +.SH SYNOPSIS +.P +.B tool1 noOptionsCommand +.RI " " +.I "argument list stuff" +.P +.B tool1 noArgumentListFullOptions +.RI [ "-t" | "--target" " " "TARGET" ] " " [ "--noshortparam" ] " " [ "-l" ] " " [ "-p" | "--noparam" ] " " [ "-n" " " "NOLONG" ] " " [ "--noshort" " " "NOSHORT" ] " " [ "-a" | "--another" " " "ANOTHER" ] " " +.I "" +.P +.B tool1 fullcommand1 +.RI [ "-t" | "--target" " " "TARGET" ] " " [ "--noshortparam" ] " " [ "-l" ] " " [ "-p" | "--noparam" ] " " [ "-n" " " "NOLONG" ] " " [ "--noshort" " " "NOSHORT" ] " " [ "-a" | "--another" " " "ANOTHER" ] " " +.I "argument list stuff" +.P +.SH DESCRIPTION +.P +.PP Tool1 is a really great Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. +.P +.B tool1 noOptionsCommand +builds a native executable from specified source files +.P +.B tool1 noArgumentListFullOptions +builds a native executable from specified source files +.P +.B tool1 fullcommand1 +builds a native executable from specified source files +.P +.SH OPTIONS +.P +.TP +.B "-t" ", " "--target" " " "TARGET" +Specifies target binary output type. EXE or DLL +.P +.TP +.B "--noshortparam" +Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra +.P +.TP +.B "-l" +Specifies noparam nolong congue elementum. Morbi in ipsum sit amet pede facilisis laoreet +.P +.TP +.B "-p" ", " "--noparam" +Specifies noparam metus vitae pharetra auctor, sem +.P +.TP +.B "-n" " " "NOLONG" +Specifies nolong Nunc feugiat mi a tellus consequat +.P +.TP +.B "--noshort" " " "NOSHORT" +Specifies noshortNam nec ante. Sed lacinia, urna non tincidunt +.P +.TP +.B "-a" ", " "--another" " " "ANOTHER" +Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra +.P +.TP +.B "-t" ", " "--target" " " "TARGET" +Specifies target binary output type. EXE or DLL +.P +.TP +.B "--noshortparam" +Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra +.P +.TP +.B "-l" +Specifies noparam nolong congue elementum. Morbi in ipsum sit amet pede facilisis laoreet +.P +.TP +.B "-p" ", " "--noparam" +Specifies noparam metus vitae pharetra auctor, sem +.P +.TP +.B "-n" " " "NOLONG" +Specifies nolong Nunc feugiat mi a tellus consequat +.P +.TP +.B "--noshort" " " "NOSHORT" +Specifies noshortNam nec ante. Sed lacinia, urna non tincidunt +.P +.TP +.B "-a" ", " "--another" " " "ANOTHER" +Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra +.P +.SH AUTHOR +.P +.B "Test Author" " " +.RI ( "testing@testing.com" ) +.P +.SH COPYRIGHT +.P +.B "This is the copyright of tool1." diff --git a/src/Installers/Debian/test/test_assets/test_package_layout/package_root/path_relative_to_package_root/test_exe.sh b/src/Installers/Debian/test/test_assets/test_package_layout/package_root/path_relative_to_package_root/test_exe.sh new file mode 100755 index 0000000000..370bc40f3a --- /dev/null +++ b/src/Installers/Debian/test/test_assets/test_package_layout/package_root/path_relative_to_package_root/test_exe.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# +# 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. +# + +# Resolve symlinks until we have the parent dir of the actual file +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +# This is how tools should be called +exec bash $DIR/../test_called.sh diff --git a/src/Installers/Debian/test/test_assets/test_package_layout/package_root/test_called.sh b/src/Installers/Debian/test/test_assets/test_package_layout/package_root/test_called.sh new file mode 100755 index 0000000000..e14e427cf6 --- /dev/null +++ b/src/Installers/Debian/test/test_assets/test_package_layout/package_root/test_called.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# +# 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. +# + +echo "script called" diff --git a/src/Installers/Debian/test/test_assets/test_package_layout/samples/testsample.cs b/src/Installers/Debian/test/test_assets/test_package_layout/samples/testsample.cs new file mode 100755 index 0000000000..4f7432b480 --- /dev/null +++ b/src/Installers/Debian/test/test_assets/test_package_layout/samples/testsample.cs @@ -0,0 +1,12 @@ +// 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. + +using System; + +public class Program { + + public static void Main(){ + System.Console.WriteLine("Hello World"); + } + +} \ No newline at end of file diff --git a/src/Installers/Debian/test/test_assets/testdocs.json b/src/Installers/Debian/test/test_assets/testdocs.json new file mode 100755 index 0000000000..e35fdb3bfd --- /dev/null +++ b/src/Installers/Debian/test/test_assets/testdocs.json @@ -0,0 +1,108 @@ +{ + "tools": { + "tool1": { + "copyright": "This is the copyright of tool1.", + "license" : "This is the license of tool1", + "author":"Test Author", + "author_email":"testing@testing.com", + "short_description":"A tool to Vestibulum lacinia arcu eget nulla.", + "long_description":"Tool1 is a really great Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. ", + "commands": { + "fullcommand1":{ + "description":"builds a native executable from specified source files", + "options" : { + "target": { + "short": "-t", + "long":"--target", + "description":"Specifies target binary output type. EXE or DLL", + "parameter":"TARGET" + }, + "target2": { + "short": "-a", + "long":"--another", + "description":"Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra", + "parameter":"ANOTHER" + }, + "noshort": { + "long":"--noshort", + "description":"Specifies noshortNam nec ante. Sed lacinia, urna non tincidunt", + "parameter":"NOSHORT" + }, + "nolong": { + "short": "-n", + "description":"Specifies nolong Nunc feugiat mi a tellus consequat ", + "parameter":"NOLONG" + }, + "noparam": { + "short": "-p", + "long":"--noparam", + "description":"Specifies noparam metus vitae pharetra auctor, sem" + }, + "noParamNoShort": { + "long":"--noshortparam", + "description":"Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra" + }, + "noParamNoLong": { + "short": "-l", + "description":"Specifies noparam nolong congue elementum. Morbi in ipsum sit amet pede facilisis laoreet" + } + }, + "argumentlist" : { + "name":"argument list stuff", + "description":"ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;" + } + + }, + "noOptionsCommand":{ + "description":"builds a native executable from specified source files", + "argumentlist" : { + "name":"argument list stuff", + "description":"ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;" + } + + }, + "noArgumentListFullOptions":{ + "description":"builds a native executable from specified source files", + "options" : { + "target": { + "short": "-t", + "long":"--target", + "description":"Specifies target binary output type. EXE or DLL", + "parameter":"TARGET" + }, + "target2": { + "short": "-a", + "long":"--another", + "description":"Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra", + "parameter":"ANOTHER" + }, + "noshort": { + "long":"--noshort", + "description":"Specifies noshortNam nec ante. Sed lacinia, urna non tincidunt", + "parameter":"NOSHORT" + }, + "nolong": { + "short": "-n", + "description":"Specifies nolong Nunc feugiat mi a tellus consequat ", + "parameter":"NOLONG" + }, + "noparam": { + "short": "-p", + "long":"--noparam", + "description":"Specifies noparam metus vitae pharetra auctor, sem" + }, + "noParamNoShort": { + "long":"--noshortparam", + "description":"Specifies another aptent taciti sociosqu ad litora torquent per conubia nostra" + }, + "noParamNoLong": { + "short": "-l", + "description":"Specifies noparam nolong congue elementum. Morbi in ipsum sit amet pede facilisis laoreet" + } + } + } + } + + } + } +} diff --git a/src/Installers/Debian/test/unit_tests/test_debian_build_lib.bats b/src/Installers/Debian/test/unit_tests/test_debian_build_lib.bats new file mode 100755 index 0000000000..193868f835 --- /dev/null +++ b/src/Installers/Debian/test/unit_tests/test_debian_build_lib.bats @@ -0,0 +1,279 @@ +#!/usr/bin/env bats +# +# 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. +# + +# Tests for debian_build_lib.sh + +setup(){ + DIR="$BATS_TEST_DIRNAME" + PACKAGIFY_DIR="$(readlink -f $DIR/../../)" + + PACKAGE_DIR="$BATS_TMPDIR/test-package" + PACKAGE_SOURCE_DIR="$BATS_TMPDIR/test-source-package" + INSTALL_ROOT="test-install-root" + + # # Create Mock Package Directory + mkdir -p $PACKAGE_SOURCE_DIR/debian + mkdir $PACKAGE_DIR + + source $PACKAGIFY_DIR/scripts/debian_build_lib.sh + +} + +teardown(){ + # Remove Mock Package Directory + rm -r $PACKAGE_DIR + rm -r $PACKAGE_SOURCE_DIR +} + +@test "add_system_file_placement populates placement array" { + + add_system_file_placement "testfile0" "testdir0" + add_system_file_placement "testfile1" "testdir1" + + [ $placement_index -eq "2" ] + [ "${install_placement[0]}" = "testfile0 testdir0" ] + [ "${install_placement[1]}" = "testfile1 testdir1" ] +} + +@test "add_system_dir_placement adds files in dir to placement array" { + test_package_rel_dir="test-dir" + abs_test_path="/abs/test/path" + + mkdir $PACKAGE_SOURCE_DIR/$test_package_rel_dir + echo "file0 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/file0 + echo "file1 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/file1 + echo "file2 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/file2 + + add_system_dir_placement $test_package_rel_dir $abs_test_path + + rm -r $PACKAGE_SOURCE_DIR/$test_package_rel_dir + + [ "$placement_index" -eq 3 ] + [ "${install_placement[0]}" = "$test_package_rel_dir/file0 $abs_test_path" ] + [ "${install_placement[1]}" = "$test_package_rel_dir/file1 $abs_test_path" ] + [ "${install_placement[2]}" = "$test_package_rel_dir/file2 $abs_test_path" ] +} + +@test "add_system_dir_placement adds all files in subdir to placement array" { + test_package_rel_dir="test-dir" + test_package_rel_subdir="test-subdir" + abs_test_path="/abs/test/path" + + mkdir -p $PACKAGE_SOURCE_DIR/$test_package_rel_dir/$test_package_rel_subdir + echo "file0 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/$test_package_rel_subdir/file0 + echo "file1 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/$test_package_rel_subdir/file1 + echo "file2 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/$test_package_rel_subdir/file2 + + add_system_dir_placement $test_package_rel_dir $abs_test_path + + rm -r $PACKAGE_SOURCE_DIR/$test_package_rel_dir + + [ "$placement_index" -eq "3" ] + [ "${install_placement[0]}" = "$test_package_rel_dir/$test_package_rel_subdir/file0 $abs_test_path/$test_package_rel_subdir" ] + [ "${install_placement[1]}" = "$test_package_rel_dir/$test_package_rel_subdir/file1 $abs_test_path/$test_package_rel_subdir" ] + [ "${install_placement[2]}" = "$test_package_rel_dir/$test_package_rel_subdir/file2 $abs_test_path/$test_package_rel_subdir" ] +} + +@test "add_system_dir_placement adds all files in subdir and dir to placement array" { + test_package_rel_dir="test-dir" + test_package_rel_subdir="test-subdir" + abs_test_path="/abs/test/path" + + mkdir -p $PACKAGE_SOURCE_DIR/$test_package_rel_dir/$test_package_rel_subdir + echo "file0 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/file0 + echo "file1 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/file1 + echo "file2 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/file2 + echo "file3 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/$test_package_rel_subdir/file3 + echo "file4 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/$test_package_rel_subdir/file4 + echo "file5 contents" > $PACKAGE_SOURCE_DIR/$test_package_rel_dir/$test_package_rel_subdir/file5 + + add_system_dir_placement $test_package_rel_dir $abs_test_path + + rm -r $PACKAGE_SOURCE_DIR/$test_package_rel_dir + + [ "$placement_index" -eq "6" ] + [ "${install_placement[0]}" = "$test_package_rel_dir/file0 $abs_test_path" ] + [ "${install_placement[1]}" = "$test_package_rel_dir/file1 $abs_test_path" ] + [ "${install_placement[2]}" = "$test_package_rel_dir/file2 $abs_test_path" ] + [ "${install_placement[3]}" = "$test_package_rel_dir/$test_package_rel_subdir/file3 $abs_test_path/$test_package_rel_subdir" ] + [ "${install_placement[4]}" = "$test_package_rel_dir/$test_package_rel_subdir/file4 $abs_test_path/$test_package_rel_subdir" ] + [ "${install_placement[5]}" = "$test_package_rel_dir/$test_package_rel_subdir/file5 $abs_test_path/$test_package_rel_subdir" ] +} + +@test "write_debian_install_file writes to debian/install" { + add_system_file_placement "somefile" "/some/abs/path" + write_debian_install_file + + [ -f "$PACKAGE_SOURCE_DIR/debian/install" ] + [ "$(cat $PACKAGE_SOURCE_DIR/debian/install)" = "somefile /some/abs/path" ] +} + +@test "add_file_to_install adds file to package_dest_dir" { + local_test_dir="$BATS_TMPDIR/local-dir" + local_subdir="the/path/should/not/matter" + package_test_dir="package-dir" + + mkdir $PACKAGE_SOURCE_DIR/$package_test_dir + mkdir -p $local_test_dir/$local_subdir + echo "file0 contents" > $local_test_dir/$local_subdir/file0 + echo "file1 contents" > $local_test_dir/$local_subdir/file1 + echo "file2 contents" > $local_test_dir/$local_subdir/file2 + + add_file_to_install "$local_test_dir/$local_subdir/file0" "$package_test_dir" + add_file_to_install "$local_test_dir/$local_subdir/file1" "$package_test_dir" + add_file_to_install "$local_test_dir/$local_subdir/file2" "$package_test_dir" + + rm -r $local_test_dir + + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/file0" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/file1" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/file2" ] +} + +@test "add_file_to_install added files written to install file after write_debian_install_file" { + local_test_dir="$BATS_TMPDIR/local-dir" + local_subdir="the/path/should/not/matter" + package_test_dir="package-dir" + + mkdir $PACKAGE_SOURCE_DIR/$package_test_dir + mkdir -p $local_test_dir/$local_subdir + echo "file0 contents" > $local_test_dir/$local_subdir/file0 + + add_file_to_install "$local_test_dir/$local_subdir/file0" "$package_test_dir" + + rm -r $local_test_dir + + [ ! -e $PACKAGE_SOURCE_DIR/debian/install ] + write_debian_install_file + [ -f $PACKAGE_SOURCE_DIR/debian/install ] + [ "$(cat $PACKAGE_SOURCE_DIR/debian/install)" = "$package_test_dir/file0 $INSTALL_ROOT/$package_test_dir" ] +} + +@test "add_dir_to_install adds files in dir to package_dest_dir" { + local_test_dir="$BATS_TMPDIR/local-dir" + package_test_dir="package-dir" + + mkdir $PACKAGE_SOURCE_DIR/$package_test_dir + mkdir $local_test_dir + echo "file0 contents" > $local_test_dir/file0 + echo "file1 contents" > $local_test_dir/file1 + echo "file2 contents" > $local_test_dir/file2 + + add_dir_to_install "$local_test_dir" "$package_test_dir" + + rm -r $local_test_dir + + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/file0" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/file1" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/file2" ] +} + +@test "add_dir_to_install adds files in subdirectory tree to package_dest_dir" { + local_test_dir="$BATS_TMPDIR/local-dir" + local_test_subdir="local-subdir" + + package_test_dir="package-dir" + + mkdir $PACKAGE_SOURCE_DIR/$package_test_dir + mkdir -p $local_test_dir/$local_test_subdir + echo "file0 contents" > $local_test_dir/$local_test_subdir/file0 + echo "file1 contents" > $local_test_dir/$local_test_subdir/file1 + echo "file2 contents" > $local_test_dir/$local_test_subdir/file2 + + add_dir_to_install "$local_test_dir" "$package_test_dir" + + rm -r $local_test_dir + + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/$local_test_subdir/file0" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/$local_test_subdir/file1" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/$local_test_subdir/file2" ] +} + +@test "add_dir_to_install adds files in directory and subdirectory tree to package_dest_dir" { + local_test_dir="$BATS_TMPDIR/local-dir" + local_test_subdir="local-subdir" + + package_test_dir="package-dir" + + mkdir $PACKAGE_SOURCE_DIR/$package_test_dir + mkdir -p $local_test_dir/$local_test_subdir + + echo "file0 contents" > $local_test_dir/file0 + echo "file1 contents" > $local_test_dir/file1 + echo "file2 contents" > $local_test_dir/file2 + echo "file3 contents" > $local_test_dir/$local_test_subdir/file3 + echo "file4 contents" > $local_test_dir/$local_test_subdir/file4 + echo "file5 contents" > $local_test_dir/$local_test_subdir/file5 + + add_dir_to_install "$local_test_dir" "$package_test_dir" + + rm -r $local_test_dir + + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/file0" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/file1" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/file2" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/$local_test_subdir/file3" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/$local_test_subdir/file4" ] + [ -f "$PACKAGE_SOURCE_DIR/$package_test_dir/$local_test_subdir/file5" ] +} + +@test "add_dir_to_install added files written to install file after write_debian_install_file" { + local_test_dir="$BATS_TMPDIR/local-dir" + package_test_dir="package-dir" + + mkdir $PACKAGE_SOURCE_DIR/$package_test_dir + mkdir -p $local_test_dir + + echo "file0 contents" > $local_test_dir/file0 + + add_dir_to_install "$local_test_dir" "$package_test_dir" + + rm -r $local_test_dir + + [ ! -e $PACKAGE_SOURCE_DIR/debian/install ] + write_debian_install_file + [ -f $PACKAGE_SOURCE_DIR/debian/install ] + [ "$(cat $PACKAGE_SOURCE_DIR/debian/install)" = "$package_test_dir/file0 $INSTALL_ROOT/$package_test_dir" ] +} + +@test "add_dir_to_install with empty dest dir outputs to PACKAGE_SOURCE_DIR" { + local_test_dir="$BATS_TMPDIR/local-dir" + mkdir -p $local_test_dir + + echo "file0 contents" > $local_test_dir/file0 + + add_dir_to_install "$local_test_dir" "" + + rm -r $local_test_dir + + [ -f "$PACKAGE_SOURCE_DIR/file0" ] +} + + +@test "add_dir_to_install with empty dest dir adds files in directory and subdirectory tree to $PACKAGE_SOURCE_DIR" { + local_test_dir="$BATS_TMPDIR/local-dir" + local_test_subdir="local-subdir" + + mkdir -p $local_test_dir/$local_test_subdir + + echo "file0 contents" > $local_test_dir/file0 + echo "file1 contents" > $local_test_dir/file1 + echo "file2 contents" > $local_test_dir/file2 + echo "file3 contents" > $local_test_dir/$local_test_subdir/file3 + echo "file4 contents" > $local_test_dir/$local_test_subdir/file4 + echo "file5 contents" > $local_test_dir/$local_test_subdir/file5 + + add_dir_to_install "$local_test_dir" "" + + rm -r $local_test_dir + + [ -f "$PACKAGE_SOURCE_DIR/file0" ] + [ -f "$PACKAGE_SOURCE_DIR/file1" ] + [ -f "$PACKAGE_SOURCE_DIR/file2" ] + [ -f "$PACKAGE_SOURCE_DIR/$local_test_subdir/file3" ] + [ -f "$PACKAGE_SOURCE_DIR/$local_test_subdir/file4" ] + [ -f "$PACKAGE_SOURCE_DIR/$local_test_subdir/file5" ] +} diff --git a/src/Installers/Debian/test/unit_tests/test_scripts.bats b/src/Installers/Debian/test/unit_tests/test_scripts.bats new file mode 100755 index 0000000000..9d23b0b126 --- /dev/null +++ b/src/Installers/Debian/test/unit_tests/test_scripts.bats @@ -0,0 +1,28 @@ +#!/usr/bin/env bats +# +# 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. +# + +# Tests for debian_build_lib.sh + +setup(){ + DIR="$BATS_TEST_DIRNAME" + PACKAGIFY_DIR="$(readlink -f $DIR/../../)" +} + +@test "manpage generation is identical to lkg file" { + # Output is file "tool1.1" + # LKG file is "lkgtestman.1" + python $PACKAGIFY_DIR/scripts/manpage_generator.py $PACKAGIFY_DIR/test/test_assets/testdocs.json $PACKAGIFY_DIR/test/test_assets + + # Test Output existence + [ -f $PACKAGIFY_DIR/test/test_assets/tool1.1 ] + + # Test Output matches LKG + # If this is failing double check line ending style + [ -z "$(diff "$PACKAGIFY_DIR/test/test_assets/tool1.1" "$PACKAGIFY_DIR/test/test_assets/lkgtestman.1")" ] + + # Cleanup + rm $PACKAGIFY_DIR/test/test_assets/tool1.1 +} \ No newline at end of file diff --git a/src/Installers/Windows/.gitignore b/src/Installers/Windows/.gitignore new file mode 100644 index 0000000000..fe67cac916 --- /dev/null +++ b/src/Installers/Windows/.gitignore @@ -0,0 +1 @@ +ancm/ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/AncmIISExpressV1.wixproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/AncmIISExpressV1.wixproj new file mode 100644 index 0000000000..8aac844ad9 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/AncmIISExpressV1.wixproj @@ -0,0 +1,72 @@ + + + + + + AspNetCoreModuleIISExpress + 2A6A4709-30D2-4716-A597-55DF0FB74D37 + Package + ICE03 + true + + + + ancm_iis_express_x86_en + + + ancm_iis_express_x64_en + + + True + + + + + iisca.wxs + + + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + + + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixDependencyExtension.dll + WixDependencyExtension + + + $(WixExtDir)\WixUIExtension.dll + WixUIExtension + + + + + + setupstrings.wxl + + + + + include.wxi + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs new file mode 100644 index 0000000000..00a8af36cf --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Microsoft Corporation + + + + + + + + + + + (NOT NEWERVERSIONFOUND) OR Installed + + + Privileged + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + !(loc.Error30001) + !(loc.Error30002) + + !(loc.WebServicesRunning) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/AncmIISExpressV2.wixproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/AncmIISExpressV2.wixproj new file mode 100644 index 0000000000..d66768321d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/AncmIISExpressV2.wixproj @@ -0,0 +1,76 @@ + + + + + + AspNetCoreModuleV2IISExpress + 17c76489-4c09-4e14-b81c-7a86cd937144 + Package + ICE03 + true + + + + ancm_iis_express_x86_en_v2 + + + ancm_iis_express_x64_en_v2 + + + + True + + + + + + iisca.wxs + + + + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + + + + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixDependencyExtension.dll + WixDependencyExtension + + + $(WixExtDir)\WixUIExtension.dll + WixUIExtension + + + + + + setupstrings.wxl + + + + + include.wxi + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/ancm_iis_expressv2.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/ancm_iis_expressv2.wxs new file mode 100644 index 0000000000..12a2c887b8 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/ancm_iis_expressv2.wxs @@ -0,0 +1,704 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Microsoft Corporation + + + + + + + + + + + (NOT NEWERVERSIONFOUND) OR Installed + + + Privileged + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + !(loc.Error30001) + !(loc.Error30002) + + !(loc.WebServicesRunning) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj new file mode 100644 index 0000000000..e09c9574bb --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj @@ -0,0 +1,26 @@ + + + netstandard1.0 + true + true + $(RepositoryRoot).deps\ANCM + + + + + + + + + + $(RepositoryRoot).deps\ANCM; + + + $(RestoreSources); + https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; + https://api.nuget.org/v3/index.json; + https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/AncmV1.wixproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/AncmV1.wixproj new file mode 100644 index 0000000000..c1f389495c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/AncmV1.wixproj @@ -0,0 +1,74 @@ + + + + + + AspNetCoreModule + D36FDC38-FE53-48CC-BC82-A17C28F1CEE1 + true + Package + true + + + + aspnetcoremodule_x86_en + + + aspnetcoremodule_x64_en + + + + True + + + + + iisca.wxs + + + + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + + + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixDependencyExtension.dll + WixDependencyExtension + + + $(WixExtDir)\WixUIExtension.dll + WixUIExtension + + + + + + setupstrings.wxl + + + + + include.wxi + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/aspnetcoremodule.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/aspnetcoremodule.wxs new file mode 100644 index 0000000000..cdb387e44f --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/aspnetcoremodule.wxs @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Microsoft Corporation + + + + + + + + + + + + + + + + + + (NOT NEWERVERSIONFOUND) OR Installed + + + + Privileged + + + + + + + + + + + + + + + + 1 + + + + = 601)]]> + + + + + ((IISCOREWEBENGINEINSTALLED = "#1") AND (IISW3SVCINSTALLED = "#1")) OR (Installed) + + + + + NOT ( (VersionNT = 600) AND (ServicePackLevel = 1) AND (WINDOWSUPDATE_START_TYPE = "#4") ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + !(loc.Error30001) + !(loc.Error30002) + + !(loc.WebServicesRunning) + + + + + + AspNetCoreModule + AspNetCoreModuleDll + + + + + + system.webServer/aspNetCore + AspNetCoreSchemaFile + Allow + + + + + + WWW Server + {3a2a4e84-4c21-4981-ae10-3fda0d9b0f83} + ANCM + 65536 + AspNetCoreModule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/AncmV2.wixproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/AncmV2.wixproj new file mode 100644 index 0000000000..1969ce723c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/AncmV2.wixproj @@ -0,0 +1,74 @@ + + + + + + AspNetCoreModuleV2 + f9bacb48-3bd7-4ec2-ae31-664e8703ec12 + Package + true + true + + + + aspnetcoremodule_x86_en_v2 + + + aspnetcoremodule_x64_en_v2 + + + + True + + + + + iisca.wxs + + + + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + + + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixDependencyExtension.dll + WixDependencyExtension + + + $(WixExtDir)\WixUIExtension.dll + WixUIExtension + + + + + + setupstrings.wxl + + + + + include.wxi + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/aspnetcoremodulev2.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/aspnetcoremodulev2.wxs new file mode 100644 index 0000000000..775147784e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/aspnetcoremodulev2.wxs @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Microsoft Corporation + + + + + + + + + + + + + (NOT NEWERVERSIONFOUND) OR Installed + + + + Privileged + + + + + + + + + + + + + + + + 1 + + + + = 601)]]> + + + + + ((IISCOREWEBENGINEINSTALLED = "#1") AND (IISW3SVCINSTALLED = "#1")) OR (Installed) + + + + + NOT ( (VersionNT = 600) AND (ServicePackLevel = 1) AND (WINDOWSUPDATE_START_TYPE = "#4") ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + !(loc.Error30001) + !(loc.Error30002) + + !(loc.WebServicesRunning) + + + + + + AspNetCoreModuleV2 + AspNetCoreModuleV2Dll + + + + + + system.webServer/aspNetCore + AspNetCoreSchemaV2File + Allow + + + + + + WWW Server + {3a2a4e84-4c21-4981-ae10-3fda0d9b0f83} + ANCM + 65536 + AncmMofFile + AspNetCoreModuleV2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props new file mode 100644 index 0000000000..2f47372910 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props @@ -0,0 +1,15 @@ + + + + + + + $(_TwoDigitYear)$(_ThreeDigitDayOfYear) + $(PRODUCT_MAJOR) + $(PRODUCT_MINOR) + $(BUILD_MAJOR) + $(BUILD_MINOR) + BLDVERMAJOR=$(BLDVERMAJOR);BLDVERMINOR=$(BLDVERMINOR);BLDNUMMAJOR=$(BLDNUMMAJOR);BLDNUMMINOR=$(BLDNUMMINOR);$(DefineConstants) + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp new file mode 100644 index 0000000000..48d826f720 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp @@ -0,0 +1,184 @@ +// 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. + +#include + +DECLARE_DEBUG_PRINT_OBJECT( "proxyCA.dll" ); + +HINSTANCE g_hinst; + +BOOL WINAPI +DllMain( + HINSTANCE hModule, + DWORD dwReason, + LPVOID lpReserved + ) +{ + UNREFERENCED_PARAMETER( lpReserved ); + switch( dwReason ) + { + case DLL_PROCESS_ATTACH: + CREATE_DEBUG_PRINT_OBJECT; + DisableThreadLibraryCalls( hModule ); + g_hinst = hModule; + break; + + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} + + +struct COMPRESSION_MIME_TYPE +{ + PCWSTR pszMimeType; + BOOL fEnabled; +}; + +COMPRESSION_MIME_TYPE gMimeTypes[] = + { { L"text/event-stream", FALSE} }; + +UINT +WINAPI +RegisterANCMCompressionCA( + IN MSIHANDLE + ) +{ + HRESULT hr = S_OK; + DWORD i; + VARIANT varName; + IAppHostWritableAdminManager * pAdminMgr = NULL; + IAppHostElement * pHttpCompressionSection = NULL; + IAppHostElement * pDynamicCompressionElement = NULL; + IAppHostElementCollection * pMimeTypeCollection = NULL; + IAppHostElement * pMimeTypeElement = NULL; + + VariantInit(&varName); + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + goto exit; + } + + hr = pAdminMgr->GetAdminSection(L"system.webServer/httpCompression", + L"MACHINE/WEBROOT/APPHOST", + &pHttpCompressionSection); + if (FAILED(hr)) + { + goto exit; + } + + hr = pHttpCompressionSection->GetElementByName(L"dynamicTypes", + &pDynamicCompressionElement); + if (FAILED(hr)) + { + goto exit; + } + + hr = pDynamicCompressionElement->get_Collection(&pMimeTypeCollection); + if (FAILED(hr)) + { + goto exit; + } + + hr = pMimeTypeCollection->get_Count(&i); + if (FAILED(hr) || i == 0) + { + // failure or DynamicCmpression is not enabled + goto exit; + } + + for (i=0; i<_countof(gMimeTypes); i++) + { + hr = pMimeTypeCollection->CreateNewElement(L"add", + &pMimeTypeElement); + if (FAILED(hr)) + { + goto exit; + } + + hr = VariantAssign(&varName, + gMimeTypes[i].pszMimeType); + if (FAILED(hr)) + { + goto exit; + } + + hr = SetElementProperty(pMimeTypeElement, + L"mimeType", + &varName); + if (FAILED(hr)) + { + goto exit; + } + VariantClear(&varName); + + varName.vt = VT_BOOL; + varName.boolVal = gMimeTypes[i].fEnabled ? VARIANT_TRUE : VARIANT_FALSE; + + hr = SetElementProperty(pMimeTypeElement, + L"enabled", + &varName); + if (FAILED(hr)) + { + goto exit; + } + VariantClear(&varName); + + hr = pMimeTypeCollection->AddElement(pMimeTypeElement); + if (FAILED(hr) && + hr != HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) + { + goto exit; + } + + pMimeTypeElement->Release(); + pMimeTypeElement = NULL; + } + + hr = pAdminMgr->CommitChanges(); + + exit: + + VariantClear(&varName); + + if (pMimeTypeElement != NULL) + { + pMimeTypeElement->Release(); + pMimeTypeElement = NULL; + } + + if (pMimeTypeCollection != NULL) + { + pMimeTypeCollection->Release(); + pMimeTypeCollection = NULL; + } + + if (pDynamicCompressionElement != NULL) + { + pDynamicCompressionElement->Release(); + pDynamicCompressionElement = NULL; + } + + if (pHttpCompressionSection != NULL) + { + pHttpCompressionSection->Release(); + pHttpCompressionSection = NULL; + } + + if (pAdminMgr != NULL) + { + pAdminMgr->Release(); + pAdminMgr = NULL; + } + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def new file mode 100644 index 0000000000..3518cde35f --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def @@ -0,0 +1,23 @@ +LIBRARY aspnetcoreCA + +EXPORTS + + ; IIS Common Config custom actions + + IISScheduleInstallCA + IISScheduleUninstallCA + IISExecuteCA + IISBeginTransactionCA + IISRollbackTransactionCA + IISCommitTransactionCA + + CheckForSharedConfigurationCA + + ScheduleInstallWindowsHotfixCA + ExecuteInstallWindowsHotfixCA + ExecuteCleanUpWindowsHotfixCA + ScheduleRebootIfRequiredCA + + RegisterANCMCompressionCA + + CheckForServicesRunningCA diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc new file mode 100644 index 0000000000..8f05349435 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc @@ -0,0 +1,10 @@ +#define VER_FILETYPE VFT_DLL +#define RC_VERSION_INTERNAL_NAME "aspnetcoreCA\0" +#define RC_VERSION_ORIGINAL_FILE_NAME "aspnetcoreCA.dll\0" +#define RC_VERSION_FILE_DESCRIPTION "IIS AspNet Core Support Module Custom Action DLL\0" +#define PRODUCT_MAJOR 7 +#define PRODUCT_MINOR 1 +#define BUILD_MAJOR 1972 +#define BUILD_MINOR 0 + +#include diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj new file mode 100644 index 0000000000..e47590e167 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj @@ -0,0 +1,98 @@ + + + + + $(MSBuildThisFileDirectory)..\ + + + + <_IIS-SetupExportsPath>$(ANCM-Setup)IIS-Setup\build\exports.props + + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {7C27E72F-54D0-4820-8CFA-5E4BE640974B} + aspnetcoreca + aspnetcoreCA + + + + DynamicLibrary + v141 + Unicode + + + true + + + + $(IIS-Common)version;$(IIS-Common)Include;$(IIS-Setup)iisca\lib;$(WIX)sdk\$(WixPlatformToolset)\inc;$(AdditionalIncludeDirectories) + + + + true + $(AdditionalIncludeDirectories) + + + httpapi.lib;shlwapi.lib;ahadmin.lib;xmllite.lib;msi.lib;Version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + aspnetcoreCA.def + $(OutDir)$(TargetName).lib + /NODEFAULTLIB:MSVCRT %(AdditionalOptions) + + + + + + + + + + + + $(IIS-Common)version + + + + + {7324770c-0871-4d73-be3d-5e2f3e9e1b1e} + + + {b54a8f61-60de-4ad9-87ca-d102f230678e} + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp new file mode 100644 index 0000000000..b0e4753c44 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp @@ -0,0 +1,244 @@ +// 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. + +#include +#include + +HRESULT +GetServiceCurrentState( + __in LPCWSTR pszServiceName, + __out SERVICE_STATUS * pServiceStatus +) +{ + HRESULT hr = S_OK; + SC_HANDLE hServiceControlManager = NULL; + SC_HANDLE hService = NULL; + + hServiceControlManager = OpenSCManager( NULL, // Local machine + NULL, + STANDARD_RIGHTS_READ ); + if ( hServiceControlManager == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto Finished; + } + + hService = OpenService( hServiceControlManager, + pszServiceName, + SERVICE_QUERY_STATUS ); + if ( hService == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto Finished; + } + + if ( !QueryServiceStatus( hService, + pServiceStatus ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto Finished; + } + +Finished: + + if ( hService != NULL ) + { + CloseServiceHandle( hService ); + hService = NULL; + } + + if ( hServiceControlManager != NULL ) + { + CloseServiceHandle( hService ); + hService = NULL; + } + + return hr; +} + +BOOL +IsServiceRunning( + const SERVICE_STATUS & ServiceStatus +) +{ + switch( ServiceStatus.dwCurrentState ) + { + case SERVICE_RUNNING: + case SERVICE_START_PENDING: + case SERVICE_CONTINUE_PENDING: + return TRUE; + default: + return FALSE; + } +} + +HRESULT +IsQfeInstalled( + __in LPCWSTR pszQfeName, + __out BOOL * pfIsInstalled +) +{ + HRESULT hr = S_OK; + CComPtr< IWbemLocator > pLocator; + CComPtr< IWbemServices > pService; + CComPtr< IEnumWbemClassObject > pEnumerator; + ULONG Count = 0; + CComPtr< IWbemClassObject > pProcessor; + CComBSTR bstrNamespace; + CComBSTR bstrQueryLanguage; + CComBSTR bstrQuery; + + if ( FAILED( hr = bstrNamespace.Append( L"root\\CIMV2", 10 ) ) || + FAILED( hr = bstrQueryLanguage.Append( L"WQL", 3 ) ) || + FAILED( hr = bstrQuery.Append( L"SELECT HotFixID FROM Win32_QuickFixEngineering WHERE HotFixID='" ) ) || + FAILED( hr = bstrQuery.Append( pszQfeName ) ) || + FAILED( hr = bstrQuery.Append( L"'", 1 ) ) ) + { + goto Finished; + } + + hr = CoCreateInstance( __uuidof(WbemAdministrativeLocator), + NULL, // pUnkOuter + CLSCTX_INPROC_SERVER, + __uuidof(IWbemLocator), + reinterpret_cast< void** >( &pLocator ) ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = pLocator->ConnectServer( bstrNamespace, + NULL, // strUser + NULL, // strPassword + NULL, // strLocale + WBEM_FLAG_CONNECT_USE_MAX_WAIT, + NULL, // strAuthority + NULL, // pCtx + &pService ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + // + // Set the proxy so that impersonation of the client occurs. + // + hr = CoSetProxyBlanket( pService, + RPC_C_AUTHN_DEFAULT, + RPC_C_AUTHZ_NONE, + NULL, + RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, + EOAC_NONE); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = pService->ExecQuery( bstrQueryLanguage, + bstrQuery, + WBEM_FLAG_FORWARD_ONLY, + NULL, + &pEnumerator ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = pEnumerator->Next( WBEM_INFINITE, + 1L, + &pProcessor, + &Count ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + *pfIsInstalled = Count > 0; + +Finished: + + return hr; +} + +UINT +WINAPI +CheckForServicesRunningCA( + MSIHANDLE hInstall +) +{ + HRESULT hr = S_OK; + BOOL fIsServiceRunning = FALSE; + SERVICE_STATUS ServiceStatus; + LPCWSTR rgServiceNames[] = { L"WAS", L"WMSVC" }; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + // + // Check if any pService is running. + // + for( DWORD Index = 0; Index < _countof( rgServiceNames ); Index ++ ) + { + hr = GetServiceCurrentState( rgServiceNames[Index], + &ServiceStatus ); + if ( hr == HRESULT_FROM_WIN32( ERROR_SERVICE_DOES_NOT_EXIST ) ) + { + hr = S_OK; + } + else if ( FAILED( hr ) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to query the state of the service '%s' hr=0x%x", + rgServiceNames[Index], + hr ); + DBGERROR_HR(hr); + goto Finished; + } + else + { + fIsServiceRunning = IsServiceRunning( ServiceStatus ); + if ( fIsServiceRunning ) + { + break; + } + } + } + + if ( fIsServiceRunning ) + { + BOOL fQfeInstalled = FALSE; + + hr = IsQfeInstalled( L"KB954438", + &fQfeInstalled ); + if ( FAILED( hr ) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to query the hotfix 'KB949172' information hr=0x%x", + hr ); + DBGERROR_HR(hr); + goto Finished; + } + + if ( fQfeInstalled ) + { + // + // hotfix is already installed. + // + goto Finished; + } + + IISLogClose(); + return LogMsiCustomActionError( hInstall, 30003 ); + } + +Finished: + + IISLogClose(); + + // TODO Wire up when Rollback CA's are wired up + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props b/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props new file mode 100644 index 0000000000..e790ba07a1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props @@ -0,0 +1,43 @@ + + + + + + + <_TwoDigitYear>$([MSBuild]::Subtract($([System.DateTime]::UtcNow.Year), 2000)) + <_ThreeDigitDayOfYear>$([System.DateTime]::UtcNow.DayOfYear.ToString().PadLeft(3, '0')) + + + $(_TwoDigitYear)$(_ThreeDigitDayOfYear) + $(PRODUCT_MAJOR) + $(PRODUCT_MINOR) + $(BUILD_MAJOR) + $(BUILD_MINOR) + + + 1$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(BUILD_MAJOR).0 + + + 2.0.0 + + + $(RepositoryRoot)src\Installers\Windows\AspNetCoreModule-Setup\ + $(AspNetCoreSetupRoot)IIS-Setup\ + $(IIS-Setup)IIS-Common\ + $(AspNetCoreSetupRoot)build\ + + + CustomAction=$(AspNetCoreSetupRoot)CustomAction\bin\$(Configuration)\$(Platform)\aspnetcoreca.dll + $(RepositoryRoot).deps\ANCM\Microsoft.AspNetCore.AspNetCoreModule\$(MicrosoftAspNetCoreAspNetCoreModulePackageVersion)\ + $(RepositoryRoot).deps\ANCM\Microsoft.AspNetCore.AspNetCoreModuleV2\$(MicrosoftAspNetCoreAspNetCoreModuleV2PackageVersion)\ + $(PreBuiltANCMSchema)contentFiles\any\any\ + $(PreBuiltANCMV2Schema)contentFiles\any\any\ + + BLDVERMAJOR=$(BLDVERMAJOR);BLDVERMINOR=$(BLDVERMINOR);BLDNUMMAJOR=$(BLDNUMMAJOR);BLDNUMMINOR=$(BLDNUMMINOR);$(DefineConstants) + ANCMMsiVersion=$(ANCMMsiVersion);ANCMOutOfProcessNugetPackageHandlerVersion=$(ANCMOutOfProcessNugetPackageHandlerVersion);$(DefineConstants) + PreBuiltANCMRoot=$(PreBuiltANCMRoot);PreBuiltANCMV2Root=$(PreBuiltANCMV2Root);$(DefineConstants) + $(CustomActionVariable);PreBuiltANCMSchema=$(PreBuiltANCMSchema);PreBuiltANCMV2Schema=$(PreBuiltANCMV2Schema);$(DefineConstants) + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln new file mode 100644 index 0000000000..5b48ec6769 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27120.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLib", "lib\CommonLib.vcxproj", "{B54A8F61-60DE-4AD9-87CA-D102F230678E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reftrace", "reftrace\reftrace.vcxproj", "{A2599642-CBE5-4230-8511-3DC2D81874BE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.ActiveCfg = Debug|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.Build.0 = Debug|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.ActiveCfg = Debug|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.Build.0 = Debug|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.ActiveCfg = Release|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.Build.0 = Release|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.ActiveCfg = Release|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.Build.0 = Release|Win32 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x64.ActiveCfg = Debug|x64 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x64.Build.0 = Debug|x64 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x86.ActiveCfg = Debug|Win32 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x86.Build.0 = Debug|Win32 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x64.ActiveCfg = Release|x64 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x64.Build.0 = Release|x64 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x86.ActiveCfg = Release|Win32 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {81F5A61A-A12A-4F53-B0F9-C0E541CA6567} + EndGlobalSection +EndGlobal diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h new file mode 100644 index 0000000000..83e39fd7ff --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#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 * 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. diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h new file mode 100644 index 0000000000..a39c09bb73 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h @@ -0,0 +1,264 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +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 +GetElementINTProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT INT * pintValue + ); + +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 +); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx new file mode 100644 index 0000000000..871c7e8e0f --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _BASE64_HXX_ +#define _BASE64_HXX_ + +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_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h new file mode 100644 index 0000000000..63e567be4d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h @@ -0,0 +1,271 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include + + +// +// 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 +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(cbNewSize), m_pBuffer, m_cbBuffer ); + m_fHeapAllocated = true; + } + + m_pBuffer = reinterpret_cast(pNewMem); + m_cbBuffer = static_cast(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 +HRESULT +ResizeBufferByTwo( + BUFFER_T& Buffer, + SIZE_T cbIdealSize, + bool fZeroMemoryBeyondOldSize = false +) +{ + if (cbIdealSize > Buffer.QuerySize()) + { + if (!Buffer.Resize(max(cbIdealSize, static_cast(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 BUFFER; + +// +// Assumption of macros below for pointer alignment purposes +// +C_ASSERT( sizeof(VOID*) <= sizeof(ULONGLONG) ); + +// +// Declare a BUFFER that will use stack memory of +// 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 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 ) ) diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h new file mode 100644 index 0000000000..82ac441abd --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _DATETIME_H_ +#define _DATETIME_H_ + +BOOL +StringTimeToFileTime( + PCSTR pszTime, + ULONGLONG * pulTime +); + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h new file mode 100644 index 0000000000..9a33cca394 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _DBGUTIL_H_ +#define _DBGUTIL_H_ + +#include + +// +// 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 diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h new file mode 100644 index 0000000000..39033973ce --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h @@ -0,0 +1,124 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#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) + +#define DEBUG_FLAGS_REGISTRY_LOCATION_A "DebugFlags" + +extern DWORD g_dwDebugFlags; + +static +BOOL +IfDebug( + DWORD dwFlag + ) +{ + return ( dwFlag & g_dwDebugFlags ); +} + +static +VOID +DebugPrint( + DWORD dwFlag, + LPCSTR szString + ) +{ + STBUFF strOutput; + HRESULT hr; + + if ( IfDebug( dwFlag ) ) + { + hr = strOutput.Printf( "[dipmodule.dll] %s\r\n", + szString ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + OutputDebugStringA( strOutput.QueryStr() ); + } + +Finished: + + return; +} + +static +VOID +DebugPrintf( +DWORD dwFlag, +LPCSTR szFormat, +... +) +{ + STBUFF strCooked; + STBUFF strOutput; + va_list args; + HRESULT hr; + + if ( IfDebug( dwFlag ) ) + { + va_start( args, szFormat ); + + hr = strCooked.Vsprintf( (LPSTR)szFormat, args ); + + va_end( args ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + DebugPrint( dwFlag, strCooked.QueryStr() ); + } + +Finished: + + return; +} + +static void ReadDebugFlagFromRegistryKey(const char* pszRegKey, IN DWORD dwDefault) +{ + HKEY hkey = NULL; + g_dwDebugFlags = dwDefault; + DWORD dwType; + DWORD dwBuffer; + DWORD cbBuffer = sizeof(dwBuffer); + + DWORD dwError = RegOpenKeyExA(HKEY_LOCAL_MACHINE, + pszRegKey, + 0, + KEY_READ, + &hkey); + if ( dwError == NO_ERROR && hkey != NULL) + { + dwError = RegQueryValueExA( hkey, + DEBUG_FLAGS_REGISTRY_LOCATION_A, + NULL, + &dwType, + (LPBYTE)&dwBuffer, + &cbBuffer ); + if( ( dwError == NO_ERROR ) && ( dwType == REG_DWORD ) ) + { + g_dwDebugFlags = dwBuffer; + } + RegCloseKey( hkey); + hkey = NULL; + } +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h new file mode 100644 index 0000000000..a86b0a1358 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h @@ -0,0 +1,325 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#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(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(pusz)); } + +inline DWORD Hash(const signed char* pssz) +{ return HashString(reinterpret_cast(pssz)); } + +inline DWORD Hash(const wchar_t* pwsz) +{ return HashString(pwsz); } + +inline DWORD +Hash( + const GUID* pguid, + DWORD dwHash = 0) +{ + + return * reinterpret_cast(const_cast(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__ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h new file mode 100644 index 0000000000..9a299ca1af --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h @@ -0,0 +1,666 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include +#include "rwlock.h" +#include "prime.h" + +template +class HASH_NODE +{ + template + 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 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 +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 +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 +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 +__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 +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 +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 +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 +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 +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 +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(); +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h new file mode 100644 index 0000000000..400d8ec855 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h @@ -0,0 +1,2797 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __HTTP_H__ +#define __HTTP_H__ + +#pragma once + +#if _WIN32_WINNT >= 0x0501 + +// +// HTTPAPI is available on +// +// a) WinXP SP2 and higher +// b) Windows 2003 and higher +// c) Vista and higher. +// + + + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +// +// Flags for HttpInitialize() and HttpTerminate(). +// + +// +// HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for +// applications using server APIs. +// +// HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for +// applications using HTTP configuration APIs. +// +// +// Notes - +// +// 1. These flags can be used in combination. +// +// 2. HttpTerminate() must be called for each call to HttpInitialize() made +// with each flag set when invoking HttpInitialize. For example, one +// could make two calls to HttpInitialize() setting HTTP_INITIALIZE_SERVER +// the first time and HTTP_INITIALIZE_CONFIG the second time. One call +// to HttpTerminate() with both flags set suffices to clean up both +// calls to HttpInitialize(). +// + +#define HTTP_INITIALIZE_SERVER 0x00000001 +#define HTTP_INITIALIZE_CONFIG 0x00000002 + +#if _WIN32_WINNT <= 0x0501 +#define BUILD_IIS_FOR_XP 1 +#endif + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Following section defines the properties supported by the +// server side HTTP API. +// + +typedef enum _HTTP_SERVER_PROPERTY +{ + // + // Used for enabling server side authentication. + // + + HttpServerAuthenticationProperty, + + // + // Used for enabling logging. + // + + HttpServerLoggingProperty, + + // + // Used for setting QoS properties. + // + + HttpServerQosProperty, + + // + // Used for configuring timeouts. + // + + HttpServerTimeoutsProperty, + + // + // Used for limiting request queue lengths. + // + + HttpServerQueueLengthProperty, + + // + // Used for manipulating the state. + // + + HttpServerStateProperty, + + // + // Used for modifying the verbosity level of 503 type responses + // generated by server side API. + // + + HttpServer503VerbosityProperty, + + // + // Used for manipulating Url Group to Request Queue association. + // + + HttpServerBindingProperty, + + // + // Extended authentication property. + // + + HttpServerExtendedAuthenticationProperty, + + // + // Listening endpoint property. + // + + HttpServerListenEndpointProperty + + // + // Authentication channel binding property + // + +#endif +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + + ,HttpServerChannelBindProperty + + // + // IP Protection level policy for a Url Group. + // + + ,HttpServerProtectionLevelProperty +#endif +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + + +} HTTP_SERVER_PROPERTY, *PHTTP_SERVER_PROPERTY; + + +#define HTTP_MAX_SERVER_QUEUE_LENGTH 0x7FFFFFFF +#define HTTP_MIN_SERVER_QUEUE_LENGTH 1 + +// +// Generic property flags. Each structure defining a property info typically +// contain an element of this type. +// + +typedef struct _HTTP_PROPERTY_FLAGS +{ + ULONG Present:1; + +} HTTP_PROPERTY_FLAGS, *PHTTP_PROPERTY_FLAGS; + +// +// Enabled state. +// + +typedef enum _HTTP_ENABLED_STATE +{ + HttpEnabledStateActive, + HttpEnabledStateInactive, + +} HTTP_ENABLED_STATE, *PHTTP_ENABLED_STATE; + + +typedef struct _HTTP_STATE_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + HTTP_ENABLED_STATE State; + +} HTTP_STATE_INFO, *PHTTP_STATE_INFO; + +// +// Defines the verbosity level for a request queue which will be used +// when sending "503 - Service Unavailable" type error responses. Note that +// this setting only affects the error responses generated internally +// by HTTPAPI. +// + +typedef enum _HTTP_503_RESPONSE_VERBOSITY +{ + // + // Instead of sending a 503 response, the connection will be reset. + // This is the default behavior. + // + Http503ResponseVerbosityBasic, + + // + // Will send a 503 w/ a generic reason phrase. + // + Http503ResponseVerbosityLimited, + + // + // Will send a 503 w/ a detailed reason phrase. + // + Http503ResponseVerbosityFull + +} HTTP_503_RESPONSE_VERBOSITY, *PHTTP_503_RESPONSE_VERBOSITY; + +// +// Network QoS related. +// + +typedef enum _HTTP_QOS_SETTING_TYPE +{ + HttpQosSettingTypeBandwidth, + HttpQosSettingTypeConnectionLimit, + HttpQosSettingTypeFlowRate + +} HTTP_QOS_SETTING_TYPE, *PHTTP_QOS_SETTING_TYPE; + +typedef struct _HTTP_QOS_SETTING_INFO +{ + HTTP_QOS_SETTING_TYPE QosType; + PVOID QosSetting; +} HTTP_QOS_SETTING_INFO, *PHTTP_QOS_SETTING_INFO; + +typedef struct _HTTP_CONNECTION_LIMIT_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + ULONG MaxConnections; + +} HTTP_CONNECTION_LIMIT_INFO, *PHTTP_CONNECTION_LIMIT_INFO; + +typedef struct _HTTP_BANDWIDTH_LIMIT_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + ULONG MaxBandwidth; + +} HTTP_BANDWIDTH_LIMIT_INFO, *PHTTP_BANDWIDTH_LIMIT_INFO; + +typedef struct _HTTP_FLOWRATE_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + ULONG MaxBandwidth; + ULONG MaxPeakBandwidth; + ULONG BurstSize; + +} HTTP_FLOWRATE_INFO, *PHTTP_FLOWRATE_INFO; + +// +// Bandwidth throttling limit can not be set lower than the following +// number. The value is in bytes/sec. +// + +#define HTTP_MIN_ALLOWED_BANDWIDTH_THROTTLING_RATE ((ULONG)1024) + +// +// Distinguished value for bandwidth, connection limits and logging rollover +// size indicating "no limit". +// + +#define HTTP_LIMIT_INFINITE ((ULONG)-1) + +// +// Timeout information. +// + +// +// For manipulating global timeout settings. +// These timers run when connection does not belong to any application. +// Value zero is not allowed for driver wide timeout settings. +// + +typedef enum _HTTP_SERVICE_CONFIG_TIMEOUT_KEY +{ + IdleConnectionTimeout = 0, + HeaderWaitTimeout + +} HTTP_SERVICE_CONFIG_TIMEOUT_KEY, *PHTTP_SERVICE_CONFIG_TIMEOUT_KEY; + +typedef USHORT HTTP_SERVICE_CONFIG_TIMEOUT_PARAM, + *PHTTP_SERVICE_CONFIG_TIMEOUT_PARAM; + +// +// To set a timeout value use the set structure. To query/delete use the key +// directly. When you query a timeout value the output buffer must be exactly +// the sizeof param. +// + +typedef struct _HTTP_SERVICE_CONFIG_TIMEOUT_SET +{ + HTTP_SERVICE_CONFIG_TIMEOUT_KEY KeyDesc; + HTTP_SERVICE_CONFIG_TIMEOUT_PARAM ParamDesc; + +} HTTP_SERVICE_CONFIG_TIMEOUT_SET, *PHTTP_SERVICE_CONFIG_TIMEOUT_SET; + +// +// For manipulating application specific timeout settings. +// These timers run when there's a request being processed on a connection +// and HTTPAPI has already associated the request with an application. +// Setting a timeout value to zero will cause HTTPAPI to revert to default. +// + +typedef struct _HTTP_TIMEOUT_LIMIT_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + + // + // Timeouts configured in seconds. + // + + USHORT EntityBody; + USHORT DrainEntityBody; + USHORT RequestQueue; + + // + // Following two timeouts are only enforced after first request on + // connection is routed to the application. These will not manipulate + // the driver wide timeouts. + // + + USHORT IdleConnection; + USHORT HeaderWait; + + // + // Timeouts configured in bytes/second. + // This timer can be turned off by setting it to MAXULONG. + // + + ULONG MinSendRate; + +} HTTP_TIMEOUT_LIMIT_INFO, *PHTTP_TIMEOUT_LIMIT_INFO; + +// +// Controls whether IP-based URLs should listen on the specific IP or wildcard. +// + +typedef struct _HTTP_LISTEN_ENDPOINT_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + + BOOLEAN EnableSharing; + +} HTTP_LISTEN_ENDPOINT_INFO, *PHTTP_LISTEN_ENDPOINT_INFO; + + +typedef struct _HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS +{ + USHORT DomainNameLength; + PWSTR DomainName; + USHORT RealmLength; + PWSTR Realm; +} HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS, + *PHTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS; + +typedef struct _HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS +{ + USHORT RealmLength; + PWSTR Realm; +} HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS, + *PHTTP_SERVER_AUTHENTICATION_BASIC_PARAMS; + +// +// Definitions used for setting server side authentication property. +// + +#define HTTP_AUTH_ENABLE_BASIC (0x00000001) +#define HTTP_AUTH_ENABLE_DIGEST (0x00000002) +#define HTTP_AUTH_ENABLE_NTLM (0x00000004) +#define HTTP_AUTH_ENABLE_NEGOTIATE (0x00000008) +#define HTTP_AUTH_ENABLE_KERBEROS (0x00000010) + +#define HTTP_AUTH_ENABLE_ALL \ + (HTTP_AUTH_ENABLE_BASIC |\ + HTTP_AUTH_ENABLE_DIGEST |\ + HTTP_AUTH_ENABLE_NTLM |\ + HTTP_AUTH_ENABLE_NEGOTIATE |\ + HTTP_AUTH_ENABLE_KERBEROS) + + +C_ASSERT(HTTP_AUTH_ENABLE_NEGOTIATE > HTTP_AUTH_ENABLE_NTLM); +C_ASSERT(HTTP_AUTH_ENABLE_NTLM > HTTP_AUTH_ENABLE_DIGEST); +C_ASSERT(HTTP_AUTH_ENABLE_DIGEST > HTTP_AUTH_ENABLE_BASIC); + +#define HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING (0x01) +#define HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL (0x02) + +typedef struct _HTTP_SERVER_AUTHENTICATION_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + + ULONG AuthSchemes; + + BOOLEAN ReceiveMutualAuth; + BOOLEAN ReceiveContextHandle; + BOOLEAN DisableNTLMCredentialCaching; + + UCHAR ExFlags; + + HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS DigestParams; + HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS BasicParams; + +} HTTP_SERVER_AUTHENTICATION_INFO, *PHTTP_SERVER_AUTHENTICATION_INFO; + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + +// +// Definitions for setting authentication channel binding properties +// + +typedef enum _HTTP_SERVICE_BINDING_TYPE +{ + HttpServiceBindingTypeNone = 0, + HttpServiceBindingTypeW, + HttpServiceBindingTypeA + +} HTTP_SERVICE_BINDING_TYPE; + +typedef struct _HTTP_SERVICE_BINDING_BASE +{ + HTTP_SERVICE_BINDING_TYPE Type; + +} HTTP_SERVICE_BINDING_BASE, *PHTTP_SERVICE_BINDING_BASE; + +typedef struct _HTTP_SERVICE_BINDING_A +{ + HTTP_SERVICE_BINDING_BASE Base; + PCHAR Buffer; + ULONG BufferSize; + +} HTTP_SERVICE_BINDING_A, *PHTTP_SERVICE_BINDING_A; + +typedef struct _HTTP_SERVICE_BINDING_W +{ + HTTP_SERVICE_BINDING_BASE Base; + PWCHAR Buffer; + ULONG BufferSize; + +} HTTP_SERVICE_BINDING_W, *PHTTP_SERVICE_BINDING_W; + +typedef enum _HTTP_AUTHENTICATION_HARDENING_LEVELS +{ + HttpAuthenticationHardeningLegacy = 0, + HttpAuthenticationHardeningMedium, + HttpAuthenticationHardeningStrict + +} HTTP_AUTHENTICATION_HARDENING_LEVELS; + +// +// Channel binding token verification flags. +// + +#define HTTP_CHANNEL_BIND_PROXY 0x1 +#define HTTP_CHANNEL_BIND_PROXY_COHOSTING 0x20 + +// +// Service bind verification flags +// + +#define HTTP_CHANNEL_BIND_NO_SERVICE_NAME_CHECK 0x2 +#define HTTP_CHANNEL_BIND_DOTLESS_SERVICE 0x4 + +// +// Flags triggering channel bind parameters retrieval +// + +#define HTTP_CHANNEL_BIND_SECURE_CHANNEL_TOKEN 0x8 +#define HTTP_CHANNEL_BIND_CLIENT_SERVICE 0x10 + +// +// All valid flags (mask for internal checks) +// + +typedef struct _HTTP_CHANNEL_BIND_INFO +{ + HTTP_AUTHENTICATION_HARDENING_LEVELS Hardening; + ULONG Flags; + PHTTP_SERVICE_BINDING_BASE * ServiceNames; + ULONG NumberOfServiceNames; + +} HTTP_CHANNEL_BIND_INFO, *PHTTP_CHANNEL_BIND_INFO; + +typedef struct _HTTP_REQUEST_CHANNEL_BIND_STATUS +{ + PHTTP_SERVICE_BINDING_BASE ServiceName; + PUCHAR ChannelToken; + ULONG ChannelTokenSize; + ULONG Flags; + +} HTTP_REQUEST_CHANNEL_BIND_STATUS, *PHTTP_REQUEST_CHANNEL_BIND_STATUS; + +#endif + +// +// Definitions used for setting logging property. +// + +// +// The known log fields recognized/supported by HTTPAPI. Following fields +// are used for W3C logging. Subset of them are also used for error +// logging. +// + +#define HTTP_LOG_FIELD_DATE 0x00000001 +#define HTTP_LOG_FIELD_TIME 0x00000002 +#define HTTP_LOG_FIELD_CLIENT_IP 0x00000004 +#define HTTP_LOG_FIELD_USER_NAME 0x00000008 +#define HTTP_LOG_FIELD_SITE_NAME 0x00000010 +#define HTTP_LOG_FIELD_COMPUTER_NAME 0x00000020 +#define HTTP_LOG_FIELD_SERVER_IP 0x00000040 +#define HTTP_LOG_FIELD_METHOD 0x00000080 +#define HTTP_LOG_FIELD_URI_STEM 0x00000100 +#define HTTP_LOG_FIELD_URI_QUERY 0x00000200 +#define HTTP_LOG_FIELD_STATUS 0x00000400 +#define HTTP_LOG_FIELD_WIN32_STATUS 0x00000800 +#define HTTP_LOG_FIELD_BYTES_SENT 0x00001000 +#define HTTP_LOG_FIELD_BYTES_RECV 0x00002000 +#define HTTP_LOG_FIELD_TIME_TAKEN 0x00004000 +#define HTTP_LOG_FIELD_SERVER_PORT 0x00008000 +#define HTTP_LOG_FIELD_USER_AGENT 0x00010000 +#define HTTP_LOG_FIELD_COOKIE 0x00020000 +#define HTTP_LOG_FIELD_REFERER 0x00040000 +#define HTTP_LOG_FIELD_VERSION 0x00080000 +#define HTTP_LOG_FIELD_HOST 0x00100000 +#define HTTP_LOG_FIELD_SUB_STATUS 0x00200000 + +// +// Fields that are used only for error logging. +// + +#define HTTP_LOG_FIELD_CLIENT_PORT 0x00400000 +#define HTTP_LOG_FIELD_URI 0x00800000 +#define HTTP_LOG_FIELD_SITE_ID 0x01000000 +#define HTTP_LOG_FIELD_REASON 0x02000000 +#define HTTP_LOG_FIELD_QUEUE_NAME 0x04000000 + +// +// Defines the logging type. +// + +typedef enum _HTTP_LOGGING_TYPE +{ + HttpLoggingTypeW3C, + HttpLoggingTypeIIS, + HttpLoggingTypeNCSA, + HttpLoggingTypeRaw + ,HttpLoggingTypeMaximum + +} HTTP_LOGGING_TYPE, *PHTTP_LOGGING_TYPE; + +// +// Defines the rollover type for log files. +// + +typedef enum _HTTP_LOGGING_ROLLOVER_TYPE +{ + HttpLoggingRolloverSize, + HttpLoggingRolloverDaily, + HttpLoggingRolloverWeekly, + HttpLoggingRolloverMonthly, + HttpLoggingRolloverHourly + +} HTTP_LOGGING_ROLLOVER_TYPE, *PHTTP_LOGGING_ROLLOVER_TYPE; + +// +// Log file rollover size can not be set lower than the following +// limit. The value is in bytes. +// + +#define HTTP_MIN_ALLOWED_LOG_FILE_ROLLOVER_SIZE ((ULONG)(1 * 1024 * 1024)) + +// +// Logging option flags. When used in the logging configuration alters +// some default logging behaviour. +// +// HTTP_LOGGING_FLAG_LOCAL_TIME_ROLLOVER - This flag is used to change +// the log file rollover to happen by local time based. By default +// log file rollovers happen by GMT time. +// +// HTTP_LOGGING_FLAG_USE_UTF8_CONVERSION - When set the unicode fields +// will be converted to UTF8 multibytes when writting to the log +// files. When this flag is not present, the local code page +// conversion happens. +// +// HTTP_LOGGING_FLAG_LOG_ERRORS_ONLY - +// HTTP_LOGGING_FLAG_LOG_SUCCESS_ONLY - These two flags are used to +// to do selective logging. If neither of them are present both +// types of requests will be logged. Only one these flags can be +// set at a time. They are mutually exclusive. +// + +#define HTTP_LOGGING_FLAG_LOCAL_TIME_ROLLOVER (0x00000001) +#define HTTP_LOGGING_FLAG_USE_UTF8_CONVERSION (0x00000002) +#define HTTP_LOGGING_FLAG_LOG_ERRORS_ONLY (0x00000004) +#define HTTP_LOGGING_FLAG_LOG_SUCCESS_ONLY (0x00000008) + +// +// Configuration structure used for setting the logging property. +// + +typedef struct _HTTP_LOGGING_INFO +{ + // + // Specifies whether this property exists or not. + // + + HTTP_PROPERTY_FLAGS Flags; + + // + // Optional logging flags. + // + + ULONG LoggingFlags; + + // + // Optional informatonal software directive string for W3C type logging. Not + // used for other types of logging. If nothing is provided here HTTPAPI will + // log a default string. Any arbitrary string could be used here to identify + // the application. Length cannot be greater than MAX_PATH. Lenght is in + // bytes. + // + + PCWSTR SoftwareName; + USHORT SoftwareNameLength; + + // + // Log file directory must be a fully qualified path. + // Length must be in number of bytes. + // + + USHORT DirectoryNameLength; + PCWSTR DirectoryName; + + // + // Specifies the format for the log files. + // + + HTTP_LOGGING_TYPE Format; + + // + // Bitmask value indicates which fields to be logged + // if the log format is set to W3C. This must be the 'bitwise or' + // of the HTTP_LOG_FIELD_... values. + // + + ULONG Fields; + + // + // Following fields are reserved they must be NULL and zero.. + // + + PVOID pExtFields; + USHORT NumOfExtFields; + + // + // Reserved must be zero. + // + + USHORT MaxRecordSize; + + // + // Defines the rollover type for the log files. + // + + HTTP_LOGGING_ROLLOVER_TYPE RolloverType; + + // + // Indicates the maximum size (in bytes) after which + // the log files should be rolled over. A value of -1 + // (HTTP_LIMIT_INFINITE) indicates an unlimited size. + // This value is discarded if rollover type is not set to + // HttpLoggingRolloverSize. + // + + ULONG RolloverSize; + + // + // Specifies the security descriptor to be applied to + // the log files and the sub-directories. If null we will + // inherit the system default. This security descriptor must + // be self-relative. + // + + PSECURITY_DESCRIPTOR pSecurityDescriptor; + +} HTTP_LOGGING_INFO, *PHTTP_LOGGING_INFO; + +// +// Binding information. +// + +typedef struct _HTTP_BINDING_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + HANDLE RequestQueueHandle; + +} HTTP_BINDING_INFO, *PHTTP_BINDING_INFO; + +#endif +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + +// +// Defines the protection level types for UrlGroups. +// + +typedef enum _HTTP_PROTECTION_LEVEL_TYPE +{ + // + // This option will allow edge (NAT) traversed traffic, i.e. Teredo + // for the UrlGroup, unless there is an admin rule that overwrites the + // application's intend. + // + + HttpProtectionLevelUnrestricted, + + // + // This setting will ensure that edge (NAT) traversed traffic + // will not be allowed. + // + + HttpProtectionLevelEdgeRestricted, + + // + // Below type is not supported by HTTP API. + // + + HttpProtectionLevelRestricted + + +} HTTP_PROTECTION_LEVEL_TYPE, *PHTTP_PROTECTION_LEVEL_TYPE; + +// +// Controls whether the associated UrlGroup Namespace should receive +// edge traversed traffic. By default this parameter is unspecified. +// + +typedef struct _HTTP_PROTECTION_LEVEL_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + HTTP_PROTECTION_LEVEL_TYPE Level; + +} HTTP_PROTECTION_LEVEL_INFO, *PHTTP_PROTECTION_LEVEL_INFO; + +#endif +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + + +// +// Definitions for request queue manipulation. +// +// These flags are used with HttpCreateRequestQueue() API. +// +// HTTP_CREATE_REQUEST_QUEUE_FLAG_OPEN_EXISTING - To open an existing request +// queue. The request queue name must be supplied. +// +// HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER - Creates the request queue and +// marks that the caller process is not willing to do send/receive (HTTP I/O)on +// the handle directly. +// + +#define HTTP_CREATE_REQUEST_QUEUE_FLAG_OPEN_EXISTING (0x00000001) +#define HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER (0x00000002) + +#endif // _WIN32_WINNT >= 0x0600 + +// +// Flags for HttpReceiveHttpRequest(). +// +// HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY - Specifies that the caller would like +// any available entity body to be copied along with the protocol headers. +// +// HTTP_RECEIVE_REQUEST_FLAG_FLUSH_BODY - Specifies that the caller would like +// all of the entity bodies to be copied along with the protocol headers. +// + +#define HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY 0x00000001 +#define HTTP_RECEIVE_REQUEST_FLAG_FLUSH_BODY 0x00000002 + + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Flags for HttpReceiveRequestEntityBody(). +// +// HTTP_RECEIVE_REQUEST_ENTITY_BODY_FLAG_FILL_BUFFER - Specifies that the +// caller would like the buffer to get filled up with entity bodies unless +// there are no more entity bodies to be copied. +// + +#define HTTP_RECEIVE_REQUEST_ENTITY_BODY_FLAG_FILL_BUFFER 0x00000001 + +#endif // _WIN32_WINNT >= 0x0600 + + +// +// Flags for HttpSendHttpResponse() and HttpSendResponseEntityBody(). +// +// HTTP_SEND_RESPONSE_FLAG_DISCONNECT - Specifies that the network connection +// should be disconnected immediately after sending the response, overriding +// the HTTP protocol's persistent connection features, such as +// "Connection: keep-alive". +// +// HTTP_SEND_RESPONSE_FLAG_MORE_DATA - Specifies that additional entity body +// data will be sent by the caller. +// +// HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA - Specifies that a caller wants the +// response to complete as soon as possible at the cost of buffering partial +// or the entire response. +// +// HTTP_SEND_RESPONSE_FLAG_ENABLE_NAGLING - Specifies that a caller wants to +// enable the TCP nagling algorithm for this particular send. +// +// HTTP_SEND_RESPONSE_FLAG_PROCESS_RANGES - Specifies that for a range request +// a full response content is passed and a caller wants HTTP API to process +// ranges properly. +// + +#define HTTP_SEND_RESPONSE_FLAG_DISCONNECT 0x00000001 +#define HTTP_SEND_RESPONSE_FLAG_MORE_DATA 0x00000002 +#define HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA 0x00000004 +#define HTTP_SEND_RESPONSE_FLAG_ENABLE_NAGLING 0x00000008 +#define HTTP_SEND_RESPONSE_FLAG_PROCESS_RANGES 0x00000020 + + +// +// Flags for HttpFlushResponseCache(). +// +// HTTP_FLUSH_RESPONSE_FLAG_RECURSIVE - Flushes the specified URL and all +// hierarchally-related sub-URLs from the response or fragment cache. +// + +#define HTTP_FLUSH_RESPONSE_FLAG_RECURSIVE 0x00000001 + + +// +// Opaque identifiers for various HTTPAPI objects. +// + +typedef ULONGLONG HTTP_OPAQUE_ID, *PHTTP_OPAQUE_ID; + +typedef HTTP_OPAQUE_ID HTTP_REQUEST_ID, *PHTTP_REQUEST_ID; +typedef HTTP_OPAQUE_ID HTTP_CONNECTION_ID, *PHTTP_CONNECTION_ID; +typedef HTTP_OPAQUE_ID HTTP_RAW_CONNECTION_ID, *PHTTP_RAW_CONNECTION_ID; + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +typedef HTTP_OPAQUE_ID HTTP_URL_GROUP_ID, *PHTTP_URL_GROUP_ID; +typedef HTTP_OPAQUE_ID HTTP_SERVER_SESSION_ID, *PHTTP_SERVER_SESSION_ID; + +#endif // _WIN32_WINNT >= 0x0600 + +// +// Macros for opaque identifier manipulations. +// + +#define HTTP_NULL_ID (0ui64) +#define HTTP_IS_NULL_ID(pid) (HTTP_NULL_ID == *(pid)) +#define HTTP_SET_NULL_ID(pid) (*(pid) = HTTP_NULL_ID) + +// +// This structure defines a file byte range. +// +// If the Length field is HTTP_BYTE_RANGE_TO_EOF then the remainder of the +// file (everything after StartingOffset) is sent. +// + +#define HTTP_BYTE_RANGE_TO_EOF ((ULONGLONG)-1) + +typedef struct _HTTP_BYTE_RANGE +{ + ULARGE_INTEGER StartingOffset; + ULARGE_INTEGER Length; + +} HTTP_BYTE_RANGE, *PHTTP_BYTE_RANGE; + +// +// The type for HTTP protocol version numbers. +// + +typedef struct _HTTP_VERSION +{ + USHORT MajorVersion; + USHORT MinorVersion; + +} HTTP_VERSION, *PHTTP_VERSION; + +// +// Some useful macros for HTTP protocol version manipulation. +// + +#define HTTP_VERSION_UNKNOWN { 0, 0 } +#define HTTP_VERSION_0_9 { 0, 9 } +#define HTTP_VERSION_1_0 { 1, 0 } +#define HTTP_VERSION_1_1 { 1, 1 } + +#define HTTP_SET_VERSION(version, major, minor) \ +do { \ + (version).MajorVersion = (major); \ + (version).MinorVersion = (minor); \ +} while (0, 0) + +#define HTTP_EQUAL_VERSION(version, major, minor) \ + ((version).MajorVersion == (major) && \ + (version).MinorVersion == (minor)) + +#define HTTP_GREATER_VERSION(version, major, minor) \ + ((version).MajorVersion > (major) || \ + ((version).MajorVersion == (major) && \ + (version).MinorVersion > (minor))) + +#define HTTP_LESS_VERSION(version, major, minor) \ + ((version).MajorVersion < (major) || \ + ((version).MajorVersion == (major) && \ + (version).MinorVersion < (minor))) + +#define HTTP_NOT_EQUAL_VERSION(version, major, minor) \ + (!HTTP_EQUAL_VERSION(version, major, minor)) + +#define HTTP_GREATER_EQUAL_VERSION(version, major, minor) \ + (!HTTP_LESS_VERSION(version, major, minor)) + +#define HTTP_LESS_EQUAL_VERSION(version, major, minor) \ + (!HTTP_GREATER_VERSION(version, major, minor)) + +// +// The enum type for HTTP verbs. +// + +typedef enum _HTTP_VERB +{ + HttpVerbUnparsed, + HttpVerbUnknown, + HttpVerbInvalid, + HttpVerbOPTIONS, + HttpVerbGET, + HttpVerbHEAD, + HttpVerbPOST, + HttpVerbPUT, + HttpVerbDELETE, + HttpVerbTRACE, + HttpVerbCONNECT, + HttpVerbTRACK, // used by Microsoft Cluster Server for a non-logged trace + HttpVerbMOVE, + HttpVerbCOPY, + HttpVerbPROPFIND, + HttpVerbPROPPATCH, + HttpVerbMKCOL, + HttpVerbLOCK, + HttpVerbUNLOCK, + HttpVerbSEARCH, + + HttpVerbMaximum + +} HTTP_VERB, *PHTTP_VERB; + +// +// Symbols for all HTTP/1.1 headers and other tokens. Notice request + +// response values overlap. Make sure you know which type of header array +// you are indexing. +// +// These values are used as offsets into arrays and as token values in +// HTTP_KNOWN_HEADER arrays in HTTP_REQUEST_HEADERS and HTTP_RESPONSE_HEADERS. +// +// See RFC 2616, HTTP/1.1, for further explanation of most of these headers. +// + +typedef enum _HTTP_HEADER_ID +{ + HttpHeaderCacheControl = 0, // general-header [section 4.5] + HttpHeaderConnection = 1, // general-header [section 4.5] + HttpHeaderDate = 2, // general-header [section 4.5] + HttpHeaderKeepAlive = 3, // general-header [not in rfc] + HttpHeaderPragma = 4, // general-header [section 4.5] + HttpHeaderTrailer = 5, // general-header [section 4.5] + HttpHeaderTransferEncoding = 6, // general-header [section 4.5] + HttpHeaderUpgrade = 7, // general-header [section 4.5] + HttpHeaderVia = 8, // general-header [section 4.5] + HttpHeaderWarning = 9, // general-header [section 4.5] + + HttpHeaderAllow = 10, // entity-header [section 7.1] + HttpHeaderContentLength = 11, // entity-header [section 7.1] + HttpHeaderContentType = 12, // entity-header [section 7.1] + HttpHeaderContentEncoding = 13, // entity-header [section 7.1] + HttpHeaderContentLanguage = 14, // entity-header [section 7.1] + HttpHeaderContentLocation = 15, // entity-header [section 7.1] + HttpHeaderContentMd5 = 16, // entity-header [section 7.1] + HttpHeaderContentRange = 17, // entity-header [section 7.1] + HttpHeaderExpires = 18, // entity-header [section 7.1] + HttpHeaderLastModified = 19, // entity-header [section 7.1] + + + // Request Headers + + HttpHeaderAccept = 20, // request-header [section 5.3] + HttpHeaderAcceptCharset = 21, // request-header [section 5.3] + HttpHeaderAcceptEncoding = 22, // request-header [section 5.3] + HttpHeaderAcceptLanguage = 23, // request-header [section 5.3] + HttpHeaderAuthorization = 24, // request-header [section 5.3] + HttpHeaderCookie = 25, // request-header [not in rfc] + HttpHeaderExpect = 26, // request-header [section 5.3] + HttpHeaderFrom = 27, // request-header [section 5.3] + HttpHeaderHost = 28, // request-header [section 5.3] + HttpHeaderIfMatch = 29, // request-header [section 5.3] + + HttpHeaderIfModifiedSince = 30, // request-header [section 5.3] + HttpHeaderIfNoneMatch = 31, // request-header [section 5.3] + HttpHeaderIfRange = 32, // request-header [section 5.3] + HttpHeaderIfUnmodifiedSince = 33, // request-header [section 5.3] + HttpHeaderMaxForwards = 34, // request-header [section 5.3] + HttpHeaderProxyAuthorization = 35, // request-header [section 5.3] + HttpHeaderReferer = 36, // request-header [section 5.3] + HttpHeaderRange = 37, // request-header [section 5.3] + HttpHeaderTe = 38, // request-header [section 5.3] + HttpHeaderTranslate = 39, // request-header [webDAV, not in rfc 2518] + + HttpHeaderUserAgent = 40, // request-header [section 5.3] + + HttpHeaderRequestMaximum = 41, + + + // Response Headers + + HttpHeaderAcceptRanges = 20, // response-header [section 6.2] + HttpHeaderAge = 21, // response-header [section 6.2] + HttpHeaderEtag = 22, // response-header [section 6.2] + HttpHeaderLocation = 23, // response-header [section 6.2] + HttpHeaderProxyAuthenticate = 24, // response-header [section 6.2] + HttpHeaderRetryAfter = 25, // response-header [section 6.2] + HttpHeaderServer = 26, // response-header [section 6.2] + HttpHeaderSetCookie = 27, // response-header [not in rfc] + HttpHeaderVary = 28, // response-header [section 6.2] + HttpHeaderWwwAuthenticate = 29, // response-header [section 6.2] + + HttpHeaderResponseMaximum = 30, + + + HttpHeaderMaximum = 41 + +} HTTP_HEADER_ID, *PHTTP_HEADER_ID; + + +// +// Structure defining format of a known HTTP header. +// Name is from HTTP_HEADER_ID. +// + +typedef struct _HTTP_KNOWN_HEADER +{ + USHORT RawValueLength; // in bytes not including the NUL + PCSTR pRawValue; + +} HTTP_KNOWN_HEADER, *PHTTP_KNOWN_HEADER; + +// +// Structure defining format of an unknown header. +// + +typedef struct _HTTP_UNKNOWN_HEADER +{ + USHORT NameLength; // in bytes not including the NUL + USHORT RawValueLength; // in bytes not including the NUL + PCSTR pName; // The header name (minus the ':' character) + PCSTR pRawValue; // The header value + +} HTTP_UNKNOWN_HEADER, *PHTTP_UNKNOWN_HEADER; + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Log fields data structure is used for logging a request. This structure must +// be provided along with an HttpSendHttpResponse or HttpSendResponseEntityBody +// call that concludes the send. +// + +// Base structure is for future versioning. + +typedef enum _HTTP_LOG_DATA_TYPE +{ + HttpLogDataTypeFields = 0 + +} HTTP_LOG_DATA_TYPE, *PHTTP_LOG_DATA_TYPE; + +// should we DECLSPEC_ALIGN(4 or 8) == DECLSPEC_POINTERALIGN? +typedef struct _HTTP_LOG_DATA +{ + HTTP_LOG_DATA_TYPE Type; + +} HTTP_LOG_DATA, *PHTTP_LOG_DATA; + +// Current log fields data structure for of type HttpLogDataTypeFields. + +typedef struct _HTTP_LOG_FIELDS_DATA +{ + HTTP_LOG_DATA Base; + + USHORT UserNameLength; + USHORT UriStemLength; + USHORT ClientIpLength; + USHORT ServerNameLength; + USHORT ServiceNameLength; + USHORT ServerIpLength; + USHORT MethodLength; + USHORT UriQueryLength; + USHORT HostLength; + USHORT UserAgentLength; + USHORT CookieLength; + USHORT ReferrerLength; + + PWCHAR UserName; + PWCHAR UriStem; + PCHAR ClientIp; + PCHAR ServerName; + PCHAR ServiceName; + PCHAR ServerIp; + PCHAR Method; + PCHAR UriQuery; + PCHAR Host; + PCHAR UserAgent; + PCHAR Cookie; + PCHAR Referrer; + + USHORT ServerPort; + USHORT ProtocolStatus; + + ULONG Win32Status; + + HTTP_VERB MethodNum; + + USHORT SubStatus; + +} HTTP_LOG_FIELDS_DATA, *PHTTP_LOG_FIELDS_DATA; + +#endif // _WIN32_WINNT >= 0x0600 + +// +// This enum defines a data source for a particular chunk of data. +// + +typedef enum _HTTP_DATA_CHUNK_TYPE +{ + HttpDataChunkFromMemory, + HttpDataChunkFromFileHandle, + HttpDataChunkFromFragmentCache, + HttpDataChunkFromFragmentCacheEx, + + HttpDataChunkMaximum + +} HTTP_DATA_CHUNK_TYPE, *PHTTP_DATA_CHUNK_TYPE; + + +// +// This structure describes an individual data chunk. +// + +typedef struct _HTTP_DATA_CHUNK +{ + // + // The type of this data chunk. + // + + HTTP_DATA_CHUNK_TYPE DataChunkType; + + // + // The data chunk structures, one per supported data chunk type. + // + + union + { + // + // From-memory data chunk. + // + + struct + { + PVOID pBuffer; + ULONG BufferLength; + + } FromMemory; + + // + // From-file handle data chunk. + // + + struct + { + HTTP_BYTE_RANGE ByteRange; + HANDLE FileHandle; + + } FromFileHandle; + + // + // From-fragment cache data chunk. + // + + struct + { + USHORT FragmentNameLength; // in bytes not including the NUL + PCWSTR pFragmentName; + + } FromFragmentCache; + + // + // From-fragment cache data chunk that specifies a byte range. + // + + struct + { + HTTP_BYTE_RANGE ByteRange; + PCWSTR pFragmentName; // NULL-terminated string + + } FromFragmentCacheEx; + + }; + +} HTTP_DATA_CHUNK, *PHTTP_DATA_CHUNK; + +// +// HTTP API doesn't support 16 bit applications. +// Neither WIN32 nor _WIN64 was defined. +// + +C_ASSERT(TYPE_ALIGNMENT(HTTP_DATA_CHUNK) == sizeof(ULONGLONG)); + +// +// Structure defining format of request headers. +// + +typedef struct _HTTP_REQUEST_HEADERS +{ + // + // The array of unknown HTTP headers and the number of + // entries in the array. + // + + USHORT UnknownHeaderCount; + PHTTP_UNKNOWN_HEADER pUnknownHeaders; + + // + // Trailers - we don't use these currently, reserved for a future release + // + USHORT TrailerCount; // Reserved, must be 0 + PHTTP_UNKNOWN_HEADER pTrailers; // Reserved, must be NULL + + + // + // Known headers. + // + + HTTP_KNOWN_HEADER KnownHeaders[HttpHeaderRequestMaximum]; + +} HTTP_REQUEST_HEADERS, *PHTTP_REQUEST_HEADERS; + +// +// Structure defining format of response headers. +// + +typedef struct _HTTP_RESPONSE_HEADERS +{ + // + // The array of unknown HTTP headers and the number of + // entries in the array. + // + + USHORT UnknownHeaderCount; + PHTTP_UNKNOWN_HEADER pUnknownHeaders; + + // + // Trailers - we don't use these currently, reserved for a future release + // + USHORT TrailerCount; // Reserved, must be 0 + PHTTP_UNKNOWN_HEADER pTrailers; // Reserved, must be NULL + + // + // Known headers. + // + + HTTP_KNOWN_HEADER KnownHeaders[HttpHeaderResponseMaximum]; + +} HTTP_RESPONSE_HEADERS, *PHTTP_RESPONSE_HEADERS; + +// +// Structure defining format of transport address. Use pLocalAddress->sa_family +// to determine whether this is an IPv4 address (AF_INET) or IPv6 (AF_INET6). +// +// pRemoteAddress->sa_family will be the same as pLocalAddress->sa_family. +// +// SOCKADDRs are always in network order, not host order. +// + +typedef struct _HTTP_TRANSPORT_ADDRESS +{ + PSOCKADDR pRemoteAddress; + PSOCKADDR pLocalAddress; + +} HTTP_TRANSPORT_ADDRESS, *PHTTP_TRANSPORT_ADDRESS; + +// +// Structure defining format of cooked URL. +// + +typedef struct _HTTP_COOKED_URL +{ + // + // Pointers overlap and point into pFullUrl. NULL if not present. + // + + USHORT FullUrlLength; // in bytes not including the NUL + USHORT HostLength; // in bytes (no NUL) + USHORT AbsPathLength; // in bytes (no NUL) + USHORT QueryStringLength; // in bytes (no NUL) + + PCWSTR pFullUrl; // points to "http://hostname:port/abs/.../path?query" + PCWSTR pHost; // points to the first char in the hostname + PCWSTR pAbsPath; // Points to the 3rd '/' char + PCWSTR pQueryString; // Points to the 1st '?' char or NULL + +} HTTP_COOKED_URL, *PHTTP_COOKED_URL; + +// +// An opaque context for URL manipulation. +// + +typedef ULONGLONG HTTP_URL_CONTEXT; + + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Optional flags for URL manipulation functions. +// +// HTTP_URL_FLAG_REMOVE_ALL : When this flag is used +// when removing a Url from a url group, regardless of +// the passed URL, all of the Urls from the url group +// will be removed. +// + +#define HTTP_URL_FLAG_REMOVE_ALL 0x00000001 + + +// +// Request Authentication related. +// + +typedef enum _HTTP_AUTH_STATUS +{ + HttpAuthStatusSuccess, + HttpAuthStatusNotAuthenticated, + HttpAuthStatusFailure + +} HTTP_AUTH_STATUS, *PHTTP_AUTH_STATUS; + + +typedef enum _HTTP_REQUEST_AUTH_TYPE +{ + HttpRequestAuthTypeNone = 0, + HttpRequestAuthTypeBasic, + HttpRequestAuthTypeDigest, + HttpRequestAuthTypeNTLM, + HttpRequestAuthTypeNegotiate, + HttpRequestAuthTypeKerberos + + +} HTTP_REQUEST_AUTH_TYPE, *PHTTP_REQUEST_AUTH_TYPE; + +#endif // _WIN32_WINNT >= 0x0600 + +// +// SSL Client certificate information. +// + +typedef struct _HTTP_SSL_CLIENT_CERT_INFO +{ + ULONG CertFlags; + ULONG CertEncodedSize; + PUCHAR pCertEncoded; + HANDLE Token; + BOOLEAN CertDeniedByMapper; + +} HTTP_SSL_CLIENT_CERT_INFO, *PHTTP_SSL_CLIENT_CERT_INFO; + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + +// +// Flag to retrieve secure channel binding with HttpReceiveClientCertificate +// + +#define HTTP_RECEIVE_SECURE_CHANNEL_TOKEN 0x1 + +#endif + +// +// Data computed during SSL handshake. +// + +typedef struct _HTTP_SSL_INFO +{ + USHORT ServerCertKeySize; + USHORT ConnectionKeySize; + ULONG ServerCertIssuerSize; + ULONG ServerCertSubjectSize; + + PCSTR pServerCertIssuer; + PCSTR pServerCertSubject; + + PHTTP_SSL_CLIENT_CERT_INFO pClientCertInfo; + ULONG SslClientCertNegotiated; + +} HTTP_SSL_INFO, *PHTTP_SSL_INFO; + + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Generic request information type. +// + +typedef enum _HTTP_REQUEST_INFO_TYPE +{ + HttpRequestInfoTypeAuth + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 + ,HttpRequestInfoTypeChannelBind +#endif + + +} HTTP_REQUEST_INFO_TYPE, *PHTTP_REQUEST_INFO_TYPE; + +typedef struct _HTTP_REQUEST_INFO +{ + HTTP_REQUEST_INFO_TYPE InfoType; + ULONG InfoLength; + PVOID pInfo; + +} HTTP_REQUEST_INFO, *PHTTP_REQUEST_INFO; + +#ifndef __SECSTATUS_DEFINED__ +typedef LONG SECURITY_STATUS; +#define __SECSTATUS_DEFINED__ +#endif // __SECSTATUS_DEFINED__ + +// +// Authentication request info structure +// + +#define HTTP_REQUEST_AUTH_FLAG_TOKEN_FOR_CACHED_CRED (0x00000001) + +typedef struct _HTTP_REQUEST_AUTH_INFO +{ + HTTP_AUTH_STATUS AuthStatus; + SECURITY_STATUS SecStatus; + + ULONG Flags; + + HTTP_REQUEST_AUTH_TYPE AuthType; + + HANDLE AccessToken; + ULONG ContextAttributes; + + // + // Optional serialized context. + // + + ULONG PackedContextLength; + ULONG PackedContextType; + PVOID PackedContext; + + // + // Optional mutual authentication data and its length in bytes. + // + + ULONG MutualAuthDataLength; + PCHAR pMutualAuthData; + + // + // For SSPI based schemes the package name is returned. Length does + // not include the terminating null and it is in bytes. + // + + USHORT PackageNameLength; + PWSTR pPackageName; + +} HTTP_REQUEST_AUTH_INFO, *PHTTP_REQUEST_AUTH_INFO; + +#endif // _WIN32_WINNT >= 0x0600 + +// +// The structure of an HTTP request for downlevel OS +// + +typedef struct _HTTP_REQUEST_V1 +{ + // + // Request flags (see HTTP_REQUEST_FLAG_* definitions below). + // + + ULONG Flags; + + // + // An opaque request identifier. These values are used by the driver + // to correlate outgoing responses with incoming requests. + // + + HTTP_CONNECTION_ID ConnectionId; + HTTP_REQUEST_ID RequestId; + + // + // The context associated with the URL prefix. + // + + HTTP_URL_CONTEXT UrlContext; + + // + // The HTTP version number. + // + + HTTP_VERSION Version; + + // + // The request verb. + // + + HTTP_VERB Verb; + + // + // The length of the verb string if the Verb field is HttpVerbUnknown. + // + + USHORT UnknownVerbLength; // in bytes not including the NUL + + // + // The length of the raw (uncooked) URL + // + + USHORT RawUrlLength; // in bytes not including the NUL + + // + // Pointer to the verb string if the Verb field is HttpVerbUnknown. + // + + PCSTR pUnknownVerb; + + // + // Pointer to the raw (uncooked) URL + // + + PCSTR pRawUrl; + + // + // The canonicalized Unicode URL + // + + HTTP_COOKED_URL CookedUrl; + + // + // Local and remote transport addresses for the connection. + // + + HTTP_TRANSPORT_ADDRESS Address; + + // + // The request headers. + // + + HTTP_REQUEST_HEADERS Headers; + + // + // The total number of bytes received from network for this request. + // + + ULONGLONG BytesReceived; + + // + // pEntityChunks is an array of EntityChunkCount HTTP_DATA_CHUNKs. The + // entity body is copied only if HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY + // was passed to HttpReceiveHttpRequest(). + // + + USHORT EntityChunkCount; + PHTTP_DATA_CHUNK pEntityChunks; + + // + // SSL connection information. + // + + HTTP_RAW_CONNECTION_ID RawConnectionId; + PHTTP_SSL_INFO pSslInfo; + +} HTTP_REQUEST_V1, *PHTTP_REQUEST_V1; + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// Vista + +// +// Version 2.0 members are defined here +// N.B. One must define V2 elements in two places :( +// This is due to the fact that C++ doesn't allow anonymous +// structure declarations and one must use structure +// inheritance instead. +// + +#ifdef __cplusplus + +typedef struct _HTTP_REQUEST_V2 : _HTTP_REQUEST_V1 +{ + // + // Version 1.0 members are inherited + // Version 2.0 members are declared below + // + + // + // Additional Request Informations. + // + + USHORT RequestInfoCount; + PHTTP_REQUEST_INFO pRequestInfo; +} HTTP_REQUEST_V2, *PHTTP_REQUEST_V2; + +#else // __cplusplus + +typedef struct _HTTP_REQUEST_V2 +{ + struct _HTTP_REQUEST_V1; // Anonymous structure + + // + // Version 2.0 members are declared below + // + + // + // Additional Request Informations. + // + + USHORT RequestInfoCount; + PHTTP_REQUEST_INFO pRequestInfo; +} HTTP_REQUEST_V2, *PHTTP_REQUEST_V2; + +#endif // __cplusplus + +typedef HTTP_REQUEST_V2 HTTP_REQUEST; + +#else // _WIN32_WINNT >= 0x0600 + +typedef HTTP_REQUEST_V1 HTTP_REQUEST; + +#endif // _WIN32_WINNT >= 0x0600 + +typedef HTTP_REQUEST * PHTTP_REQUEST; + + +// +// Values for HTTP_REQUEST::Flags. Zero or more of these may be ORed together. +// +// HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS - there is more entity body +// to be read for this request. Otherwise, there is no entity body or +// all of the entity body was copied into pEntityChunks. +// HTTP_REQUEST_FLAG_IP_ROUTED - This flag indicates that the request has been +// routed based on host plus ip or ip binding.This is a hint for the application +// to include the local ip while flushing kernel cache entries build for this +// request if any. +// + +#define HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS 0x00000001 +#define HTTP_REQUEST_FLAG_IP_ROUTED 0x00000002 + + +// +// This structure describes an HTTP response. +// + +typedef struct _HTTP_RESPONSE_V1 +{ + // + // Response flags (see HTTP_RESPONSE_FLAG_* definitions below). + // + + ULONG Flags; + + // + // The raw HTTP protocol version number. + // + + HTTP_VERSION Version; + + // + // The HTTP status code (e.g., 200). + // + + USHORT StatusCode; + + // + // The HTTP reason (e.g., "OK"). This MUST not contain + // non-ASCII characters (i.e., all chars must be in range 0x20-0x7E). + // + + USHORT ReasonLength; // in bytes not including the '\0' + PCSTR pReason; + + // + // The response headers. + // + + HTTP_RESPONSE_HEADERS Headers; + + // + // pEntityChunks points to an array of EntityChunkCount HTTP_DATA_CHUNKs. + // + + USHORT EntityChunkCount; + PHTTP_DATA_CHUNK pEntityChunks; + +} HTTP_RESPONSE_V1, *PHTTP_RESPONSE_V1; + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Values for HTTP_RESPONSE::Flags. +// +// HTTP_RESPONSE_FLAG_MULTIPLE_ENCODINGS_AVAILABLE - Set this flag if encodings +// other than identity form are available for this resource.This flag is ignored +// if application has not asked for response to be cached. It's used as a hint +// to the Http Server API for content negotiation used when serving from the +// the kernel response cache. +// + +#define HTTP_RESPONSE_FLAG_MULTIPLE_ENCODINGS_AVAILABLE 0x00000001 + + +// Vista + +typedef enum _HTTP_RESPONSE_INFO_TYPE +{ + HttpResponseInfoTypeMultipleKnownHeaders, + HttpResponseInfoTypeAuthenticationProperty, + HttpResponseInfoTypeQoSProperty + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + ,HttpResponseInfoTypeChannelBind +#endif + +} HTTP_RESPONSE_INFO_TYPE, PHTTP_RESPONSE_INFO_TYPE; + +typedef struct _HTTP_RESPONSE_INFO +{ + HTTP_RESPONSE_INFO_TYPE Type; + ULONG Length; + PVOID pInfo; +} HTTP_RESPONSE_INFO, *PHTTP_RESPONSE_INFO; + +#define HTTP_RESPONSE_INFO_FLAGS_PRESERVE_ORDER 0x00000001 + +// +// This structure allows the provision of providing multiple known headers. +// + +typedef struct _HTTP_MULTIPLE_KNOWN_HEADERS +{ + // + // Known header id. + // + + HTTP_HEADER_ID HeaderId; + + ULONG Flags; + + // + // Number of headers of the same category. + // + + USHORT KnownHeaderCount; + + // + // Array of known header structures. + // + + PHTTP_KNOWN_HEADER KnownHeaders; + +} HTTP_MULTIPLE_KNOWN_HEADERS, *PHTTP_MULTIPLE_KNOWN_HEADERS; + +// +// Version 2.0 members are defined here +// N.B. One must define V2 elements in two places :( +// This is due to the fact that C++ doesn't allow anonymous +// structure declarations and one must use structure +// inheritance instead. +// + +#ifdef __cplusplus + +typedef struct _HTTP_RESPONSE_V2 : _HTTP_RESPONSE_V1 +{ + // + // Version 1.0 members are inherited + // Version 2.0 members are declared below + // + + USHORT ResponseInfoCount; + PHTTP_RESPONSE_INFO pResponseInfo; + +} HTTP_RESPONSE_V2, *PHTTP_RESPONSE_V2; + +#else // __cplusplus + +typedef struct _HTTP_RESPONSE_V2 +{ + struct _HTTP_RESPONSE_V1; + + // + // Version 2.0 members are declared below + // + + USHORT ResponseInfoCount; + PHTTP_RESPONSE_INFO pResponseInfo; +} HTTP_RESPONSE_V2, *PHTTP_RESPONSE_V2; + +#endif // __cplusplus + +typedef HTTP_RESPONSE_V2 HTTP_RESPONSE; + +#else // _WIN32_WINNT >= 0x0600 + +typedef HTTP_RESPONSE_V1 HTTP_RESPONSE; + +#endif // _WIN32_WINNT >= 0x0600 + +typedef HTTP_RESPONSE *PHTTP_RESPONSE; + +// +// Api Version. This is used to ensure compatibility between applications and +// httpapi.dll and http.sys. +// +// This must not be confused with the HTTP Protocol version. +// + +typedef struct _HTTPAPI_VERSION +{ + USHORT HttpApiMajorVersion; + USHORT HttpApiMinorVersion; + +} HTTPAPI_VERSION, *PHTTPAPI_VERSION; + + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// Vista + +#define HTTPAPI_VERSION_2 { 2, 0 } + +#endif // _WIN32_WINNT >= 0x0600 + +#define HTTPAPI_VERSION_1 { 1, 0 } + +#define HTTPAPI_EQUAL_VERSION(version, major, minor) \ + ((version).HttpApiMajorVersion == (major) && \ + (version).HttpApiMinorVersion == (minor)) + +#define HTTPAPI_GREATER_VERSION(version, major, minor) \ + ((version).HttpApiMajorVersion > (major) || \ + ((version).HttpApiMajorVersion == (major) && \ + (version).HttpApiMinorVersion > (minor))) + +#define HTTPAPI_LESS_VERSION(version, major, minor) \ + ((version).HttpApiMajorVersion < (major) || \ + ((version).HttpApiMajorVersion == (major) && \ + (version).HttpApiMinorVersion < (minor))) + +#define HTTPAPI_VERSION_GREATER_OR_EQUAL( version, major, minor) \ + (!HTTPAPI_LESS_VERSION(version, major, minor)) + + +// +// Cache control. +// + +// +// This enum defines the available cache policies. +// + +typedef enum _HTTP_CACHE_POLICY_TYPE +{ + HttpCachePolicyNocache, + HttpCachePolicyUserInvalidates, + HttpCachePolicyTimeToLive, + + HttpCachePolicyMaximum + +} HTTP_CACHE_POLICY_TYPE, *PHTTP_CACHE_POLICY_TYPE; + + +// +// Only cache unauthorized GETs + HEADs. +// + +typedef struct _HTTP_CACHE_POLICY +{ + HTTP_CACHE_POLICY_TYPE Policy; + ULONG SecondsToLive; + +} HTTP_CACHE_POLICY, *PHTTP_CACHE_POLICY; + +// +// Enum that is used with HttpSetServiceConfiguration(), +// HttpQueryServiceConfiguration(), and HttpDeleteServiceConfiguration() APIs. +// + +typedef enum _HTTP_SERVICE_CONFIG_ID +{ + HttpServiceConfigIPListenList, // Set, Query & Delete. + HttpServiceConfigSSLCertInfo, // Set, Query & Delete. + HttpServiceConfigUrlAclInfo, // Set, Query & Delete. + HttpServiceConfigTimeout, // Set, Query & Delete. + HttpServiceConfigCache, // Set, Query & Delete. + HttpServiceConfigMax + +} HTTP_SERVICE_CONFIG_ID, *PHTTP_SERVICE_CONFIG_ID; + +// +// Generic Query enum that can be used with HttpQueryServiceConfiguration() +// + +typedef enum _HTTP_SERVICE_CONFIG_QUERY_TYPE +{ + HttpServiceConfigQueryExact, + HttpServiceConfigQueryNext, + HttpServiceConfigQueryMax + +} HTTP_SERVICE_CONFIG_QUERY_TYPE, *PHTTP_SERVICE_CONFIG_QUERY_TYPE; + +// +// This data structure is used to define a key of the SSL certificate hash +// store. +// + +typedef struct _HTTP_SERVICE_CONFIG_SSL_KEY +{ + PSOCKADDR pIpPort; +} HTTP_SERVICE_CONFIG_SSL_KEY, *PHTTP_SERVICE_CONFIG_SSL_KEY; + +// +// This defines a record for the SSL config store. +// + +typedef struct _HTTP_SERVICE_CONFIG_SSL_PARAM +{ + ULONG SslHashLength; // Length of the SSL hash (in bytes) + PVOID pSslHash; // Pointer to the SSL hash + GUID AppId; // A unique identifier that can be used to + // identify the app that has set this parameter + + PWSTR pSslCertStoreName; // Store name to read the server certificate + // from; defaults to "MY". Certificate must be + // stored in the LOCAL_MACHINE context. + + // + // The following settings are used only for client certificates + // + + // + // DefaultCertCheckMode is a bit flag with the following semantics + // 0x1 - Client certificate will not be verified for revocation + // 0x2 - Only cached certificate revocation will be used. + // 0x4 - Enable use of the DefaultRevocationFreshnessTime setting + // 0x10000 - No usage check. + + DWORD DefaultCertCheckMode; + + // + // DefaultRevocationFreshnessTime (seconds) - How often to check for + // an updated Certificate revocation list (CRL). If this value is 0 + // then the new CRL is updated only if the previous one expires + // + + DWORD DefaultRevocationFreshnessTime; + + // + // DefaultRevocationUrlRetrievalTimeout (milliseconds) - Timeout on + // attempt to retrieve certificate revocation list from the remote URL. + // + + DWORD DefaultRevocationUrlRetrievalTimeout; + + // + // pDefaultSslCtlIdentifier - Restrict the certificate issuers that you + // want to trust. Can be a subset of the certificate issuers that are + // trusted by the machine. + // + + PWSTR pDefaultSslCtlIdentifier; + + // + // Store name under LOCAL_MACHINE where Ctl identified by + // pDefaultSslCtlIdentifier is stored. + // + + PWSTR pDefaultSslCtlStoreName; + + // + // Default Flags - see HTTP_SERVICE_CONFIG_SSL_FLAG* below. + // + + DWORD DefaultFlags; + +} HTTP_SERVICE_CONFIG_SSL_PARAM, *PHTTP_SERVICE_CONFIG_SSL_PARAM; + +#define HTTP_SERVICE_CONFIG_SSL_FLAG_USE_DS_MAPPER 0x00000001 +#define HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT 0x00000002 +#if _WIN32_WINNT < 0x0600 +#define HTTP_SERVICE_CONFIG_SSL_FLAG_NO_RAW_FILTER 0x00000004 +#endif // _WIN32_WINNT < 0x0600 + +// +// This data structure is used by HttpSetServiceConfiguration() for the +// config ID HttpServiceConfigSSLCertInfo. It's used to add a new record +// to the SSL store. +// + +typedef struct _HTTP_SERVICE_CONFIG_SSL_SET +{ + HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc; + HTTP_SERVICE_CONFIG_SSL_PARAM ParamDesc; +} HTTP_SERVICE_CONFIG_SSL_SET, *PHTTP_SERVICE_CONFIG_SSL_SET; + +// +// This data structure is used by HttpQueryServiceConfiguration() for the +// config ID HttpServiceConfigSSLCertInfo. It's used to query a particular +// record from the SSL store. +// +// If QueryType is HttpServiceConfigQueryExact, then one particular record of +// the type HTTP_SERVICE_CONFIG_SSL_SET is returned. If the QueryType is +// HttpServiceConfigQueryNext, then the next instance of +// HTTP_SERVICE_CONFIG_SSL_SET is returned. In such cases, the dwToken field +// represents the cursor. For the first item, dwToken has to be 0. +// For subsequent items, dwToken has to be incremented by 1, +// until ERROR_NO_MORE_ITEMS is returned. +// + +typedef struct _HTTP_SERVICE_CONFIG_SSL_QUERY +{ + HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc; + HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc; + DWORD dwToken; +} HTTP_SERVICE_CONFIG_SSL_QUERY, *PHTTP_SERVICE_CONFIG_SSL_QUERY; + +// +// Set/Delete IP Listen-Only List record +// +// Used as a parameter to both HttpSetServiceConfiguration() and +// HttpDeleteServiceConfiguration() functions. +// + +typedef struct _HTTP_SERVICE_CONFIG_IP_LISTEN_PARAM +{ + USHORT AddrLength; + PSOCKADDR pAddress; +} HTTP_SERVICE_CONFIG_IP_LISTEN_PARAM, *PHTTP_SERVICE_CONFIG_IP_LISTEN_PARAM; + +// +// Query IP Listen-Only List record. +// +// Parameter to HttpQueryServiceConfiguration() for the config ID +// HttpServiceConfigIPListenList. On successful return, AddrList +// contains an array of AddrCount elements. Caller must provide a +// large enough buffer to hold all elements in one call. +// +// Caller may determine the type of each returned element by examining +// AddrList[i].ss_family. If it's AF_INET, use ((PSOCKADDR_IN) &AddrList[i]); +// otherwise, for AF_INET6, use ((PSOCKADDR_IN6) &AddrList[i]) +// to select the appropriate address type. +// + +typedef struct _HTTP_SERVICE_CONFIG_IP_LISTEN_QUERY +{ + ULONG AddrCount; + SOCKADDR_STORAGE AddrList[ANYSIZE_ARRAY]; +} HTTP_SERVICE_CONFIG_IP_LISTEN_QUERY, *PHTTP_SERVICE_CONFIG_IP_LISTEN_QUERY; + +// +// URL ACL +// +// +typedef struct _HTTP_SERVICE_CONFIG_URLACL_KEY +{ + PWSTR pUrlPrefix; + +} HTTP_SERVICE_CONFIG_URLACL_KEY, *PHTTP_SERVICE_CONFIG_URLACL_KEY; + +// +// This defines a record for the SSL config store. +// + +typedef struct _HTTP_SERVICE_CONFIG_URLACL_PARAM +{ + PWSTR pStringSecurityDescriptor; +} HTTP_SERVICE_CONFIG_URLACL_PARAM, *PHTTP_SERVICE_CONFIG_URLACL_PARAM; + + +// +// This data structure is used by HttpSetServiceConfiguration for the config ID +// HttpServiceConfigUrlAclInfo. It is used to add a new record to the URL ACL +// store. +// + +typedef struct _HTTP_SERVICE_CONFIG_URLACL_SET +{ + HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc; + HTTP_SERVICE_CONFIG_URLACL_PARAM ParamDesc; +} HTTP_SERVICE_CONFIG_URLACL_SET, *PHTTP_SERVICE_CONFIG_URLACL_SET; + + +// +// This data structure is used by HttpQueryServiceConfiguration() for the +// config ID HttpServiceConfigUrlAclInfo. It's used to query a particular +// record from the URL ACL store. +// +// If QueryType is HttpServiceConfigQueryExact, then one particular record of +// the type HTTP_SERVICE_CONFIG_URLACL_SET is returned. If the QueryType is +// HttpServiceConfigQueryNext, then the next instance of +// HTTP_SERVICE_CONFIG_URLACL_SET is returned. In such cases, the dwToken field +// represents the cursor. For the first item, dwToken has to be 0. +// For subsequent items, dwToken has to be incremented by 1, +// until ERROR_NO_MORE_ITEMS is returned. +// + +typedef struct _HTTP_SERVICE_CONFIG_URLACL_QUERY +{ + HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc; + HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc; + DWORD dwToken; +} HTTP_SERVICE_CONFIG_URLACL_QUERY, *PHTTP_SERVICE_CONFIG_URLACL_QUERY; + +// +// Cache Paramemers +// + +// +// For manipulating global cache parameters. +// The parameters that can be changed or queued are per-uri cache size +// and cached range chunk size. +// + +typedef enum _HTTP_SERVICE_CONFIG_CACHE_KEY +{ + MaxCacheResponseSize = 0, + CacheRangeChunkSize +} HTTP_SERVICE_CONFIG_CACHE_KEY, *PHTTP_SERVICE_CONFIG_CACHE_KEY; + +typedef ULONG HTTP_SERVICE_CONFIG_CACHE_PARAM, + *PHTTP_SERVICE_CONFIG_CACHE_PARAM; + +// +// To set a cache parameter value use the set structure. To query use the key +// directly. When you query a parameter value the output buffer must be exactly +// the sizeof param. +// + +typedef struct { + HTTP_SERVICE_CONFIG_CACHE_KEY KeyDesc; + HTTP_SERVICE_CONFIG_CACHE_PARAM ParamDesc; +} HTTP_SERVICE_CONFIG_CACHE_SET, *PHTTP_SERVICE_CONFIG_CACHE_SET; + + +// +// Define our API linkage. +// + +#if !defined(HTTPAPI_LINKAGE) +#define HTTPAPI_LINKAGE DECLSPEC_IMPORT +#endif // !HTTPAPI_LINKAGE + +// +// Initialize/Terminate APIs. +// + + +// NOTE: MUST be called once before all other APIs + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpInitialize( + IN HTTPAPI_VERSION Version, + IN ULONG Flags, + __reserved IN OUT PVOID pReserved + ); + +// NOTE: MUST be called after final API call returns. + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpTerminate( + IN ULONG Flags, + __reserved IN OUT PVOID pReserved + ); + +// +// HTTP Request Queue manipulation APIs. +// +// This API is maintained for backward competibility for the first +// version of the HTTPAPI and should not be used. Instead the new +// HttpCreateRequestQueue() API must be used. +// +// Use CloseHandle() to release the handles returned by +// HttpCreateHttpHandle() API. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCreateHttpHandle( + OUT PHANDLE pReqQueueHandle, + __reserved IN ULONG Reserved + ); + +#if _WIN32_WINNT >= 0x0600 + +// +// Extended Request Queue manipulation APIs. +// +// Use HttpCloseRequestQueue() API to close the handles +// created by the HttpCreateRequestQueue API. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCreateRequestQueue( + IN HTTPAPI_VERSION Version, + IN PCWSTR pName OPTIONAL, + IN PSECURITY_ATTRIBUTES pSecurityAttributes OPTIONAL, + IN ULONG Flags OPTIONAL, + OUT PHANDLE pReqQueueHandle + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCloseRequestQueue( + IN HANDLE ReqQueueHandle + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSetRequestQueueProperty( + IN HANDLE Handle, + IN HTTP_SERVER_PROPERTY Property, + __in_bcount(PropertyInformationLength) IN PVOID pPropertyInformation, + IN ULONG PropertyInformationLength, + __reserved IN ULONG Reserved, + __reserved IN PVOID pReserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpQueryRequestQueueProperty( + IN HANDLE Handle, + IN HTTP_SERVER_PROPERTY Property, + __out_bcount_part(PropertyInformationLength, *pReturnLength) + OUT PVOID pPropertyInformation, + IN ULONG PropertyInformationLength, + __reserved IN ULONG Reserved, + __out_opt OUT PULONG pReturnLength OPTIONAL, + __reserved IN PVOID pReserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpShutdownRequestQueue( + IN HANDLE ReqQueueHandle + ); + +#endif // _WIN32_WINNT >= 0x0600 + +// +// SSL APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpReceiveClientCertificate( + IN HANDLE ReqQueueHandle, + IN HTTP_CONNECTION_ID ConnectionId, + IN ULONG Flags, + __out_bcount_part(SslClientCertInfoSize, *pBytesReceived) + OUT PHTTP_SSL_CLIENT_CERT_INFO pSslClientCertInfo, + IN ULONG SslClientCertInfoSize, + __out_opt OUT PULONG pBytesReceived OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +#if _WIN32_WINNT >= 0x0600 + +// +// Server Session APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCreateServerSession( + IN HTTPAPI_VERSION Version, + OUT PHTTP_SERVER_SESSION_ID pServerSessionId, + __reserved IN ULONG Reserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCloseServerSession( + IN HTTP_SERVER_SESSION_ID ServerSessionId + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpQueryServerSessionProperty( + IN HTTP_SERVER_SESSION_ID ServerSessionId, + IN HTTP_SERVER_PROPERTY Property, + __out_bcount_part(PropertyInformationLength, *pReturnLength) + OUT PVOID pPropertyInformation, + IN ULONG PropertyInformationLength, + __out_opt OUT PULONG pReturnLength OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSetServerSessionProperty( + IN HTTP_SERVER_SESSION_ID ServerSessionId, + IN HTTP_SERVER_PROPERTY Property, + __in_bcount(PropertyInformationLength) IN PVOID pPropertyInformation, + IN ULONG PropertyInformationLength + ); + +#endif // _WIN32_WINNT >= 0x0600 + +// +// Url Configuration APIs. Can only be used for V1 request queues. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpAddUrl( + IN HANDLE ReqQueueHandle, + IN PCWSTR pFullyQualifiedUrl, + __reserved IN PVOID pReserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpRemoveUrl( + IN HANDLE ReqQueueHandle, + IN PCWSTR pFullyQualifiedUrl + ); + +#if _WIN32_WINNT >= 0x0600 + +// +// Url Group APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCreateUrlGroup( + IN HTTP_SERVER_SESSION_ID ServerSessionId, + OUT PHTTP_URL_GROUP_ID pUrlGroupId, + __reserved IN ULONG Reserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCloseUrlGroup( + IN HTTP_URL_GROUP_ID UrlGroupId + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpAddUrlToUrlGroup( + IN HTTP_URL_GROUP_ID UrlGroupId, + IN PCWSTR pFullyQualifiedUrl, + IN HTTP_URL_CONTEXT UrlContext OPTIONAL, + __reserved IN ULONG Reserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpRemoveUrlFromUrlGroup( + IN HTTP_URL_GROUP_ID UrlGroupId, + IN PCWSTR pFullyQualifiedUrl, + IN ULONG Flags + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSetUrlGroupProperty( + IN HTTP_URL_GROUP_ID UrlGroupId, + IN HTTP_SERVER_PROPERTY Property, + __in_bcount(PropertyInformationLength) IN PVOID pPropertyInformation, + IN ULONG PropertyInformationLength + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpQueryUrlGroupProperty( + IN HTTP_URL_GROUP_ID UrlGroupId, + IN HTTP_SERVER_PROPERTY Property, + __out_bcount_part(PropertyInformationLength, *pReturnLength) + OUT PVOID pPropertyInformation, + IN ULONG PropertyInformationLength, + __out_opt OUT PULONG pReturnLength OPTIONAL + ); + +#endif // _WIN32_WINNT >= 0x0600 + +// +// HTTP Server I/O APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpReceiveHttpRequest( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + __out_bcount_part(RequestBufferLength, *pBytesReceived) + OUT PHTTP_REQUEST pRequestBuffer, + IN ULONG RequestBufferLength, + __out_opt OUT PULONG pBytesReceived OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpReceiveRequestEntityBody( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + __out_bcount_part(BufferLength, *pBytesReceived) OUT PVOID pBuffer, + IN ULONG BufferLength, + __out_opt OUT PULONG pBytesReceived OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +#if _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSendHttpResponse( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + IN PHTTP_RESPONSE pHttpResponse, + IN PHTTP_CACHE_POLICY pCachePolicy OPTIONAL, + OUT PULONG pBytesSent OPTIONAL, + OUT PVOID pReserved1 OPTIONAL, // must be NULL + IN ULONG Reserved2 OPTIONAL, // must be 0 + IN LPOVERLAPPED pOverlapped OPTIONAL, + IN PHTTP_LOG_DATA pLogData OPTIONAL + ); + +#else // _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSendHttpResponse( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + IN PHTTP_RESPONSE pHttpResponse, + IN PVOID pReserved1 OPTIONAL, // must be NULL + OUT PULONG pBytesSent OPTIONAL, + OUT PVOID pReserved2 OPTIONAL, // must be NULL + IN ULONG Reserved3 OPTIONAL, // must be 0 + IN LPOVERLAPPED pOverlapped OPTIONAL, + IN PVOID pReserved4 OPTIONAL // must be NULL + ); + +#endif // _WIN32_WINNT >= 0x0600 + +#if _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSendResponseEntityBody( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + IN USHORT EntityChunkCount OPTIONAL, + __in_ecount_opt(EntityChunkCount) + IN PHTTP_DATA_CHUNK pEntityChunks OPTIONAL, + OUT PULONG pBytesSent OPTIONAL, + OUT PVOID pReserved1 OPTIONAL, // must be NULL + IN ULONG Reserved2 OPTIONAL, // must be 0 + IN LPOVERLAPPED pOverlapped OPTIONAL, + IN PHTTP_LOG_DATA pLogData OPTIONAL + ); + +#else // _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSendResponseEntityBody( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + IN USHORT EntityChunkCount OPTIONAL, + __in_ecount_opt(EntityChunkCount) + IN PHTTP_DATA_CHUNK pEntityChunks OPTIONAL, + OUT PULONG pBytesSent OPTIONAL, + OUT PVOID pReserved1 OPTIONAL, // must be NULL + IN ULONG Reserved2 OPTIONAL, // must be 0 + IN LPOVERLAPPED pOverlapped OPTIONAL, + IN PVOID pReserved3 OPTIONAL // must be NULL + ); + +#endif // _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpWaitForDisconnect( + IN HANDLE ReqQueueHandle, + IN HTTP_CONNECTION_ID ConnectionId, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +#if _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpWaitForDisconnectEx( + IN HANDLE ReqQueueHandle, + IN HTTP_CONNECTION_ID ConnectionId, + __reserved IN ULONG Reserved OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCancelHttpRequest( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpWaitForDemandStart( + IN HANDLE ReqQueueHandle, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + + +#endif // _WIN32_WINNT >= 0x0600 + +// +// Cache manipulation APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpFlushResponseCache( + IN HANDLE ReqQueueHandle, + IN PCWSTR pUrlPrefix, + IN ULONG Flags, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpAddFragmentToCache( + IN HANDLE ReqQueueHandle, + IN PCWSTR pUrlPrefix, + IN PHTTP_DATA_CHUNK pDataChunk, + IN PHTTP_CACHE_POLICY pCachePolicy, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpReadFragmentFromCache( + IN HANDLE ReqQueueHandle, + IN PCWSTR pUrlPrefix, + IN PHTTP_BYTE_RANGE pByteRange OPTIONAL, + __out_bcount_part(BufferLength, *pBytesRead) OUT PVOID pBuffer, + IN ULONG BufferLength, + OUT PULONG pBytesRead OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +// +// Server configuration APIs +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSetServiceConfiguration( + __reserved IN HANDLE ServiceHandle, + IN HTTP_SERVICE_CONFIG_ID ConfigId, + __in_bcount(ConfigInformationLength) IN PVOID pConfigInformation, + IN ULONG ConfigInformationLength, + __reserved IN LPOVERLAPPED pOverlapped + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpDeleteServiceConfiguration( + __reserved IN HANDLE ServiceHandle, + IN HTTP_SERVICE_CONFIG_ID ConfigId, + __in_bcount(ConfigInformationLength) IN PVOID pConfigInformation, + IN ULONG ConfigInformationLength, + __reserved IN LPOVERLAPPED pOverlapped + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpQueryServiceConfiguration( + __reserved IN HANDLE ServiceHandle, + IN HTTP_SERVICE_CONFIG_ID ConfigId, + __in_bcount_opt(InputConfigInformationLength) + IN PVOID pInputConfigInformation OPTIONAL, + IN ULONG InputConfigInformationLength OPTIONAL, + __out_bcount_part_opt(OutputConfigInformationLength, *pReturnLength) + OUT PVOID pOutputConfigInformation OPTIONAL, + IN ULONG OutputConfigInformationLength OPTIONAL, + __out_opt OUT PULONG pReturnLength OPTIONAL, + __reserved IN LPOVERLAPPED pOverlapped + ); + + +#if BUILD_IIS_FOR_XP + +// part of the httpp.h necessary to build for XP + +// +// Counter Group. +// + +// +// Counter property description. +// + +typedef struct _HTTP_PROP_DESC +{ + ULONG Size; + ULONG Offset; + BOOLEAN WPZeros; + +} HTTP_PROP_DESC, *PHTTP_PROP_DESC; + + +// +// This enum defines the available counter groups. +// + +typedef enum _HTTP_COUNTER_GROUP +{ + HttpCounterGroupSite, + HttpCounterGroupGlobal, + + HttpCounterGroupMaximum + +} HTTP_COUNTER_GROUP, *PHTTP_COUNTER_GROUP; + +// +// Structures for IOCTL_HTTP_GET_COUNTERS. +// + +typedef struct _HTTP_COUNTER_INFO +{ + HTTP_SERVER_SESSION_ID ServerSessionId; + HTTP_COUNTER_GROUP CounterGroup; + +} HTTP_COUNTER_INFO, *PHTTP_COUNTER_INFO; + +// +// This enum defines the type of global couters. +// + +typedef enum _HTTP_GLOBAL_COUNTER_ID +{ + HttpGlobalCounterCurrentUrisCached, + HttpGlobalCounterTotalUrisCached, + HttpGlobalCounterUriCacheHits, + HttpGlobalCounterUriCacheMisses, + HttpGlobalCounterUriCacheFlushes, + HttpGlobalCounterTotalFlushedUris, + + HttpGlobalCounterMaximum + +} HTTP_GLOBAL_COUNTER_ID, *PHTTP_GLOBAL_COUNTER_ID; + + +// +// Global couters. +// + +typedef struct _HTTP_GLOBAL_COUNTERS +{ + ULONG CurrentUrisCached; + ULONG TotalUrisCached; + ULONG UriCacheHits; + ULONG UriCacheMisses; + ULONG UriCacheFlushes; + ULONG TotalFlushedUris; + +} HTTP_GLOBAL_COUNTERS, *PHTTP_GLOBAL_COUNTERS; + + +// +// This enum defines the type of site counters. +// NB: HTTP_SITE_COUNTER_ID and HTTP_SITE_COUNTERS +// must be in the same order +// + +typedef enum _HTTP_SITE_COUNTER_ID +{ + HttpSiteCounterBytesSent, + HttpSiteCounterBytesReceived, + HttpSiteCounterBytesTransfered, + HttpSiteCounterCurrentConns, + HttpSiteCounterMaxConnections, + HttpSiteCounterConnAttempts, + HttpSiteCounterGetReqs, + HttpSiteCounterHeadReqs, + HttpSiteCounterAllReqs, + HttpSiteCounterMeasuredIoBandwidthUsage, + HttpSiteCounterCurrentBlockedBandwidthBytes, + HttpSiteCounterTotalBlockedBandwidthBytes, + + HttpSiteCounterMaximum + +} HTTP_SITE_COUNTER_ID, *PHTTP_SITE_COUNTER_ID; + + +// +// Site counters. +// + +typedef struct _HTTP_SITE_COUNTERS +{ + ULONG SiteId; + ULONGLONG BytesSent; + ULONGLONG BytesReceived; + ULONGLONG BytesTransfered; + ULONG CurrentConns; + ULONG MaxConnections; + ULONG ConnAttempts; + ULONG GetReqs; + ULONG HeadReqs; + ULONG AllReqs; + ULONG MeasuredIoBandwidthUsage; + ULONG CurrentBlockedBandwidthBytes; + ULONG TotalBlockedBandwidthBytes; + +} HTTP_SITE_COUNTERS, *PHTTP_SITE_COUNTERS; + +#endif + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // _WIN32_WINNT >= 0x0501 + +#endif // __HTTP_H__ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h new file mode 100644 index 0000000000..6e9437d7ed --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h @@ -0,0 +1,3404 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _HTTPSERV_H_ +#define _HTTPSERV_H_ + +#if (!defined(_WIN64) && !defined(WIN32)) +#error httpserv.h is only supported on WIN32 or WIN64 platforms +#endif + +#include + +#if _WIN32_WINNT >= 0x0600 +#include "http.h" +#else +#include "http_xp.h" +#endif + +// +// Request deterministic notifications +// + +// request is beginning +#define RQ_BEGIN_REQUEST 0x00000001 +// request is being authenticated +#define RQ_AUTHENTICATE_REQUEST 0x00000002 +// request is being authorized +#define RQ_AUTHORIZE_REQUEST 0x00000004 +// satisfy request from cache +#define RQ_RESOLVE_REQUEST_CACHE 0x00000008 +// map handler for request +#define RQ_MAP_REQUEST_HANDLER 0x00000010 +// acquire request state +#define RQ_ACQUIRE_REQUEST_STATE 0x00000020 +// pre-execute handler +#define RQ_PRE_EXECUTE_REQUEST_HANDLER 0x00000040 +// execute handler +#define RQ_EXECUTE_REQUEST_HANDLER 0x00000080 +// release request state +#define RQ_RELEASE_REQUEST_STATE 0x00000100 +// update cache +#define RQ_UPDATE_REQUEST_CACHE 0x00000200 +// log request +#define RQ_LOG_REQUEST 0x00000400 +// end request +#define RQ_END_REQUEST 0x00000800 + +// +// Request non-deterministic notifications +// + +// custom notification +#define RQ_CUSTOM_NOTIFICATION 0x10000000 +// send response +#define RQ_SEND_RESPONSE 0x20000000 +// read entity +#define RQ_READ_ENTITY 0x40000000 +// map a url to a physical path +#define RQ_MAP_PATH 0x80000000 + +// +// Global notifications +// + +// stop accepting new requests +#define GL_STOP_LISTENING 0x00000002 +// cache cleanup before termination +#define GL_CACHE_CLEANUP 0x00000004 +// cache operation +#define GL_CACHE_OPERATION 0x00000010 +// health check +#define GL_HEALTH_CHECK 0x00000020 +// configuration changed +#define GL_CONFIGURATION_CHANGE 0x00000040 +// file changed +#define GL_FILE_CHANGE 0x00000080 +// before request pipeline has started +#define GL_PRE_BEGIN_REQUEST 0x00000100 +// application start +#define GL_APPLICATION_START 0x00000200 +// resolve modules for an application +#define GL_APPLICATION_RESOLVE_MODULES 0x00000400 +// application end +#define GL_APPLICATION_STOP 0x00000800 +// RSCA query +#define GL_RSCA_QUERY 0x00001000 +// trace event was raised +#define GL_TRACE_EVENT 0x00002000 +// custom notification +#define GL_CUSTOM_NOTIFICATION 0x00004000 +// thread cleanup notification +#define GL_THREAD_CLEANUP 0x00008000 +// application preload notification +#define GL_APPLICATION_PRELOAD 0x00010000 + +// +// Request notification return status +// + +typedef enum REQUEST_NOTIFICATION_STATUS +{ + RQ_NOTIFICATION_CONTINUE, // continue processing + // for notification + RQ_NOTIFICATION_PENDING, // suspend processing + // for notification + RQ_NOTIFICATION_FINISH_REQUEST // finish request + // processing +}; + +// +// Out of band return codes +// + +typedef enum GLOBAL_NOTIFICATION_STATUS +{ + GL_NOTIFICATION_CONTINUE, // continue processing + // for notification + GL_NOTIFICATION_HANDLED // finish processing for + // notification +}; + +// +// Priority class aliases +// + +#define PRIORITY_ALIAS_FIRST L"FIRST" +#define PRIORITY_ALIAS_HIGH L"HIGH" +#define PRIORITY_ALIAS_MEDIUM L"MEDIUM" +#define PRIORITY_ALIAS_LOW L"LOW" +#define PRIORITY_ALIAS_LAST L"LAST" + +// +// Cache operations +// + +typedef enum CACHE_OPERATION +{ + CACHE_OPERATION_RETRIEVE, + CACHE_OPERATION_ADD, + CACHE_OPERATION_DELETE, + CACHE_OPERATION_FLUSH_PREFIX, + CACHE_OPERATION_ENUM +}; + +// +// Module identifier +// + +typedef VOID* HTTP_MODULE_ID; + +// +// Flags for IHttpContext->CloneContext() +// + +#define CLONE_FLAG_BASICS 0x01 +#define CLONE_FLAG_HEADERS 0x02 +#define CLONE_FLAG_ENTITY 0x04 +#define CLONE_FLAG_NO_PRECONDITION 0x08 +#define CLONE_FLAG_NO_DAV 0x10 + +// +// Flags for IHttpContext->ExecuteRequest() +// + +#define EXECUTE_FLAG_NO_HEADERS 0x01 +#define EXECUTE_FLAG_IGNORE_CURRENT_INTERCEPTOR 0x02 +#define EXECUTE_FLAG_IGNORE_APPPOOL 0x04 +#define EXECUTE_FLAG_DISABLE_CUSTOM_ERROR 0x08 +#define EXECUTE_FLAG_SAME_URL 0x10 +// do not flush the child response but copy it back to the parent +#define EXECUTE_FLAG_BUFFER_RESPONSE 0x20 +// child response is still eligible for http.sys caching +#define EXECUTE_FLAG_HTTP_CACHE_ELIGIBLE 0x40 + + +// +// forward declarations +// +struct HTTP_TRACE_CONFIGURATION; +struct HTTP_TRACE_EVENT; + +class IWpfSettings; +class IHttpTraceContext; + +// +// Module-specific context descriptor +// +class __declspec(uuid("f1927f76-790e-4ccb-a72e-396bdfdae05d")) +IHttpStoredContext +{ + public: + virtual + VOID + CleanupStoredContext( + VOID + ) = 0; +}; + +// +// Context container +// +class __declspec(uuid("d7fad7c9-aa27-4ab9-bd60-e55ccba3f5dc")) +IHttpModuleContextContainer +{ + public: + virtual + IHttpStoredContext * + GetModuleContext( + IN HTTP_MODULE_ID moduleId + ) = 0; + + virtual + HRESULT + SetModuleContext( + IN IHttpStoredContext * ppStoredContext, + IN HTTP_MODULE_ID moduleId + ) = 0; +}; + +// +// Dispensed context container +// +class __declspec(uuid("2ae49359-95dd-4e48-ae20-c0cb9d0bc03a")) +IDispensedHttpModuleContextContainer : public IHttpModuleContextContainer +{ +public: + virtual + VOID + ReleaseContainer( + VOID + ) = 0; +}; + +// +// Performance counter descriptor +// +class __declspec(uuid("bdfc4c4a-12a4-4744-87d8-765eb320c59f")) +IHttpPerfCounterInfo +{ + public: + virtual + VOID + IncrementCounter( + DWORD dwCounterIndex, + DWORD dwValue = 1 + ) = 0; + + virtual + VOID + DecrementCounter( + DWORD dwCounterIndex, + DWORD dwValue = 1 + ) = 0; +}; + +// +// Application descriptor +// +class __declspec(uuid("3f75d9e6-1075-422c-ad89-93a85f2d7bdc")) +IHttpApplication +{ + public: + virtual + PCWSTR + GetApplicationPhysicalPath( + VOID + ) const = 0; + + virtual + PCWSTR + GetApplicationId( + VOID + ) const = 0; + + virtual + PCWSTR + GetAppConfigPath( + VOID + ) const = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; +}; + +// +// URI cache entry descriptor +// +class __declspec(uuid("7e0e6167-0094-49a1-8287-ecf6dc6e73a6")) +IHttpUrlInfo +{ + public: + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + BOOL + IsFrequentlyHit( + VOID + ) const = 0; +}; + +// +// Script map descriptor +// +class __declspec(uuid("d7fe3d77-68bc-4d4a-851f-eec9fb68017c")) +IScriptMapInfo +{ + public: + virtual + PCWSTR + GetPath( + VOID + ) const = 0; + + virtual + PCSTR + GetAllowedVerbs( + VOID + ) const = 0; + + virtual + PCWSTR + GetModules( + OUT DWORD * pcchModules = NULL + ) const = 0; + + virtual + PCWSTR + GetScriptProcessor( + OUT DWORD * pcchScriptProcessor = NULL + ) const = 0; + + virtual + PCWSTR + GetManagedType( + OUT DWORD * pcchManagedType = NULL + ) const = 0; + + virtual + BOOL + GetAllowPathInfoForScriptMappings( + VOID + ) const = 0; + + virtual + DWORD + GetRequiredAccess( + VOID + ) const = 0; + + virtual + DWORD + GetResourceType( + VOID + ) const = 0; + + virtual + BOOL + GetIsStarScriptMap( + VOID + ) const = 0; + + virtual + DWORD + GetResponseBufferLimit( + VOID + ) const = 0; + + virtual + PCWSTR + GetName( + VOID + ) const = 0; +}; + +class __declspec(uuid("fd86e6de-fb0e-47dd-820a-e0da12be46e9")) +IHttpTokenEntry; + +// +// Metadata descriptor +// +class __declspec(uuid("48b10633-825d-495e-93b0-225380053e8e")) +IMetadataInfo +{ + public: + virtual + PCWSTR + GetMetaPath( + VOID + ) const = 0; + + virtual + PCWSTR + GetVrPath( + VOID + ) const = 0; + + virtual + IHttpTokenEntry * + GetVrToken( + VOID + ) = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; +}; + +// +// Provides an interface to an HTTP request object. The methods on this +// class can be used to inspect and modify request data. +// +class __declspec(uuid("e8698f7e-576e-4cac-a309-67435355faef")) +IHttpRequest +{ + public: + virtual + HTTP_REQUEST * + GetRawHttpRequest( + VOID + ) = 0; + + virtual + const HTTP_REQUEST * + GetRawHttpRequest( + VOID + ) const = 0; + + virtual + PCSTR + GetHeader( + IN PCSTR pszHeaderName, + OUT USHORT * pcchHeaderValue = NULL + ) const = 0; + + virtual + PCSTR + GetHeader( + IN HTTP_HEADER_ID ulHeaderIndex, + OUT USHORT * pcchHeaderValue = NULL + ) const = 0; + + virtual + HRESULT + SetHeader( + IN PCSTR pszHeaderName, + IN PCSTR pszHeaderValue, + IN USHORT cchHeaderValue, + IN BOOL fReplace + ) = 0; + + virtual + HRESULT + SetHeader( + IN HTTP_HEADER_ID ulHeaderIndex, + IN PCSTR pszHeaderValue, + IN USHORT cchHeaderValue, + IN BOOL fReplace + ) = 0; + + virtual + HRESULT + DeleteHeader( + IN PCSTR pszHeaderName + ) = 0; + + virtual + HRESULT + DeleteHeader( + IN HTTP_HEADER_ID ulHeaderIndex + ) = 0; + + virtual + PCSTR + GetHttpMethod( + VOID + ) const = 0; + + virtual + HRESULT + SetHttpMethod( + IN PCSTR pszHttpMethod + ) = 0; + + virtual + HRESULT + SetUrl( + IN PCWSTR pszUrl, + IN DWORD cchUrl, + IN BOOL fResetQueryString + ) = 0; + + virtual + HRESULT + SetUrl( + IN PCSTR pszUrl, + IN DWORD cchUrl, + IN BOOL fResetQueryString + ) = 0; + + virtual + BOOL + GetUrlChanged( + VOID + ) const = 0; + + virtual + PCWSTR + GetForwardedUrl( + VOID + ) const = 0; + + virtual + PSOCKADDR + GetLocalAddress( + VOID + ) const = 0; + + virtual + PSOCKADDR + GetRemoteAddress( + VOID + ) const = 0; + + virtual + HRESULT + ReadEntityBody( + OUT VOID * pvBuffer, + IN DWORD cbBuffer, + IN BOOL fAsync, + OUT DWORD * pcbBytesReceived, + OUT BOOL * pfCompletionPending = NULL + ) = 0; + + virtual + HRESULT + InsertEntityBody( + IN VOID * pvBuffer, + IN DWORD cbBuffer + ) = 0; + + virtual + DWORD + GetRemainingEntityBytes( + VOID + ) = 0; + + virtual + VOID + GetHttpVersion( + OUT USHORT * pMajorVersion, + OUT USHORT * pMinorVersion + ) const = 0; + + virtual + HRESULT + GetClientCertificate( + OUT HTTP_SSL_CLIENT_CERT_INFO ** ppClientCertInfo, + OUT BOOL * pfClientCertNegotiated + ) = 0; + + virtual + HRESULT + NegotiateClientCertificate( + IN BOOL fAsync, + OUT BOOL * pfCompletionPending = NULL + ) = 0; + + virtual + DWORD + GetSiteId( + VOID + ) const = 0; + + virtual + HRESULT + GetHeaderChanges( + IN DWORD dwOldChangeNumber, + OUT DWORD * pdwNewChangeNumber, + IN OUT PCSTR knownHeaderSnapshot[HttpHeaderRequestMaximum], + IN OUT DWORD * pdwUnknownHeaderSnapshot, + IN OUT PCSTR **ppUnknownHeaderNameSnapshot, + IN OUT PCSTR **ppUnknownHeaderValueSnapshot, + __out_ecount(HttpHeaderRequestMaximum+1) + DWORD diffedKnownHeaderIndices[HttpHeaderRequestMaximum+1], + OUT DWORD * pdwDiffedUnknownHeaders, + OUT DWORD **ppDiffedUnknownHeaderIndices + ) = 0; +}; + +class __declspec(uuid("d9244ae1-51f8-4aa1-a66d-19277c33e610")) +IHttpRequest2 : public IHttpRequest +{ + public: + virtual + HRESULT + GetChannelBindingToken( + __deref_out_bcount_part(*pTokenSize, *pTokenSize) + PBYTE * ppToken, + DWORD * pTokenSize + ) = 0; +}; + +class __declspec(uuid("cb1c40ca-70f2-41a0-add2-881f5ef57388")) +IHttpCachePolicy +{ + public: + virtual + HTTP_CACHE_POLICY * + GetKernelCachePolicy( + VOID + ) = 0; + + virtual + VOID + SetKernelCacheInvalidatorSet( + VOID + ) = 0; + + virtual + HTTP_CACHE_POLICY * + GetUserCachePolicy( + VOID + ) = 0; + + virtual + HRESULT + AppendVaryByHeader( + PCSTR pszHeader + ) = 0; + + virtual + PCSTR + GetVaryByHeaders( + VOID + ) const = 0; + + virtual + HRESULT + AppendVaryByQueryString( + PCSTR pszParam + ) = 0; + + virtual + PCSTR + GetVaryByQueryStrings( + VOID + ) const = 0; + + virtual + HRESULT + SetVaryByValue( + PCSTR pszValue + ) = 0; + + virtual + PCSTR + GetVaryByValue( + VOID + ) const = 0; + + virtual + BOOL + IsUserCacheEnabled( + VOID + ) const = 0; + + virtual + VOID + DisableUserCache( + VOID + ) = 0; + + virtual + BOOL + IsCached( + VOID + ) const = 0; + + virtual + VOID + SetIsCached( + VOID + ) = 0; + + virtual + BOOL + GetKernelCacheInvalidatorSet( + VOID + ) const = 0; +}; + +class __declspec(uuid("9f4ba807-050e-4495-ae55-8870f7e9194a")) +IHttpCachePolicy2 : public IHttpCachePolicy +{ + public: + virtual + BOOL + IsForceUpdateSet( + VOID + ) const = 0; + + virtual + VOID + SetForceUpdate( + VOID + ) = 0; +}; + +// +// Response descriptor +// +class __declspec(uuid("7e1c6b38-628f-4e6c-95dc-41237eb7f95e")) +IHttpResponse +{ + public: + virtual + HTTP_RESPONSE * + GetRawHttpResponse( + VOID + ) = 0; + + virtual + const HTTP_RESPONSE * + GetRawHttpResponse( + VOID + ) const = 0; + + virtual + IHttpCachePolicy * + GetCachePolicy( + VOID + ) = 0; + + virtual + HRESULT + SetStatus( + IN USHORT statusCode, + IN PCSTR pszReason, + IN USHORT uSubStatus = 0, + IN HRESULT hrErrorToReport = S_OK, + IN IAppHostConfigException *pException = NULL, + IN BOOL fTrySkipCustomErrors = FALSE + ) = 0; + + virtual + HRESULT + SetHeader( + IN PCSTR pszHeaderName, + IN PCSTR pszHeaderValue, + IN USHORT cchHeaderValue, + IN BOOL fReplace + ) = 0; + + virtual + HRESULT + SetHeader( + IN HTTP_HEADER_ID ulHeaderIndex, + IN PCSTR pszHeaderValue, + IN USHORT cchHeaderValue, + IN BOOL fReplace + ) = 0; + + virtual + HRESULT + DeleteHeader( + IN PCSTR pszHeaderName + ) = 0; + + virtual + HRESULT + DeleteHeader( + IN HTTP_HEADER_ID ulHeaderIndex + ) = 0; + + virtual + PCSTR + GetHeader( + IN PCSTR pszHeaderName, + OUT USHORT * pcchHeaderValue = NULL + ) const = 0; + + virtual + PCSTR + GetHeader( + IN HTTP_HEADER_ID ulHeaderIndex, + OUT USHORT * pcchHeaderValue = NULL + ) const = 0; + + virtual + VOID + Clear( + VOID + ) = 0; + + virtual + VOID + ClearHeaders( + VOID + ) = 0; + + virtual + VOID + SetNeedDisconnect( + VOID + ) = 0; + + virtual + VOID + ResetConnection( + VOID + ) = 0; + + virtual + VOID + DisableKernelCache( + ULONG reason = 9 + ) = 0; + + virtual + BOOL + GetKernelCacheEnabled( + VOID + ) const = 0; + + virtual + VOID + SuppressHeaders( + VOID + ) = 0; + + virtual + BOOL + GetHeadersSuppressed( + VOID + ) const = 0; + + virtual + HRESULT + Flush( + IN BOOL fAsync, + IN BOOL fMoreData, + OUT DWORD * pcbSent, + OUT BOOL * pfCompletionExpected = NULL + ) = 0; + + virtual + HRESULT + Redirect( + IN PCSTR pszUrl, + IN BOOL fResetStatusCode = TRUE, + IN BOOL fIncludeParameters = FALSE + ) = 0; + + virtual + HRESULT + WriteEntityChunkByReference( + IN HTTP_DATA_CHUNK * pDataChunk, + IN LONG lInsertPosition = -1 + ) = 0; + + virtual + HRESULT + WriteEntityChunks( + IN HTTP_DATA_CHUNK * pDataChunks, + IN DWORD nChunks, + IN BOOL fAsync, + IN BOOL fMoreData, + OUT DWORD * pcbSent, + OUT BOOL * pfCompletionExpected = NULL + ) = 0; + + virtual + VOID + DisableBuffering( + VOID + ) = 0; + + virtual + VOID + GetStatus( + OUT USHORT * pStatusCode, + OUT USHORT * pSubStatus = NULL, + OUT PCSTR * ppszReason = NULL, + OUT USHORT * pcchReason = NULL, + OUT HRESULT * phrErrorToReport = NULL, + OUT PCWSTR * ppszModule = NULL, + OUT DWORD * pdwNotification = NULL, + OUT IAppHostConfigException ** ppException = NULL, + OUT BOOL * pfTrySkipCustomErrors = NULL + ) = 0; + + virtual + HRESULT + SetErrorDescription( + IN PCWSTR pszDescription, + IN DWORD cchDescription, + IN BOOL fHtmlEncode = TRUE + ) = 0; + + virtual + PCWSTR + GetErrorDescription( + OUT DWORD * pcchDescription = NULL + ) = 0; + + virtual + HRESULT + GetHeaderChanges( + IN DWORD dwOldChangeNumber, + OUT DWORD * pdwNewChangeNumber, + IN OUT PCSTR knownHeaderSnapshot[HttpHeaderResponseMaximum], + IN OUT DWORD * pdwUnknownHeaderSnapshot, + IN OUT PCSTR **ppUnknownHeaderNameSnapshot, + IN OUT PCSTR **ppUnknownHeaderValueSnapshot, + __out_ecount(HttpHeaderResponseMaximum+1) + DWORD diffedKnownHeaderIndices[HttpHeaderResponseMaximum+1], + OUT DWORD * pdwDiffedUnknownHeaders, + OUT DWORD **ppDiffedUnknownHeaderIndices + ) = 0; + + virtual + VOID + CloseConnection( + VOID + ) = 0; +}; + +// +// User descriptor +// +class __declspec(uuid("8059e6f8-10ce-4d61-b47e-5a1d8d9a8b67")) +IHttpUser +{ + public: + virtual + PCWSTR + GetRemoteUserName( + VOID + ) = 0; + + virtual + PCWSTR + GetUserName( + VOID + ) = 0; + + virtual + PCWSTR + GetAuthenticationType( + VOID + ) = 0; + + virtual + PCWSTR + GetPassword( + VOID + ) = 0; + + virtual + HANDLE + GetImpersonationToken( + VOID + ) = 0; + + virtual + HANDLE + GetPrimaryToken( + VOID + ) = 0; + + virtual + VOID + ReferenceUser( + VOID + ) = 0; + + virtual + VOID + DereferenceUser( + VOID + ) = 0; + + virtual + BOOL + SupportsIsInRole( + VOID + ) = 0; + + virtual + HRESULT + IsInRole( + IN PCWSTR pszRoleName, + OUT BOOL * pfInRole + ) = 0; + + virtual + PVOID + GetUserVariable( + IN PCSTR pszVariableName + ) = 0; +}; + +#define HTTP_USER_VARIABLE_SID "SID" +#define HTTP_USER_VARIABLE_CTXT_HANDLE "CtxtHandle" +#define HTTP_USER_VARIABLE_CRED_HANDLE "CredHandle" + +class __declspec(uuid("841d9a71-75f4-4626-8b97-66046ca7e45b")) +IHttpConnectionStoredContext : public IHttpStoredContext +{ + public: + virtual + VOID + NotifyDisconnect( + VOID + ) = 0; +}; + +class __declspec(uuid("f3dd2fb3-4d11-4295-b8ab-4cb667add1fe")) +IHttpConnectionModuleContextContainer : public IHttpModuleContextContainer +{ + public: + virtual + IHttpConnectionStoredContext * + GetConnectionModuleContext( + IN HTTP_MODULE_ID moduleId + ) = 0; + + virtual + HRESULT + SetConnectionModuleContext( + IN IHttpConnectionStoredContext * ppStoredContext, + IN HTTP_MODULE_ID moduleId + ) = 0; +}; + +// +// Connection descriptor +// +class __declspec(uuid("d9a5de00-3346-4599-9826-fe88565e1226")) +IHttpConnection +{ + public: + virtual + BOOL + IsConnected( + VOID + ) const = 0; + + virtual + VOID * + AllocateMemory( + DWORD cbAllocation + ) = 0; + + virtual + IHttpConnectionModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; +}; + +// +// Forward declarations +// +class __declspec(uuid("71e95595-8c74-44d9-88a9-f5112d5f5900")) +IHttpFileInfo; + +class __declspec(uuid("eb16a6ec-ba5d-436f-bf24-3ede13906450")) +IHttpSite; + +class __declspec(uuid("671e6d34-9380-4df4-b453-91129df02b24")) +ICustomNotificationProvider; + +class __declspec(uuid("6f3f657d-2fb8-43c6-a096-5064b41f0580")) +IHttpEventProvider; + +class CHttpModule; + +// +// IHttpContext extended interface versions (deprecated) +// +enum HTTP_CONTEXT_INTERFACE_VERSION +{ +}; + +// +// Context object representing the processing of an HTTP request +// +class __declspec(uuid("424c1b8c-a1ba-44d7-ac98-9f8f457701a5")) +IHttpContext +{ + public: + virtual + IHttpSite * + GetSite( + VOID + ) = 0; + + virtual + IHttpApplication * + GetApplication( + VOID + ) = 0; + + virtual + IHttpConnection * + GetConnection( + VOID + ) = 0; + + virtual + IHttpRequest * + GetRequest( + VOID + ) = 0; + + virtual + IHttpResponse * + GetResponse( + VOID + ) = 0; + + virtual + BOOL + GetResponseHeadersSent( + VOID + ) const = 0; + + virtual + IHttpUser * + GetUser( + VOID + ) const = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + VOID + IndicateCompletion( + IN REQUEST_NOTIFICATION_STATUS notificationStatus + ) = 0; + + virtual + HRESULT + PostCompletion( + IN DWORD cbBytes + ) = 0; + + virtual + VOID + DisableNotifications( + IN DWORD dwNotifications, + IN DWORD dwPostNotifications + ) = 0; + + virtual + BOOL + GetNextNotification( + IN REQUEST_NOTIFICATION_STATUS status, + OUT DWORD * pdwNotification, + OUT BOOL * pfIsPostNotification, + OUT CHttpModule ** ppModuleInfo, + OUT IHttpEventProvider ** ppRequestOutput + ) = 0; + + virtual + BOOL + GetIsLastNotification( + IN REQUEST_NOTIFICATION_STATUS status + ) = 0; + + virtual + HRESULT + ExecuteRequest( + IN BOOL fAsync, + IN IHttpContext * pHttpContext, + IN DWORD dwExecuteFlags, + IN IHttpUser * pHttpUser, + OUT BOOL * pfCompletionExpected = NULL + ) = 0; + + virtual + DWORD + GetExecuteFlags( + VOID + ) const = 0; + + virtual + HRESULT + GetServerVariable( + PCSTR pszVariableName, + __deref_out_ecount(*pcchValueLength) PCWSTR * ppszValue, + __out DWORD * pcchValueLength + ) = 0; + + virtual + HRESULT + GetServerVariable( + PCSTR pszVariableName, + __deref_out_ecount(*pcchValueLength) PCSTR * ppszValue, + __out DWORD * pcchValueLength + ) = 0; + + virtual + HRESULT + SetServerVariable( + PCSTR pszVariableName, + PCWSTR pszVariableValue + ) = 0; + + virtual + VOID * + AllocateRequestMemory( + IN DWORD cbAllocation + ) = 0; + + virtual + IHttpUrlInfo * + GetUrlInfo( + VOID + ) = 0; + + virtual + IMetadataInfo * + GetMetadata( + VOID + ) = 0; + + virtual + PCWSTR + GetPhysicalPath( + OUT DWORD * pcchPhysicalPath = NULL + ) = 0; + + virtual + PCWSTR + GetScriptName( + OUT DWORD * pcchScriptName = NULL + ) const = 0; + + virtual + PCWSTR + GetScriptTranslated( + OUT DWORD * pcchScriptTranslated = NULL + ) = 0; + + virtual + IScriptMapInfo * + GetScriptMap( + VOID + ) const = 0; + + virtual + VOID + SetRequestHandled( + VOID + ) = 0; + + virtual + IHttpFileInfo * + GetFileInfo( + VOID + ) const = 0; + + virtual + HRESULT + MapPath( + PCWSTR pszUrl, + __out_bcount_opt(*pcbPhysicalPath) PWSTR pszPhysicalPath, + IN OUT DWORD * pcbPhysicalPath + ) = 0; + + virtual + HRESULT + NotifyCustomNotification( + ICustomNotificationProvider * pCustomOutput, + OUT BOOL * pfCompletionExpected + ) = 0; + + virtual + IHttpContext * + GetParentContext( + VOID + ) const = 0; + + virtual + IHttpContext * + GetRootContext( + VOID + ) const = 0; + + virtual + HRESULT + CloneContext( + IN DWORD dwCloneFlags, + OUT IHttpContext ** ppHttpContext + ) = 0; + + virtual + HRESULT + ReleaseClonedContext( + VOID + ) = 0; + + virtual + HRESULT + GetCurrentExecutionStats( + OUT DWORD * pdwNotification, + OUT DWORD * pdwNotificationStartTickCount = NULL, + OUT PCWSTR * ppszModule = NULL, + OUT DWORD * pdwModuleStartTickCount = NULL, + OUT DWORD * pdwAsyncNotification = NULL, + OUT DWORD * pdwAsyncNotificationStartTickCount = NULL + ) const = 0; + + virtual + IHttpTraceContext * + GetTraceContext( + VOID + ) const = 0; + + virtual + HRESULT + GetServerVarChanges( + IN DWORD dwOldChangeNumber, + OUT DWORD * pdwNewChangeNumber, + IN OUT DWORD * pdwVariableSnapshot, + IN OUT PCSTR ** ppVariableNameSnapshot, + IN OUT PCWSTR ** ppVariableValueSnapshot, + OUT DWORD * pdwDiffedVariables, + OUT DWORD ** ppDiffedVariableIndices + ) = 0; + + virtual + HRESULT + CancelIo( + VOID + ) = 0; + + virtual + HRESULT + MapHandler( + IN DWORD dwSiteId, + IN PCWSTR pszSiteName, + IN PCWSTR pszUrl, + IN PCSTR pszVerb, + OUT IScriptMapInfo ** ppScriptMap, + IN BOOL fIgnoreWildcardMappings = FALSE + ) = 0; + + __declspec(deprecated("This method is deprecated. Use the HttpGetExtendedInterface helper function instead.")) + virtual + HRESULT + GetExtendedInterface( + IN HTTP_CONTEXT_INTERFACE_VERSION version, + OUT PVOID * ppInterface + ) = 0; +}; + +class __declspec(uuid("9f9098d5-915c-4294-a52e-66532a232bc9")) +IHttpTraceContext +{ +public: + virtual + HRESULT + GetTraceConfiguration( + IN OUT HTTP_TRACE_CONFIGURATION * pHttpTraceConfiguration + ) = 0; + + virtual + HRESULT + SetTraceConfiguration( + IN HTTP_MODULE_ID moduleId, + IN HTTP_TRACE_CONFIGURATION * pHttpTraceConfiguration, + IN DWORD cHttpTraceConfiguration = 1 + ) = 0; + + virtual + HRESULT + RaiseTraceEvent( + IN HTTP_TRACE_EVENT * pTraceEvent + ) = 0; + + virtual + LPCGUID + GetTraceActivityId( + ) = 0; + + virtual + HRESULT + QuickTrace( + IN PCWSTR pszData1, + IN PCWSTR pszData2 = NULL, + IN HRESULT hrLastError = S_OK, + // + // 4 == TRACE_LEVEL_INFORMATION + // + IN UCHAR Level = 4 + ) = 0; +}; + +class __declspec(uuid("37776aff-852e-4eec-93a5-b85a285a95b8")) +IHttpCacheSpecificData; + +// +// Cache helpers +// +class __declspec(uuid("cdef2aad-20b3-4512-b1b1-094b3844aeb2")) +IHttpCacheKey +{ + public: + virtual + DWORD + GetHash( + VOID + ) const = 0; + + virtual + PCWSTR + GetCacheName( + VOID + ) const = 0; + + virtual + bool + GetIsEqual( + IHttpCacheKey * pCacheCompareKey + ) const = 0; + + virtual + bool + GetIsPrefix( + IHttpCacheKey * pCacheCompareKey + ) const = 0; + + virtual + VOID + Enum( + IHttpCacheSpecificData * + ) = 0; +}; + +class __declspec(uuid("37776aff-852e-4eec-93a5-b85a285a95b8")) +IHttpCacheSpecificData +{ + public: + virtual + IHttpCacheKey * + GetCacheKey( + VOID + ) const = 0; + + virtual + VOID + ReferenceCacheData( + VOID + ) = 0; + + virtual + VOID + DereferenceCacheData( + VOID + ) = 0; + + virtual + VOID + ResetTTL( + VOID + ) = 0; + + virtual + VOID + DecrementTTL( + OUT BOOL *pfTTLExpired + ) = 0; + + virtual + VOID + SetFlushed( + VOID + ) = 0; + + virtual + BOOL + GetFlushed( + VOID + ) const = 0; +}; + +// +// Site descriptor +// +class __declspec(uuid("eb16a6ec-ba5d-436f-bf24-3ede13906450")) +IHttpSite +{ + public: + virtual + DWORD + GetSiteId( + VOID + ) const = 0; + + virtual + PCWSTR + GetSiteName( + VOID + ) const = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + IHttpPerfCounterInfo * + GetPerfCounterInfo( + VOID + ) = 0; +}; + +// +// File change monitor +// +// +class __declspec(uuid("985422da-b0cf-473b-ba9e-8148ceb3e240")) +IHttpFileMonitor +{ + public: + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + VOID + DereferenceFileMonitor( + VOID + ) = 0; +}; + +// +// File descriptor +// +// +class __declspec(uuid("71e95595-8c74-44d9-88a9-f5112d5f5900")) +IHttpFileInfo : public IHttpCacheSpecificData +{ + public: + virtual + DWORD + GetAttributes( + VOID + ) const = 0; + + virtual + VOID + GetSize( + OUT ULARGE_INTEGER * pliSize + ) const = 0; + + virtual + const BYTE * + GetFileBuffer( + VOID + ) const = 0; + + virtual + HANDLE + GetFileHandle( + VOID + ) const = 0; + + virtual + PCWSTR + GetFilePath( + VOID + ) const = 0; + + virtual + PCSTR + GetETag( + OUT USHORT * pcchETag = NULL + ) const = 0; + + virtual + VOID + GetLastModifiedTime( + OUT FILETIME * pFileTime + ) const = 0; + + virtual + PCSTR + GetLastModifiedString( + VOID + ) const = 0; + + virtual + BOOL + GetHttpCacheAllowed( + OUT DWORD * pSecondsToLive + ) const = 0; + + virtual + HRESULT + AccessCheck( + IN HANDLE hUserToken, + IN PSID pUserSid + ) = 0; + + virtual + HANDLE + GetVrToken( + VOID + ) const = 0; + + virtual + PCWSTR + GetVrPath( + VOID + ) const = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + BOOL + CheckIfFileHasChanged( + IN HANDLE hUserToken + ) = 0; +}; + + +// +// Token-cache entry +// +class __declspec(uuid("fd86e6de-fb0e-47dd-820a-e0da12be46e9")) +IHttpTokenEntry : public IHttpCacheSpecificData +{ + public: + virtual + HANDLE + GetImpersonationToken( + VOID + ) = 0; + + virtual + HANDLE + GetPrimaryToken( + VOID + ) = 0; + + virtual + PSID + GetSid( + VOID + ) = 0; +}; + + +// +// IHttpServer extended interface versions +// +enum HTTP_SERVER_INTERFACE_VERSION +{ + HTTP_SERVER_INTERFACE_V2 +}; + + +// +// Global utility descriptor +// +class __declspec(uuid("eda2a40f-fb92-4d6d-b52b-c8c207380b4e")) +IHttpServer +{ + public: + virtual + BOOL + IsCommandLineLaunch( + VOID + ) const = 0; + + virtual + PCWSTR + GetAppPoolName( + VOID + ) const = 0; + + virtual + HRESULT + AssociateWithThreadPool( + IN HANDLE hHandle, + IN LPOVERLAPPED_COMPLETION_ROUTINE completionRoutine + ) = 0; + + virtual + VOID + IncrementThreadCount( + VOID + ) = 0; + + virtual + VOID + DecrementThreadCount( + VOID + ) = 0; + + virtual + VOID + ReportUnhealthy( + IN PCWSTR pszReasonString, + IN HRESULT hrReason + ) = 0; + + virtual + VOID + RecycleProcess( + PCWSTR pszReason + ) = 0; + + virtual + IAppHostAdminManager * + GetAdminManager( + VOID + ) const = 0; + + virtual + HRESULT + GetFileInfo( + IN PCWSTR pszPhysicalPath, + IN HANDLE hUserToken, + IN PSID pSid, + IN PCWSTR pszChangeNotificationPath, + IN HANDLE hChangeNotificationToken, + IN BOOL fCache, + OUT IHttpFileInfo ** ppFileInfo, + IN IHttpTraceContext * pHttpTraceContext = NULL + ) = 0; + + virtual + HRESULT + FlushKernelCache( + IN PCWSTR pszUrl + ) = 0; + + virtual + HRESULT + DoCacheOperation( + IN CACHE_OPERATION cacheOperation, + IN IHttpCacheKey * pCacheKey, + OUT IHttpCacheSpecificData ** ppCacheSpecificData, + IN IHttpTraceContext * pHttpTraceContext = NULL + ) = 0; + + virtual + GLOBAL_NOTIFICATION_STATUS + NotifyCustomNotification( + ICustomNotificationProvider * pCustomOutput + ) = 0; + + virtual + IHttpPerfCounterInfo * + GetPerfCounterInfo( + VOID + ) = 0; + + virtual + VOID + RecycleApplication( + PCWSTR pszAppConfigPath + ) = 0; + + virtual + VOID + NotifyConfigurationChange( + PCWSTR pszPath + ) = 0; + + virtual + VOID + NotifyFileChange( + PCWSTR pszFileName + ) = 0; + + virtual + IDispensedHttpModuleContextContainer * + DispenseContainer( + VOID + ) = 0; + + virtual + HRESULT + AddFragmentToCache( + IN HTTP_DATA_CHUNK * pDataChunk, + PCWSTR pszFragmentName + ) = 0; + + virtual + HRESULT + ReadFragmentFromCache( + PCWSTR pszFragmentName, + OUT BYTE * pvBuffer, + DWORD cbSize, + OUT DWORD * pcbCopied + ) = 0; + + virtual + HRESULT + RemoveFragmentFromCache( + PCWSTR pszFragmentName + ) = 0; + + virtual + HRESULT + GetWorkerProcessSettings( + OUT IWpfSettings ** ppWorkerProcessSettings + ) = 0; + + virtual + HRESULT + GetProtocolManagerCustomInterface( + IN PCWSTR pProtocolManagerDll, + IN PCWSTR pProtocolManagerDllInitFunction, + IN DWORD dwCustomInterfaceId, + OUT PVOID* ppCustomInterface + ) = 0; + + virtual + BOOL + SatisfiesPrecondition( + PCWSTR pszPrecondition, + BOOL * pfUnknownPrecondition = NULL + ) const = 0; + + virtual + IHttpTraceContext * + GetTraceContext( + VOID + ) const = 0; + + virtual + HRESULT + RegisterFileChangeMonitor( + PCWSTR pszPath, + HANDLE hToken, + IHttpFileMonitor ** ppFileMonitor + ) = 0; + + virtual + HRESULT + GetExtendedInterface( + IN HTTP_SERVER_INTERFACE_VERSION version, + OUT PVOID * ppInterface + ) = 0; +}; + +class __declspec(uuid("34af637e-afe8-4556-bcc1-767f8e0b4a4e")) +IHttpServer2 : public IHttpServer +{ + public: + + virtual + HRESULT + GetToken( + PCWSTR pszUserName, + PCWSTR pszPassword, + DWORD dwLogonMethod, + IHttpTokenEntry ** ppTokenEntry, + PCWSTR pszDefaultDomain = NULL, + PSOCKADDR pSockAddr = NULL, + IHttpTraceContext * pHttpTraceContext = NULL + ) = 0; + + virtual + PCWSTR + GetAppPoolConfigFile( + __out DWORD * pcchConfigFilePath = NULL + ) const = 0; + + virtual + HRESULT + GetExtendedInterface( + __in const GUID & Version1, + __in PVOID pInput, + __in const GUID & Version2, + __deref_out PVOID * ppOutput + ) = 0; +}; + +// +// Helper function to get extended HTTP interfaces. +// +// Template parameters (HttpType1 and HttpType2) +// can be deduced from the arguments to the function. +// +// Example: +// +// IHttpRequest * pHttpRequest = pHttpContext->GetRequest(); +// IHttpRequest2 * pHttpRequest2; +// HRESULT hr = HttpGetExtendedInterface(g_pHttpServer, pHttpRequest, &pHttpRequest2); +// if( SUCCEEDED(hr) ) +// { +// // Use pHttpRequest2. +// } +// +// Where pHttpContext is an IHttpContext pointer and +// g_pHttpServer is an IHttpServer pointer. +// + +template +HRESULT +HttpGetExtendedInterface( + __in IHttpServer * pHttpServer, + __in HttpType1 * pInput, + __deref_out HttpType2 ** ppOutput +) +{ + HRESULT hr; + IHttpServer2 * pHttpServer2; + hr = pHttpServer->GetExtendedInterface(HTTP_SERVER_INTERFACE_V2, + reinterpret_cast(&pHttpServer2) ); + if (SUCCEEDED(hr)) + { + hr = pHttpServer2->GetExtendedInterface(__uuidof(HttpType1), + pInput, + __uuidof(HttpType2), + reinterpret_cast(ppOutput) ); + } + return hr; +} + +// +// Notification specific output for notifications +// +class __declspec(uuid("6f3f657d-2fb8-43c6-a096-5064b41f0580")) +IHttpEventProvider +{ + public: + virtual + VOID + SetErrorStatus( + HRESULT hrError + ) = 0; +}; + +// +// Completion information for notifications +// +class __declspec(uuid("49dd20e3-d9c0-463c-8821-f3413b55cc00")) +IHttpCompletionInfo +{ + public: + virtual + DWORD + GetCompletionBytes( + VOID + ) const = 0; + + virtual + HRESULT + GetCompletionStatus( + VOID + ) const = 0; +}; + +// +// RQ_ and GL_ CUSTOM_NOTIFICATION outputs +// +class __declspec(uuid("671e6d34-9380-4df4-b453-91129df02b24")) +ICustomNotificationProvider : public IHttpEventProvider +{ + public: + virtual + PCWSTR + QueryNotificationType( + VOID + ) = 0; +}; + +// +// RQ_REQUEST_AUTHENTICATE descriptor +// +class __declspec(uuid("304d51d0-0307-45ed-83fd-dd3fc032fdfc")) +IAuthenticationProvider : public IHttpEventProvider +{ + public: + virtual + VOID + SetUser( + IN IHttpUser * pUser + ) = 0; +}; + +// +// RQ_MAP_REQUEST_HANDLER +// +class __declspec(uuid("fea3ce6b-e346-47e7-b2a6-ad265baeff2c")) +IMapHandlerProvider : public IHttpEventProvider +{ + public: + virtual + HRESULT + SetScriptName( + PCWSTR pszScriptName, + DWORD cchScriptName + ) = 0; + + virtual + VOID + SetScriptMap( + IN IScriptMapInfo * pScriptMap + ) = 0; + + virtual + VOID + SetFileInfo( + IN IHttpFileInfo * pFileInfo + ) = 0; +}; + +// +// RQ_MAP_PATH +// +class __declspec(uuid("8efdf557-a8f1-4bc9-b462-6df3b038a59a")) +IMapPathProvider : public IHttpEventProvider +{ + public: + virtual + PCWSTR + GetUrl( + ) const = 0; + + virtual + PCWSTR + GetPhysicalPath( + ) const = 0; + + virtual + HRESULT + SetPhysicalPath( + PCWSTR pszPhysicalPath, + DWORD cchPhysicalPath + ) = 0; +}; + +// +// RQ_SEND_RESPONSE +// +class __declspec(uuid("57f2e7bc-0bcf-4a9f-94a4-10e55c6e5b51")) +ISendResponseProvider : public IHttpEventProvider +{ + public: + virtual + BOOL + GetHeadersBeingSent( + VOID + ) const = 0; + + virtual + DWORD + GetFlags( + VOID + ) const = 0; + + virtual + VOID + SetFlags( + DWORD dwFlags + ) = 0; + + virtual + HTTP_LOG_DATA * + GetLogData( + VOID + ) const = 0; + + virtual + HRESULT + SetLogData( + IN HTTP_LOG_DATA *pLogData + ) = 0; + + virtual + BOOL + GetReadyToLogData( + VOID + ) const = 0; +}; + +// +// RQ_READ_ENTITY +// +class __declspec(uuid("fe6d905a-99b8-49fd-b389-cfc809562b81")) +IReadEntityProvider : public IHttpEventProvider +{ + public: + virtual + VOID + GetEntity( + OUT PVOID * ppBuffer, + OUT DWORD * pcbData, + OUT DWORD * pcbBuffer + ) = 0; + + virtual + VOID + SetEntity( + IN PVOID pBuffer, + DWORD cbData, + DWORD cbBuffer + ) = 0; +}; + +// +// GL_PRE_BEGIN_REQUEST provider +// +class __declspec(uuid("fb715d26-aff9-476a-8fc0-6b1acb3d1098")) +IPreBeginRequestProvider : public IHttpEventProvider +{ + public: + virtual + IHttpContext * + GetHttpContext( + VOID + ) = 0; +}; + +// +// GL_APPLICATION_START provider +// +class __declspec(uuid("1de2c71c-c126-4512-aed3-f4f885e14997")) +IHttpApplicationProvider : public IHttpEventProvider +{ + public: + virtual + IHttpApplication * + GetApplication( + VOID + ) = 0; +}; + +typedef IHttpApplicationProvider IHttpApplicationStartProvider; + +class __declspec(uuid("ba32d330-9ea8-4b9e-89f1-8c76a323277f")) +IHttpModuleFactory; + +// +// GL_APPLICATION_RESOLVE_MODULES provider +// +class __declspec(uuid("0617d9b9-e20f-4a9f-94f9-35403b3be01e")) +IHttpApplicationResolveModulesProvider : public IHttpApplicationProvider +{ + public: + virtual + HRESULT + RegisterModule( + IN HTTP_MODULE_ID parentModuleId, + IN IHttpModuleFactory * pModuleFactory, + IN PCWSTR pszModuleName, + IN PCWSTR pszModuleType, + IN PCWSTR pszModulePreCondition, + IN DWORD dwRequestNotifications, + IN DWORD dwPostRequestNotifications + ) = 0; + + virtual + HRESULT + SetPriorityForRequestNotification( + IN PCWSTR pszModuleName, + IN DWORD dwRequestNotification, + IN PCWSTR pszPriorityAlias + ) = 0; +}; + +// +// GL_APPLICATION_STOP provider +// +typedef IHttpApplicationProvider IHttpApplicationStopProvider; + +// +// GL_RSCA_QUERY provider +// +class __declspec(uuid("63fdc43f-934a-4ee5-bcd8-7e7b50b75605")) +IGlobalRSCAQueryProvider : public IHttpEventProvider +{ + public: + virtual + PCWSTR + GetFunctionName( + VOID + ) const = 0; + + virtual + PCWSTR + GetFunctionParameters( + VOID + ) const = 0; + + virtual + HRESULT + GetOutputBuffer( + DWORD cbBuffer, + OUT BYTE ** ppbBuffer + ) = 0; + + virtual + HRESULT + ResizeOutputBuffer( + DWORD cbNewBuffer, + DWORD cbBytesToCopy, + IN OUT BYTE ** ppbBuffer + ) = 0; + + virtual + VOID + SetResult( + DWORD cbData, + HRESULT hr + ) = 0; +}; + +// +// GL_STOP_LISTENING +// +class __declspec(uuid("41f9a601-e25d-4ac8-8a1f-635698a30ab9")) +IGlobalStopListeningProvider : public IHttpEventProvider +{ + public: + virtual + BOOL + DrainRequestsGracefully( + VOID + ) const = 0; +}; + +// +// GL_CACHE_OPERATION +// +class __declspec(uuid("58925fb9-7c5e-4684-833b-4a04e1286690")) +ICacheProvider : public IHttpEventProvider +{ + public: + virtual + CACHE_OPERATION + GetCacheOperation( + VOID + ) const = 0; + + virtual + IHttpCacheKey * + GetCacheKey( + VOID + ) const = 0; + + virtual + IHttpCacheSpecificData * + GetCacheRecord( + VOID + ) const = 0; + + virtual + VOID + SetCacheRecord( + IHttpCacheSpecificData * pCacheRecord + ) = 0; + + virtual + IHttpTraceContext * + GetTraceContext( + VOID + ) const = 0; +}; + +// +// GL_CONFIGURATION_CHANGE +// +class __declspec(uuid("3405f3b4-b3d6-4b73-b5f5-4d8a3cc642ce")) +IGlobalConfigurationChangeProvider : public IHttpEventProvider +{ + public: + virtual + PCWSTR + GetChangePath( + VOID + ) const = 0; +}; + +// +// GL_FILE_CHANGE +// +class __declspec(uuid("ece31ee5-0486-4fb0-a875-6739a2d7daf5")) +IGlobalFileChangeProvider : public IHttpEventProvider +{ +public: + virtual + PCWSTR + GetFileName( + VOID + ) const = 0; + + virtual + IHttpFileMonitor * + GetFileMonitor( + VOID + ) = 0; +}; + +// +// GL_TRACE_EVENT +// +class __declspec(uuid("7c6bb150-0310-4718-a01f-6faceb62dc1d")) +IGlobalTraceEventProvider : public IHttpEventProvider +{ + public: + virtual + HRESULT + GetTraceEvent( + OUT HTTP_TRACE_EVENT ** ppTraceEvent + ) = 0; + + virtual + BOOL + CheckSubscription( + IN HTTP_MODULE_ID ModuleId + ) = 0; + + virtual + HRESULT + GetCurrentHttpRequestContext( + OUT IHttpContext ** ppHttpContext + ) = 0; +}; + +// +// GL_THREAD_CLEANUP +// +class __declspec(uuid("6b36a149-8620-45a0-8197-00814a706e2e")) +IGlobalThreadCleanupProvider : public IHttpEventProvider +{ +public: + virtual + IHttpApplication * + GetApplication( + VOID + ) = 0; +}; + +// +// GL_APPLICATION_PRELOAD +// +class __declspec(uuid("2111f8d6-0c41-4ff7-bd45-5c04c7e91a73")) +IGlobalApplicationPreloadProvider : public IHttpEventProvider +{ +public: + virtual + HRESULT + CreateContext( + OUT IHttpContext ** ppHttpContext + ) = 0; + + virtual + HRESULT + ExecuteRequest( + IN IHttpContext * pHttpContext, + IN IHttpUser * pHttpUser + ) = 0; +}; + +class CHttpModule +{ +public: + // RQ_BEGIN_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnBeginRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostBeginRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_AUTHENTICATE_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnAuthenticateRequest( + IN IHttpContext * pHttpContext, + IN IAuthenticationProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostAuthenticateRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_AUTHORIZE_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnAuthorizeRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostAuthorizeRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_RESOLVE_REQUEST_CACHE + + virtual + REQUEST_NOTIFICATION_STATUS + OnResolveRequestCache( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostResolveRequestCache( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_MAP_REQUEST_HANDLER + + virtual + REQUEST_NOTIFICATION_STATUS + OnMapRequestHandler( + IN IHttpContext * pHttpContext, + IN IMapHandlerProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostMapRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_ACQUIRE_REQUEST_STATE + + virtual + REQUEST_NOTIFICATION_STATUS + OnAcquireRequestState( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostAcquireRequestState( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_PRE_EXECUTE_REQUEST_HANDLER + + virtual + REQUEST_NOTIFICATION_STATUS + OnPreExecuteRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostPreExecuteRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_EXECUTE_REQUEST_HANDLER + + virtual + REQUEST_NOTIFICATION_STATUS + OnExecuteRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostExecuteRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_RELEASE_REQUEST_STATE + + virtual + REQUEST_NOTIFICATION_STATUS + OnReleaseRequestState( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostReleaseRequestState( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_UPDATE_REQUEST_CACHE + + virtual + REQUEST_NOTIFICATION_STATUS + OnUpdateRequestCache( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostUpdateRequestCache( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_LOG_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnLogRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostLogRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_END_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnEndRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostEndRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_SEND_RESPONSE + + virtual + REQUEST_NOTIFICATION_STATUS + OnSendResponse( + IN IHttpContext * pHttpContext, + IN ISendResponseProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_MAP_PATH + + virtual + REQUEST_NOTIFICATION_STATUS + OnMapPath( + IN IHttpContext * pHttpContext, + IN IMapPathProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_READ_ENTITY + + virtual + REQUEST_NOTIFICATION_STATUS + OnReadEntity( + IN IHttpContext * pHttpContext, + IN IReadEntityProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_CUSTOM_NOTIFICATION + + virtual + REQUEST_NOTIFICATION_STATUS + OnCustomRequestNotification( + IN IHttpContext * pHttpContext, + IN ICustomNotificationProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // Completion + + virtual + REQUEST_NOTIFICATION_STATUS + OnAsyncCompletion( + IN IHttpContext * pHttpContext, + IN DWORD dwNotification, + IN BOOL fPostNotification, + IN IHttpEventProvider * pProvider, + IN IHttpCompletionInfo * pCompletionInfo + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( dwNotification ); + UNREFERENCED_PARAMETER( fPostNotification ); + UNREFERENCED_PARAMETER( pProvider ); + UNREFERENCED_PARAMETER( pCompletionInfo ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + virtual + VOID + Dispose( + VOID + ) + { + delete this; + } + + protected: + + CHttpModule() + {} + + virtual + ~CHttpModule() + {} +}; + +class CGlobalModule +{ + public: + + // GL_STOP_LISTENING + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalStopListening( + IN IGlobalStopListeningProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_CACHE_CLEANUP + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalCacheCleanup( + VOID + ) + { + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_CACHE_OPERATION + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalCacheOperation( + IN ICacheProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_HEALTH_CHECK + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalHealthCheck( + VOID + ) + { + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_CONFIGURATION_CHANGE + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalConfigurationChange( + IN IGlobalConfigurationChangeProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_FILE_CHANGE + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalFileChange( + IN IGlobalFileChangeProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_PRE_BEGIN_REQUEST + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalPreBeginRequest( + IN IPreBeginRequestProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_APPLICATION_START + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalApplicationStart( + IN IHttpApplicationStartProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_APPLICATION_RESOLVE_MODULES + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalApplicationResolveModules( + IN IHttpApplicationResolveModulesProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_APPLICATION_STOP + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalApplicationStop( + IN IHttpApplicationStopProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_RSCA_QUERY + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalRSCAQuery( + IN IGlobalRSCAQueryProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_TRACE_EVENT + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalTraceEvent( + IN IGlobalTraceEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_CUSTOM_NOTIFICATION + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalCustomNotification( + IN ICustomNotificationProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + virtual + VOID + Terminate( + VOID + ) = 0; + + // GL_THREAD_CLEANUP + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalThreadCleanup( + IN IGlobalThreadCleanupProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_APPLICATION_PRELOAD + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalApplicationPreload( + IN IGlobalApplicationPreloadProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + +}; + +class __declspec(uuid("85c1679c-0b21-491c-afb5-c7b5c86464c4")) +IModuleAllocator +{ + public: + virtual + VOID * + AllocateMemory( + IN DWORD cbAllocation + ) = 0; +}; + +class __declspec(uuid("ba32d330-9ea8-4b9e-89f1-8c76a323277f")) +IHttpModuleFactory +{ + public: + virtual + HRESULT + GetHttpModule( + OUT CHttpModule ** ppModule, + IN IModuleAllocator * pAllocator + ) = 0; + + virtual + VOID + Terminate( + VOID + ) = 0; +}; + +// +// Register-module descriptor +// +class __declspec(uuid("07e5beb3-b798-459d-a98a-e6c485b2b3bc")) +IHttpModuleRegistrationInfo +{ + public: + virtual + PCWSTR + GetName( + VOID + ) const = 0; + + virtual + HTTP_MODULE_ID + GetId( + VOID + ) const = 0; + + virtual + HRESULT + SetRequestNotifications( + IN IHttpModuleFactory * pModuleFactory, + IN DWORD dwRequestNotifications, + IN DWORD dwPostRequestNotifications + ) = 0; + + virtual + HRESULT + SetGlobalNotifications( + IN CGlobalModule * pGlobalModule, + IN DWORD dwGlobalNotifications + ) = 0; + + virtual + HRESULT + SetPriorityForRequestNotification( + IN DWORD dwRequestNotification, + IN PCWSTR pszPriority + ) = 0; + + virtual + HRESULT + SetPriorityForGlobalNotification( + IN DWORD dwGlobalNotification, + IN PCWSTR pszPriority + ) = 0; +}; + + +// +// Register Module entry point +// + +typedef +HRESULT +(WINAPI * PFN_REGISTERMODULE)( + DWORD dwServerVersion, + IHttpModuleRegistrationInfo * pModuleInfo, + IHttpServer * pGlobalInfo +); + +#define MODULE_REGISTERMODULE "RegisterModule" + +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h new file mode 100644 index 0000000000..4d0d5735bc --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h @@ -0,0 +1,243 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +template +class HYBRID_ARRAY +{ +public: + + HYBRID_ARRAY( + VOID + ) : m_pArray(m_InlineArray), + m_Capacity(ARRAYSIZE(m_InlineArray)) + { + } + + ~HYBRID_ARRAY() + { + if ( !QueryUsesInlineArray() ) + { + delete [] m_pArray; + m_pArray = NULL; + } + } + + SIZE_T + QueryCapacity( + VOID + ) const + { + // + // Number of elements available in the array. + // + return m_Capacity; + } + + TYPE * + QueryArray( + VOID + ) const + { + // + // Raw pointer to the current array. + // + return m_pArray; + } + + TYPE & + QueryItem( + __in const SIZE_T Index + ) + { + // + // Gets the array item giving the index. + // + return m_pArray[Index]; + } + + TYPE & + operator [] (const SIZE_T Index) + { + // + // Operator override for convenience. + // Please don't add other overloads like '++' '--' + // in order to keep it simple. + // + return m_pArray[Index]; + } + + const TYPE & + operator [] (const SIZE_T Index) const + { + return m_pArray[Index]; + } + + template + HRESULT + Copy( + __in TYPE const (&SourceArray)[SourceSize], + __in bool fHasTrivialAssign = false + ) + /*++ + + Routine Description: + + Copies a source array like: + + int source[] = { 1, 2, 3 }; + hr = hybridArray.Copy( source ); + + It will statically determinate the length of the source array. + + Arguments: + + SourceArray - The array to copy. + SourceSize - The number of array elements. + fHasTrivialAssign - True if safe to perform buffer copy. + + Return Value: + + HRESULT + + --*/ + { + return Copy( SourceArray, SourceSize, fHasTrivialAssign ); + } + + HRESULT + Copy( + __in_ecount(SourceSize) + const TYPE * pSourceArray, + __in const SIZE_T SourceSize, + __in bool fHasTrivialAssign = false + ) + /*++ + + Routine Description: + + Copies a source array. + + Arguments: + + pSourceArray - The array to copy. + SourceSize - The number of array elements. + fHasTrivialAssign - True if safe to perform buffer copy. + + Return Value: + + HRESULT + + --*/ + { + HRESULT hr; + + hr = EnsureCapacity( SourceSize, + FALSE, // fCopyPrevious + FALSE ); // fHasTrivialAssign + if ( FAILED( hr ) ) + { + return hr; + } + + if ( fHasTrivialAssign ) // Future Work: use std::tr1::has_trivial_assign + { + CopyMemory(m_pArray, pSourceArray, m_Capacity * sizeof(TYPE)); + } + else + { + for ( SIZE_T Index = 0; Index < SourceSize; ++Index ) + { + m_pArray[Index] = pSourceArray[Index]; + } + } + + return S_OK; + } + + HRESULT + EnsureCapacity( + __in const SIZE_T MinimumCapacity, + __in bool fCopyPrevious, + __in bool fHasTrivialAssign = false + ) + /*++ + + Routine Description: + + Copies a source array. + + Arguments: + + MinimumCapacity - The expected length of the array. + fCopyPrevious - Must be always explicit parameter. + True if copy previous array data. + fHasTrivialAssign - True if safe to perform buffer copy. + + Return Value: + + HRESULT + + --*/ + { + // + // Caller is responsible for calculating a length that won't cause + // too many reallocations in the future. + // + + if ( MinimumCapacity <= ARRAYSIZE(m_InlineArray) ) + { + return S_OK; + } + + TYPE * pNewArray; + + pNewArray = new TYPE[ MinimumCapacity ]; + if ( pNewArray == NULL ) + { + return E_OUTOFMEMORY; + } + + if ( fCopyPrevious ) + { + if ( fHasTrivialAssign ) + { + CopyMemory(pNewArray, m_pArray, m_Capacity * sizeof(TYPE)); + } + else + { + for ( SIZE_T Index = 0; Index < m_Capacity; ++Index ) + { + pNewArray[Index] = m_pArray[Index]; + } + } + } + + if ( QueryUsesInlineArray() ) + { + m_pArray = pNewArray; + } + else + { + delete [] m_pArray; + m_pArray = pNewArray; + } + + m_Capacity = MinimumCapacity; + + return S_OK; + } + +private: + + bool + QueryUsesInlineArray( + VOID + ) const + { + return m_pArray == m_InlineArray; + } + + TYPE m_InlineArray[SIZE]; + TYPE * m_pArray; + SIZE_T m_Capacity; +}; \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h new file mode 100644 index 0000000000..04c1d1ab46 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h @@ -0,0 +1,163 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#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 diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h new file mode 100644 index 0000000000..56a67eb1c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#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 diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx new file mode 100644 index 0000000000..dd891b3252 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx @@ -0,0 +1,225 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _MULTISZ_HXX_ +#define _MULTISZ_HXX_ + +# include + + +/*++ + 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 +// 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_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx new file mode 100644 index 0000000000..44aa802563 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx @@ -0,0 +1,225 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _MULTISZA_HXX_ +#define _MULTISZA_HXX_ + +# include + + +/*++ + 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 +// 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_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h new file mode 100644 index 0000000000..411c3660a4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __NORMALIZE_URL__H__ +#define __NORMALIZE_URL__H__ + +HRESULT +NormalizeUrl( + __inout LPSTR pszUrl +); + + +HRESULT +NormalizeUrlW( + __inout LPWSTR pszUrl +); + + + +HRESULT +UlCleanAndCopyUrl( + __in LPSTR pSource, + IN ULONG SourceLength, + OUT PULONG pBytesCopied, + __inout PWSTR pDestination, + __deref_opt_out_opt PWSTR * ppQueryString OPTIONAL +); + +HRESULT +UlInitializeParsing( + VOID +); + +HRESULT +InitializeNormalizeUrl( + VOID +); + + +#endif \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h new file mode 100644 index 0000000000..8a8d656f21 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#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 + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h new file mode 100644 index 0000000000..ae59b1c805 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h @@ -0,0 +1,305 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +template +class PER_CPU +{ +public: + + template + inline + static + HRESULT + Create( + FunctionInitializer Initializer, + __deref_out PER_CPU ** ppInstance + ); + + inline + T * + GetLocal( + VOID + ); + + template + 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 + 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 +template +inline +// static +HRESULT +PER_CPU::Create( + FunctionInitializer Initializer, + __deref_out PER_CPU ** ppInstance +) +{ + HRESULT hr = S_OK; + DWORD CacheLineSize = 0; + DWORD ObjectCacheLineSize = 0; + DWORD NumberOfProcessors = 0; + PER_CPU * 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 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*) _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(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 +inline +T * +PER_CPU::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 +inline +T * +PER_CPU::GetObject( + DWORD Index +) +{ + return reinterpret_cast(static_cast(m_pVariables) + Index * m_Alignment); +} + +template +template +inline +VOID +PER_CPU::ForEach( + FunctionForEach Function +) +{ + for(DWORD Index = 0; Index < m_VariablesCount; ++Index) + { + T * pObject = GetObject(Index); + Function(pObject); + } +} + +template +VOID +PER_CPU::Dispose( + VOID +) +{ + _aligned_free(this); +} + +template +template +inline +HRESULT +PER_CPU::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 +// static +HRESULT +PER_CPU::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; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h new file mode 100644 index 0000000000..77fcb75b8a --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include +#include + +// +// 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(sqrt(static_cast(dwCandidate))); + + for ( DWORD Index = 3; Index <= dwMax; Index += 2 ) + { + if ( (dwCandidate % Index) == 0 ) + { + return FALSE; + } + } + return TRUE; + } + + PRIME() {} + ~PRIME() {} +}; \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h new file mode 100644 index 0000000000..ace85dcde2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _REFTRACE_H_ +#define _REFTRACE_H_ + + +#if defined(__cplusplus) +extern "C" { +#endif // __cplusplus + + +#include + + +// +// 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_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h new file mode 100644 index 0000000000..50b9b1ca11 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h @@ -0,0 +1,193 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#if (_WIN32_WINNT < 0x600) + +// +// XP implementation. +// +class CWSDRWLock +{ +public: + + CWSDRWLock() + : m_bInited(FALSE) + { + } + + ~CWSDRWLock() + { + if (m_bInited) + { + DeleteCriticalSection(&m_rwLock.critsec); + CloseHandle(m_rwLock.ReadersDoneEvent); + } + } + + BOOL QueryInited() const + { + return m_bInited; + } + + HRESULT Init() + { + HRESULT hr = S_OK; + + if (FALSE == m_bInited) + { + m_rwLock.fWriterWaiting = FALSE; + m_rwLock.LockCount = 0; + if ( !InitializeCriticalSectionAndSpinCount( &m_rwLock.critsec, 0 )) + { + DWORD dwError = GetLastError(); + hr = HRESULT_FROM_WIN32(dwError); + return hr; + } + + m_rwLock.ReadersDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if( NULL == m_rwLock.ReadersDoneEvent ) + { + DWORD dwError = GetLastError(); + hr = HRESULT_FROM_WIN32(dwError); + DeleteCriticalSection(&m_rwLock.critsec); + return hr; + } + m_bInited = TRUE; + } + + return hr; + } + + void SharedAcquire() + { + EnterCriticalSection(&m_rwLock.critsec); + InterlockedIncrement(&m_rwLock.LockCount); + LeaveCriticalSection(&m_rwLock.critsec); + } + + void SharedRelease() + { + ReleaseRWLock(); + } + + void ExclusiveAcquire() + { + EnterCriticalSection( &m_rwLock.critsec ); + + m_rwLock.fWriterWaiting = TRUE; + + // check if there are any readers active + if ( InterlockedExchangeAdd( &m_rwLock.LockCount, 0 ) > 0 ) + { + // + // Wait for all the readers to get done.. + // + WaitForSingleObject( m_rwLock.ReadersDoneEvent, INFINITE ); + } + m_rwLock.LockCount = -1; + } + + void ExclusiveRelease() + { + ReleaseRWLock(); + } + +private: + + BOOL m_bInited; + + typedef struct _RW_LOCK + { + BOOL fWriterWaiting; // Is a writer waiting on the lock? + LONG LockCount; + CRITICAL_SECTION critsec; + HANDLE ReadersDoneEvent; + } RW_LOCK, *PRW_LOCK; + + RW_LOCK m_rwLock; + +private: + + void ReleaseRWLock() + { + LONG Count = InterlockedDecrement( &m_rwLock.LockCount ); + + if ( 0 <= Count ) + { + // releasing a read lock + if (( m_rwLock.fWriterWaiting ) && ( 0 == Count )) + { + SetEvent( m_rwLock.ReadersDoneEvent ); + } + } + else + { + // Releasing a write lock + m_rwLock.LockCount = 0; + m_rwLock.fWriterWaiting = FALSE; + LeaveCriticalSection(&m_rwLock.critsec); + } + } +}; + +#else + +// +// Implementation for Windows Vista or greater. +// +class CWSDRWLock +{ +public: + + CWSDRWLock() + { + InitializeSRWLock(&m_rwLock); + } + + BOOL QueryInited() + { + return TRUE; + } + + + HRESULT Init() + { + // + // Method defined to keep compatibility with CWSDRWLock class for XP. + // + return S_OK; + } + + void SharedAcquire() + { + AcquireSRWLockShared(&m_rwLock); + } + + void SharedRelease() + { + ReleaseSRWLockShared(&m_rwLock); + } + + void ExclusiveAcquire() + { + AcquireSRWLockExclusive(&m_rwLock); + } + + void ExclusiveRelease() + { + ReleaseSRWLockExclusive(&m_rwLock); + } + +private: + + SRWLOCK m_rwLock; +}; + +#endif + +// +// Rename the lock class to a more clear name. +// +typedef CWSDRWLock READ_WRITE_LOCK; \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h new file mode 100644 index 0000000000..f2c7980405 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h @@ -0,0 +1,730 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __STATIC_HASH__H_ +#define __STATIC_HASH__H_ + +#define STATIC_STRING_HASH_BUCKETS 131 + +// +// SERVER_VARIABLE_HASH maps server variable string to routines to eval them +// + +struct STATIC_STRING_HASH_RECORD +{ + CHAR * _pszName; + STATIC_STRING_HASH_RECORD * _pNext; + USHORT _cchName; +}; + +struct STATIC_STRING_HASH_ITER +{ + STATIC_STRING_HASH_RECORD *_pCursor; + DWORD _dwBucket; + BOOL _fRemove; +}; + +class STATIC_STRING_HASH +{ + public: + + STATIC_STRING_HASH( + BOOL fCaseSensitive = FALSE + ) : _fCaseSensitive( fCaseSensitive ) + { + Reset(); + } + + VOID + Reset() + { + ZeroMemory( &_rgBuckets, sizeof( _rgBuckets ) ); + } + + static + PCSTR + ExtractKey( + __in const STATIC_STRING_HASH_RECORD * pRecord + ) + /*++ + + Routine Description: + + Get the key out of the record + + Arguments: + + record to fetch the key from + + Return Value: + + key + + --*/ + { + DBG_ASSERT( pRecord != NULL ); + return pRecord->_pszName; + } + + VOID + InsertRecord( + __in STATIC_STRING_HASH_RECORD * pRecord + ) + /*++ + + Routine Description: + + Insert record to hash table + + Note: remember this is static hash table + There is no synchronization on the table + Exclusive acess must be assured by caller + + Arguments: + + record to fetch the key from + + Return Value: + + VOID + + --*/ + { + DWORD dwIndex; + STATIC_STRING_HASH_RECORD* pCursor; + + DBG_ASSERT( pRecord != NULL ); + DBG_ASSERT( pRecord->_pszName != NULL ); + + if(NULL == pRecord->_pszName) + { + return; + } + + if (_fCaseSensitive) + { + dwIndex = HashString( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS; + } + else + { + dwIndex = HashStringNoCase( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS; + } + + pCursor = _rgBuckets[ dwIndex ]; + + pRecord->_pNext = pCursor; + _rgBuckets[ dwIndex ] = pRecord; + } + + STATIC_STRING_HASH_RECORD * + FindKey( + __in PCSTR pszName, + BOOL fRemove = FALSE + ) + /*++ + + Routine Description: + + Find key in the table (and remove it optionally) + + Arguments: + + key + + Return Value: + + record containing the key + + --*/ + { + DWORD dwIndex; + STATIC_STRING_HASH_RECORD* pRecord; + STATIC_STRING_HASH_RECORD* pLastRecord = NULL; + + DBG_ASSERT( pszName != NULL ); + + if (_fCaseSensitive) + { + dwIndex = HashString( pszName ) % STATIC_STRING_HASH_BUCKETS; + } + else + { + dwIndex = HashStringNoCase( pszName ) % STATIC_STRING_HASH_BUCKETS; + } + + pRecord = _rgBuckets[ dwIndex ]; + while ( pRecord != NULL ) + { + if (_fCaseSensitive) + { + if ( strcmp( pszName, pRecord->_pszName ) == 0 ) + { + break; + } + } + else if ( _stricmp( pszName, pRecord->_pszName ) == 0 ) + { + break; + } + + pLastRecord = pRecord; + pRecord = pRecord->_pNext; + } + + if (fRemove && + pRecord != NULL) + { + if (pLastRecord != NULL) + { + pLastRecord->_pNext = pRecord->_pNext; + } + else + { + _rgBuckets[dwIndex] = pRecord->_pNext; + } + } + + return pRecord; + } + + BOOL + CheckDistribution( + IN DWORD dwConflictThreshold, + IN BOOL fToDebugger + ) + /*++ + + Routine Description: + + Simple verification on conflicts within the table + + Arguments: + + dwConflictThreshold - max number of entries tolerated per bucket + fToDebbuger - spew the entries exceeding threshold into debugger + + Return Value: + + FALSE it threshold was reached (means hash funcion may not be optimal) + + --*/ + { + BOOL fThresholdReached = FALSE; + STATIC_STRING_HASH_RECORD* pRecord; + for ( DWORD dwIndex = 0; dwIndex < STATIC_STRING_HASH_BUCKETS; dwIndex++) + { + pRecord = _rgBuckets[ dwIndex ]; + DWORD countInBucket = 0; + while ( pRecord != NULL ) + { + countInBucket++; + pRecord = pRecord->_pNext; + } + // + // print out the list of multiple entries in bucket + // + if ( countInBucket > dwConflictThreshold && fToDebugger ) + { + fThresholdReached = TRUE; + + pRecord = _rgBuckets[ dwIndex ]; + while ( pRecord != NULL ) + { + pRecord = pRecord->_pNext; + } + } + } + return fThresholdReached; + } + + STATIC_STRING_HASH_RECORD * + FindFirst( + STATIC_STRING_HASH_ITER *pIterator, + BOOL fRemove = FALSE + ) + /*++ + + Routine Description: + + Begins a new hash item enumeration. + + Arguments: + + pIterator - Supplies the context for the enumeration. + + fRemove - Supplies TRUE if the items should be removed + from the hash as they are enumerated. + + Return Value: + + The first entry in the hash if successful, NULL otherwise. + + --*/ + { + pIterator->_dwBucket = 0; + pIterator->_fRemove = fRemove; + pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket); + + if (pIterator->_fRemove && pIterator->_pCursor != NULL) + { + _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext; + } + + return pIterator->_pCursor; + } + + STATIC_STRING_HASH_RECORD * + FindNext( + STATIC_STRING_HASH_ITER *pIterator + ) + /*++ + + Routine Description: + + Continues a hash item enumeration. + + Arguments: + + pIterator - Supplies the context for the enumeration. + + Return Value: + + The next entry in the hash if successful, NULL otherwise. + + --*/ + { + if (pIterator->_pCursor != NULL) + { + if (pIterator->_fRemove) + { + pIterator->_pCursor = _rgBuckets[pIterator->_dwBucket]; + } + else + { + pIterator->_pCursor = pIterator->_pCursor->_pNext; + } + + if (pIterator->_pCursor == NULL) + { + pIterator->_dwBucket++; + pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket); + } + } + + if (pIterator->_fRemove && pIterator->_pCursor != NULL) + { + _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext; + } + + return pIterator->_pCursor; + } + + protected: + + STATIC_STRING_HASH_RECORD * _rgBuckets[ STATIC_STRING_HASH_BUCKETS ]; + + private: + + BOOL _fCaseSensitive; + + STATIC_STRING_HASH_RECORD * + FindNextBucket( + DWORD *pdwStartingBucket + ) + /*++ + + Routine Description: + + Scan for the next non-empty bucket. + + Arguments: + + pdwStartingBucket - Supplies a pointer to the starting + bucket index. This value is updated with the index + of the next non-empty bucket if successful. + + Return Value: + + The first entry in the next non-empty bucket if successful, + NULL otherwise. + + --*/ + { + DWORD i; + STATIC_STRING_HASH_RECORD *pScan = NULL; + + for (i = *pdwStartingBucket ; i < STATIC_STRING_HASH_BUCKETS ; i++) + { + pScan = _rgBuckets[i]; + + if (pScan != NULL) + { + break; + } + } + + *pdwStartingBucket = i; + return pScan; + } +}; + + + + +struct STATIC_WSTRING_HASH_RECORD +{ + WCHAR * _pszName; + STATIC_WSTRING_HASH_RECORD * _pNext; + USHORT _cchName; +}; + + +struct STATIC_WSTRING_HASH_ITER +{ + STATIC_WSTRING_HASH_RECORD *_pCursor; + DWORD _dwBucket; + BOOL _fRemove; +}; + + +class STATIC_WSTRING_HASH +{ + public: + STATIC_WSTRING_HASH( + BOOL fCaseSensitive = FALSE + ) : _fCaseSensitive( fCaseSensitive ) + { + Reset(); + } + + VOID + Reset() + { + ZeroMemory( &_rgBuckets, sizeof( _rgBuckets ) ); + } + + static + PCWSTR + ExtractKey( + __in const STATIC_WSTRING_HASH_RECORD * pRecord + ) + /*++ + + Routine Description: + + Get the key out of the record + + Arguments: + + record to fetch the key from + + Return Value: + + key + + --*/ + { + DBG_ASSERT( pRecord != NULL ); + return pRecord->_pszName; + } + + VOID + InsertRecord( + __in STATIC_WSTRING_HASH_RECORD * pRecord + ) + /*++ + + Routine Description: + + Insert record to hash table + + Note: remember this is static hash table + There is no synchronization on the table + Exclusive acess must be assured by caller + + Arguments: + + record to fetch the key from + + Return Value: + + VOID + + --*/ + { + DWORD dwIndex; + STATIC_WSTRING_HASH_RECORD* pCursor; + + DBG_ASSERT( pRecord != NULL ); + DBG_ASSERT( pRecord->_pszName != NULL ); + + if (_fCaseSensitive) + { + dwIndex = HashString( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS; + } + else + { + dwIndex = HashStringNoCase( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS; + } + + pCursor = _rgBuckets[ dwIndex ]; + + pRecord->_pNext = pCursor; + _rgBuckets[ dwIndex ] = pRecord; + } + + STATIC_WSTRING_HASH_RECORD * + FindKey( + __in PCWSTR pszName, + BOOL fRemove = FALSE + ) + /*++ + + Routine Description: + + Find key in the table (and remove it optionally) + + Arguments: + + key + + Return Value: + + record containing the key + + --*/ + { + DWORD dwIndex; + STATIC_WSTRING_HASH_RECORD* pRecord; + STATIC_WSTRING_HASH_RECORD* pLastRecord = NULL; + + DBG_ASSERT( pszName != NULL ); + + if (_fCaseSensitive) + { + dwIndex = HashString( pszName ) % STATIC_STRING_HASH_BUCKETS; + } + else + { + dwIndex = HashStringNoCase( pszName ) % STATIC_STRING_HASH_BUCKETS; + } + + pRecord = _rgBuckets[ dwIndex ]; + while ( pRecord != NULL ) + { + if ( _fCaseSensitive ) + { + if ( wcscmp( pszName, pRecord->_pszName ) == 0 ) + { + break; + } + } + else if ( _wcsicmp( pszName, pRecord->_pszName ) == 0 ) + { + break; + } + + pLastRecord = pRecord; + pRecord = pRecord->_pNext; + } + + if (fRemove && + pRecord != NULL) + { + if (pLastRecord != NULL) + { + pLastRecord->_pNext = pRecord->_pNext; + } + else + { + _rgBuckets[dwIndex] = pRecord->_pNext; + } + } + + return pRecord; + } + + BOOL + CheckDistribution( + IN DWORD dwConflictThreshold, + IN BOOL fToDebugger + ) + /*++ + + Routine Description: + + Simple verification on conflicts within the table + + Arguments: + + dwConflictThreshold - max number of entries tolerated per bucket + fToDebbuger - spew the entries exceeding threshold into debugger + + Return Value: + + FALSE it threshold was reached (means hash funcion may not be optimal) + + --*/ + { + BOOL fThresholdReached = FALSE; + STATIC_WSTRING_HASH_RECORD* pRecord; + for ( DWORD dwIndex = 0; dwIndex < STATIC_STRING_HASH_BUCKETS; dwIndex++) + { + pRecord = _rgBuckets[ dwIndex ]; + DWORD countInBucket = 0; + while ( pRecord != NULL ) + { + countInBucket++; + pRecord = pRecord->_pNext; + } + // + // print out the list of multiple entries in bucket + // + if ( countInBucket > dwConflictThreshold && fToDebugger ) + { + fThresholdReached = TRUE; + + pRecord = _rgBuckets[ dwIndex ]; + while ( pRecord != NULL ) + { + pRecord = pRecord->_pNext; + } + } + } + return fThresholdReached; + } + + STATIC_WSTRING_HASH_RECORD * + FindFirst( + STATIC_WSTRING_HASH_ITER *pIterator, + BOOL fRemove = FALSE + ) + /*++ + + Routine Description: + + Begins a new hash item enumeration. + + Arguments: + + pIterator - Supplies the context for the enumeration. + + fRemove - Supplies TRUE if the items should be removed + from the hash as they are enumerated. + + Return Value: + + The first entry in the hash if successful, NULL otherwise. + + --*/ + { + pIterator->_dwBucket = 0; + pIterator->_fRemove = fRemove; + pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket); + + if (pIterator->_fRemove && pIterator->_pCursor != NULL) + { + _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext; + } + + return pIterator->_pCursor; + } + + STATIC_WSTRING_HASH_RECORD * + FindNext( + STATIC_WSTRING_HASH_ITER *pIterator + ) + /*++ + + Routine Description: + + Continues a hash item enumeration. + + Arguments: + + pIterator - Supplies the context for the enumeration. + + Return Value: + + The next entry in the hash if successful, NULL otherwise. + + --*/ + { + if (pIterator->_pCursor != NULL) + { + if (pIterator->_fRemove) + { + pIterator->_pCursor = _rgBuckets[pIterator->_dwBucket]; + } + else + { + pIterator->_pCursor = pIterator->_pCursor->_pNext; + } + + if (pIterator->_pCursor == NULL) + { + pIterator->_dwBucket++; + pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket); + } + } + + if (pIterator->_fRemove && pIterator->_pCursor != NULL) + { + _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext; + } + + return pIterator->_pCursor; + } + + protected: + + STATIC_WSTRING_HASH_RECORD * _rgBuckets[ STATIC_STRING_HASH_BUCKETS ]; + + private: + + BOOL _fCaseSensitive; + + STATIC_WSTRING_HASH_RECORD * + FindNextBucket( + DWORD *pdwStartingBucket + ) + /*++ + + Routine Description: + + Scan for the next non-empty bucket. + + Arguments: + + pdwStartingBucket - Supplies a pointer to the starting + bucket index. This value is updated with the index + of the next non-empty bucket if successful. + + Return Value: + + The first entry in the next non-empty bucket if successful, + NULL otherwise. + + --*/ + { + DWORD i; + STATIC_WSTRING_HASH_RECORD *pScan = NULL; + + for (i = *pdwStartingBucket ; i < STATIC_STRING_HASH_BUCKETS ; i++) + { + pScan = _rgBuckets[i]; + + if (pScan != NULL) + { + break; + } + } + + *pdwStartingBucket = i; + return pScan; + } +}; + + +#endif //__STATIC_HASH__H_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h new file mode 100644 index 0000000000..53a631b036 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +// +// Use C++ standard 'nullptr' +// + +#ifdef NULL +#undef NULL +#endif + +#ifdef __cplusplus +#ifdef _NATIVE_NULLPTR_SUPPORTED +#define NULL nullptr +#else +#define NULL 0 +#define nullptr 0 +#endif +#else +#define NULL ((void *)0) +//#define nullptr ((void *)0) +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h new file mode 100644 index 0000000000..d38604014e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h @@ -0,0 +1,515 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "buffer.h" +#include "macros.h" +#include + +class STRA +{ + +public: + + STRA( + VOID + ); + + STRA( + __inout_ecount(cchInit) CHAR* pbInit, + __in DWORD cchInit + ); + + BOOL + IsEmpty( + VOID + ) const; + + BOOL + Equals( + __in PCSTR pszRhs, + __in BOOL fIgnoreCase = FALSE + ) const; + + BOOL + Equals( + __in const STRA * pstrRhs, + __in BOOL fIgnoreCase = FALSE + ) const; + + BOOL + Equals( + __in const STRA & strRhs, + __in BOOL fIgnoreCase = FALSE + ) const; + + static + BOOL + Equals( + __in PCSTR pszLhs, + __in PCSTR pszRhs, + __in bool fIgnoreCase = false + ) + { + // Return FALSE if either or both strings are NULL. + if (!pszLhs || !pszRhs) return FALSE; + + if( fIgnoreCase ) + { + return ( 0 == _stricmp( pszLhs, pszRhs ) ); + } + + return ( 0 == strcmp( pszLhs, pszRhs ) ); + } + + VOID + Trim(); + + BOOL + StartsWith( + __in const STRA * pStraPrefix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + StartsWith( + __in const STRA & straPrefix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + StartsWith( + __in PCSTR pszPrefix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + EndsWith( + __in const STRA * pStraSuffix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + EndsWith( + __in const STRA & straSuffix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + EndsWith( + __in PCSTR pszSuffix, + __in bool fIgnoreCase = FALSE + ) const; + + INT + IndexOf( + __in CHAR charValue, + __in DWORD dwStartIndex = 0 + ) const; + + INT + IndexOf( + __in PCSTR pszValue, + __in DWORD dwStartIndex = 0 + ) const; + + INT + LastIndexOf( + __in CHAR charValue, + __in DWORD dwStartIndex = 0 + ) const; + + DWORD + QueryCB( + VOID + ) const; + + DWORD + QueryCCH( + VOID + ) const; + + DWORD + QuerySizeCCH( + VOID + ) const; + + DWORD + QuerySize( + VOID + ) const; + + __nullterminated + __bcount(this->m_cchLen) + CHAR * + QueryStr( + VOID + ) const; + + VOID + Reset( + VOID + ); + + HRESULT + Resize( + __in DWORD cchSize + ); + + HRESULT + SyncWithBuffer( + VOID + ); + + HRESULT + Copy( + __in PCSTR pszCopy + ); + + HRESULT + Copy( + __in_ecount(cbLen) + PCSTR pszCopy, + __in SIZE_T cbLen + ); + + HRESULT + Copy( + __in const STRA * pstrRhs + ); + + HRESULT + Copy( + __in const STRA & strRhs + ); + + HRESULT + CopyW( + __in PCWSTR pszCopyW + ); + + HRESULT + CopyW( + __in_ecount(cchLen) + PCWSTR pszCopyW, + __in SIZE_T cchLen, + __in UINT CodePage = CP_UTF8, + __in BOOL fFailIfNoTranslation = FALSE + ) + { + _ASSERTE( cchLen <= MAXDWORD ); + + return AuxAppendW( + pszCopyW, + static_cast(cchLen), + 0, + CodePage, + fFailIfNoTranslation + ); + } + + HRESULT + CopyWTruncate( + __in PCWSTR pszCopyWTruncate + ); + + HRESULT + CopyWTruncate( + __in_ecount(cchLen) + PCWSTR pszCopyWTruncate, + __in SIZE_T cchLen + ); + + HRESULT + Append( + __in PCSTR pszAppend + ); + + HRESULT + Append( + __in_ecount(cbLen) + PCSTR pszAppend, + __in SIZE_T cbLen + ); + + HRESULT + Append( + __in const STRA * pstrRhs + ); + + HRESULT + Append( + __in const STRA & strRhs + ); + + HRESULT + AppendW( + __in PCWSTR pszAppendW + ) + { + HRESULT hr; + size_t cchLen; + hr = StringCchLengthW( pszAppendW, + STRSAFE_MAX_CCH, + &cchLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return AppendW( pszAppendW, cchLen ); + } + + HRESULT + AppendW( + __in_ecount(cchLen) + PCWSTR pszAppendW, + __in SIZE_T cchLen, + __in UINT CodePage = CP_UTF8, + __in BOOL fFailIfNoTranslation = FALSE + ) + { + _ASSERTE( cchLen <= MAXDWORD ); + if ( cchLen == 0 ) + { + return S_OK; + } + return AuxAppendW( + pszAppendW, + static_cast(cchLen), + QueryCB(), + CodePage, + fFailIfNoTranslation + ); + } + + HRESULT + AppendWTruncate( + __in PCWSTR pszAppendWTruncate + ); + + HRESULT + AppendWTruncate( + __in_ecount(cchLen) + PCWSTR pszAppendWTruncate, + __in SIZE_T cchLen + ); + + HRESULT + CopyToBuffer( + __out_bcount(*pcb) CHAR* pszBuffer, + __inout DWORD * pcb + ) const; + + HRESULT + SetLen( + __in DWORD cchLen + ); + + HRESULT + SafeSnprintf( + __in __format_string + PCSTR pszFormatString, + ... + ); + + HRESULT + SafeVsnprintf( + __in __format_string + PCSTR pszFormatString, + va_list argsList + ); + + HRESULT + Escape( + VOID + ); + + HRESULT + EscapeUtf8( + VOID + ); + + VOID + Unescape( + VOID + ); + + HRESULT + CopyWToUTF8Unescaped( + __in LPCWSTR cpchStr + ); + + HRESULT + CopyWToUTF8Unescaped( + __in_ecount(cch) + LPCWSTR cpchStr, + __in DWORD cch + ); + + HRESULT + CopyWToUTF8Escaped( + __in LPCWSTR cpchStr + ); + + HRESULT + CopyWToUTF8Escaped( + __in_ecount(cch) + LPCWSTR cpchStr, + __in DWORD cch + ); + +private: + + // + // Avoid C++ errors. This object should never go through a copy + // constructor, unintended cast or assignment. + // + STRA( const STRA &); + STRA & operator = (const STRA &); + + HRESULT + AuxAppend( + __in_ecount(cbLen) + LPCSTR pStr, + __in DWORD cbLen, + __in DWORD cbOffset + ); + + HRESULT + AuxAppendW( + __in_ecount(cchAppendW) + PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset, + __in UINT CodePage, + __in BOOL fFailIfNoTranslation + ) + { + DWORD dwFlags = 0; + + if( CP_ACP == CodePage ) + { + dwFlags = WC_NO_BEST_FIT_CHARS; + } + else if( fFailIfNoTranslation && CodePage == CP_UTF8 ) + { + // + // WC_ERR_INVALID_CHARS is only supported in Longhorn or greater. + // +#if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + dwFlags |= WC_ERR_INVALID_CHARS; +#else + UNREFERENCED_PARAMETER(fFailIfNoTranslation); +#endif + } + + return AuxAppendW( pszAppendW, + cchAppendW, + cbOffset, + CodePage, + fFailIfNoTranslation, + dwFlags ); + } + + HRESULT + AuxAppendW( + __in_ecount(cchAppendW) + PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset, + __in UINT CodePage, + __in BOOL fFailIfNoTranslation, + __in DWORD dwFlags + ); + + HRESULT + AuxAppendWTruncate( + __in_ecount(cchAppendW) + __in PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset + ); + + static + int + ConvertUnicodeToCodePage( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __inout BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen, + __in UINT uCodePage + ); + + static + HRESULT + ConvertUnicodeToMultiByte( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __in BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen + ); + + static + HRESULT + ConvertUnicodeToUTF8( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __in BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen + ); + + typedef bool (* PFN_F_SHOULD_ESCAPE)(BYTE ch); + + HRESULT + EscapeInternal( + PFN_F_SHOULD_ESCAPE pfnFShouldEscape + ); + + // + // Buffer with an inline buffer of 1, + // enough to hold null-terminating character. + // + BUFFER_T m_Buff; + DWORD m_cchLen; +}; + +inline +HRESULT +AppendToString( + ULONGLONG Number, + STRA & String +) +{ + // prefast complains Append requires input + // to be null terminated, so zero initialize + // and pass the size of the buffer minus one + // to _ui64toa_s + CHAR chNumber[32] = {0}; + if (_ui64toa_s(Number, + chNumber, + sizeof(chNumber) - sizeof(CHAR), + 10) != 0) + { + return E_INVALIDARG; + } + return String.Append(chNumber); +} + +template +CHAR* InitHelper(__out CHAR (&psz)[size]) +{ + psz[0] = '\0'; + return psz; +} + +// +// Heap operation reduction macros +// +#define STACK_STRA(name, size) CHAR __ach##name[size];\ + STRA name(InitHelper(__ach##name), sizeof(__ach##name)) + +#define INLINE_STRA(name, size) CHAR __ach##name[size];\ + STRA name; + +#define INLINE_STRA_INIT(name) name(InitHelper(__ach##name), sizeof(__ach##name)) diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h new file mode 100644 index 0000000000..6c8f8f755b --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h @@ -0,0 +1,433 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "buffer.h" +#include + +class STRU +{ + +public: + + STRU( + VOID + ); + + STRU( + __inout_ecount(cchInit) WCHAR* pbInit, + __in DWORD cchInit + ); + + BOOL + IsEmpty( + VOID + ) const; + + BOOL + Equals( + __in const STRU * pstrRhs, + __in BOOL fIgnoreCase = FALSE + ) const + { + _ASSERTE( pstrRhs != NULL ); + return Equals( pstrRhs->QueryStr(), fIgnoreCase ); + } + + BOOL + Equals( + __in const STRU & strRhs, + __in BOOL fIgnoreCase = FALSE + ) const + { + return Equals( strRhs.QueryStr(), fIgnoreCase ); + } + + BOOL + Equals( + __in PCWSTR pszRhs, + __in BOOL fIgnoreCase = FALSE + ) const + { + _ASSERTE( NULL != pszRhs ); + if ( NULL == pszRhs ) + { + return FALSE; + } + + #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + return ( CSTR_EQUAL == CompareStringOrdinal( QueryStr(), + QueryCCH(), + pszRhs, + -1, + fIgnoreCase ) ); + #else + + if( fIgnoreCase ) + { + return ( 0 == _wcsicmp( QueryStr(), pszRhs ) ); + } + return ( 0 == wcscmp( QueryStr(), pszRhs ) ); + + #endif + } + + + static + BOOL + Equals( + __in PCWSTR pwszLhs, + __in PCWSTR pwszRhs, + __in bool fIgnoreCase = false + ) + { + // Return FALSE if either or both strings are NULL. + if (!pwszLhs || !pwszRhs) return FALSE; + + // + // This method performs a ordinal string comparison when OS is Vista or + // greater and a culture sensitive comparison if not (XP). This is + // consistent with the existing Equals implementation (see above). + // +#if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + return ( CSTR_EQUAL == CompareStringOrdinal( pwszLhs, + -1, + pwszRhs, + -1, + fIgnoreCase ) ); +#else + + if( fIgnoreCase ) + { + return ( 0 == _wcsicmp( pwszLhs, pwszRhs ) ); + } + else + { + return ( 0 == wcscmp( pwszLhs, pwszRhs ) ); + } + +#endif + } + + VOID + Trim(); + + BOOL + StartsWith( + __in const STRU * pStruPrefix, + __in bool fIgnoreCase = FALSE + ) const + { + _ASSERTE( pStruPrefix != NULL ); + return StartsWith( pStruPrefix->QueryStr(), fIgnoreCase ); + } + + BOOL + StartsWith( + __in const STRU & struPrefix, + __in bool fIgnoreCase = FALSE + ) const + { + return StartsWith( struPrefix.QueryStr(), fIgnoreCase ); + } + + BOOL + StartsWith( + __in PCWSTR pwszPrefix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + EndsWith( + __in const STRU * pStruSuffix, + __in bool fIgnoreCase = FALSE + ) const + { + _ASSERTE( pStruSuffix != NULL ); + return EndsWith( pStruSuffix->QueryStr(), fIgnoreCase ); + } + + BOOL + EndsWith( + __in const STRU & struSuffix, + __in bool fIgnoreCase = FALSE + ) const + { + return EndsWith( struSuffix.QueryStr(), fIgnoreCase ); + } + + BOOL + EndsWith( + __in PCWSTR pwszSuffix, + __in bool fIgnoreCase = FALSE + ) const; + + INT + IndexOf( + __in WCHAR charValue, + __in DWORD dwStartIndex = 0 + ) const; + + INT + IndexOf( + __in PCWSTR pwszValue, + __in DWORD dwStartIndex = 0 + ) const; + + INT + LastIndexOf( + __in WCHAR charValue, + __in DWORD dwStartIndex = 0 + ) const; + + DWORD + QueryCB( + VOID + ) const; + + DWORD + QueryCCH( + VOID + ) const; + + DWORD + QuerySizeCCH( + VOID + ) const; + + __nullterminated + __ecount(this->m_cchLen) + WCHAR* + QueryStr( + VOID + ) const; + + VOID + Reset( + VOID + ); + + HRESULT + Resize( + DWORD cchSize + ); + + HRESULT + SyncWithBuffer( + VOID + ); + + template + HRESULT + Copy( + __in PCWSTR const (&rgpszStrings)[size] + ) + // + // Copies an array of strings declared as stack array. For example: + // + // LPCWSTR rgExample[] { L"one", L"two" }; + // hr = str.Copy( rgExample ); + // + { + Reset(); + + return AuxAppend( rgpszStrings, _countof( rgpszStrings ) ); + } + + HRESULT + Copy( + __in PCWSTR pszCopy + ); + + HRESULT + Copy( + __in_ecount(cchLen) + PCWSTR pszCopy, + SIZE_T cchLen + ); + + HRESULT + Copy( + __in const STRU * pstrRhs + ); + + HRESULT + Copy( + __in const STRU & str + ); + + HRESULT + CopyAndExpandEnvironmentStrings( + __in PCWSTR pszSource + ); + + HRESULT + CopyA( + __in PCSTR pszCopyA + ); + + HRESULT + CopyA( + __in_bcount(cchLen) + PCSTR pszCopyA, + SIZE_T cchLen, + UINT CodePage = CP_UTF8 + ); + + template + HRESULT + Append( + __in PCWSTR const (&rgpszStrings)[size] + ) + // + // Appends an array of strings declared as stack array. For example: + // + // LPCWSTR rgExample[] { L"one", L"two" }; + // hr = str.Append( rgExample ); + // + { + return AuxAppend( rgpszStrings, _countof( rgpszStrings ) ); + } + + HRESULT + Append( + __in PCWSTR pszAppend + ); + + HRESULT + Append( + __in_ecount(cchLen) + PCWSTR pszAppend, + SIZE_T cchLen + ); + + HRESULT + Append( + __in const STRU * pstrRhs + ); + + HRESULT + Append( + __in const STRU & strRhs + ); + + HRESULT + AppendA( + __in PCSTR pszAppendA + ); + + HRESULT + AppendA( + __in_bcount(cchLen) + PCSTR pszAppendA, + SIZE_T cchLen, + UINT CodePage = CP_UTF8 + ); + + HRESULT + CopyToBuffer( + __out_bcount(*pcb) WCHAR* pszBuffer, + PDWORD pcb + ) const; + + HRESULT + CopyToBufferA( + __out_bcount(*pcb) CHAR* pszBuffer, + __inout PDWORD pcb + ) const; + + HRESULT + SetLen( + __in DWORD cchLen + ); + + HRESULT + SafeSnwprintf( + __in PCWSTR pwszFormatString, + ... + ); + + HRESULT + SafeVsnwprintf( + __in PCWSTR pwszFormatString, + va_list argsList + ); + + static + HRESULT ExpandEnvironmentVariables( + __in PCWSTR pszString, + __out STRU * pstrExpandedString + ); + +private: + + // + // Avoid C++ errors. This object should never go through a copy + // constructor, unintended cast or assignment. + // + STRU( const STRU & ); + STRU & operator = ( const STRU & ); + + HRESULT + AuxAppend( + __in_ecount(cNumStrings) + PCWSTR const rgpszStrings[], + SIZE_T cNumStrings + ); + + HRESULT + AuxAppend( + __in_bcount(cbStr) + const WCHAR* pStr, + SIZE_T cbStr, + DWORD cbOffset + ); + + HRESULT + AuxAppendA( + __in_bcount(cbStr) + const CHAR* pStr, + SIZE_T cbStr, + DWORD cbOffset, + UINT CodePage + ); + + // + // Buffer with an inline buffer of 1, + // enough to hold null-terminating character. + // + BUFFER_T m_Buff; + DWORD m_cchLen; +}; + +// +// Helps to initialize an external buffer before +// constructing the STRU object. +// +template +WCHAR* InitHelper(__out WCHAR (&psz)[size]) +{ + psz[0] = L'\0'; + return psz; +} + +// +// Heap operation reduction macros +// +#define STACK_STRU(name, size) WCHAR __ach##name[size];\ + STRU name(InitHelper(__ach##name), sizeof(__ach##name)/sizeof(*__ach##name)) + +#define INLINE_STRU(name, size) WCHAR __ach##name[size];\ + STRU name; + +#define INLINE_STRU_INIT(name) name(InitHelper(__ach##name), sizeof(__ach##name)/sizeof(*__ach##name)) + + +HRESULT +MakePathCanonicalizationProof( + IN PCWSTR pszName, + OUT STRU * pstrPath +); diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h new file mode 100644 index 0000000000..b0fba23559 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h @@ -0,0 +1,243 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STTIMER_H +#define _STTIMER_H + +class STTIMER +{ +public: + + STTIMER() + : _pTimer( NULL ) + { + fInCanel = FALSE; + } + + virtual + ~STTIMER() + { + if ( _pTimer ) + { + CancelTimer(); + + CloseThreadpoolTimer( _pTimer ); + + _pTimer = NULL; + } + } + + HRESULT + InitializeTimer( + PTP_TIMER_CALLBACK pfnCallback, + VOID * pContext, + DWORD dwInitialWait = 0, + DWORD dwPeriod = 0 + ) + { + _pTimer = CreateThreadpoolTimer( pfnCallback, + pContext, + NULL ); + + if ( !_pTimer ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + if ( dwInitialWait ) + { + SetTimer( dwInitialWait, + dwPeriod ); + } + + return S_OK; + } + + VOID + SetTimer( + DWORD dwInitialWait, + DWORD dwPeriod = 0 + ) + { + FILETIME ftInitialWait; + + if ( dwInitialWait == 0 && dwPeriod == 0 ) + { + // + // Special case. We are preventing new callbacks + // from being queued. Any existing callbacks in the + // queue will still run. + // + // This effectively disables the timer. It can be + // re-enabled by setting non-zero initial wait or + // period values. + // + if (_pTimer != NULL) + { + SetThreadpoolTimer(_pTimer, NULL, 0, 0); + } + + return; + } + + InitializeRelativeFileTime( &ftInitialWait, dwInitialWait ); + + SetThreadpoolTimer( _pTimer, + &ftInitialWait, + dwPeriod, + 0 ); + } + + VOID + CancelTimer() + { + // + // Disable the timer + // + if (fInCanel) + return; + + fInCanel = TRUE; + SetTimer( 0 ); + + // + // Wait until any callbacks queued prior to disabling + // have completed. + // + if (_pTimer != NULL) + WaitForThreadpoolTimerCallbacks( _pTimer, TRUE ); + + _pTimer = NULL; + fInCanel = FALSE; + } + +private: + + VOID + InitializeRelativeFileTime( + FILETIME * pft, + DWORD dwMilliseconds + ) + { + LARGE_INTEGER li; + + // + // The pftDueTime parameter expects the time to be + // expressed as the number of 100 nanosecond intervals + // times -1. + // + // To convert from milliseconds, we'll multiply by + // -10000 + // + + li.QuadPart = (LONGLONG)dwMilliseconds * -10000; + + pft->dwHighDateTime = li.HighPart; + pft->dwLowDateTime = li.LowPart; + }; + + TP_TIMER * _pTimer; + BOOL fInCanel; +}; + +class STELAPSED +{ +public: + + STELAPSED() + : _dwInitTime( 0 ), + _dwInitTickCount( 0 ), + _dwPerfCountsPerMillisecond( 0 ), + _fUsingHighResolution( FALSE ) + { + LARGE_INTEGER li; + BOOL fResult; + + _dwInitTickCount = GetTickCount64(); + + fResult = QueryPerformanceFrequency( &li ); + + if ( !fResult ) + { + goto Finished; + } + + _dwPerfCountsPerMillisecond = li.QuadPart / 1000; + + fResult = QueryPerformanceCounter( &li ); + + if ( !fResult ) + { + goto Finished; + } + + _dwInitTime = li.QuadPart / _dwPerfCountsPerMillisecond; + + _fUsingHighResolution = TRUE; + +Finished: + + return; + } + + virtual + ~STELAPSED() + { + } + + LONGLONG + QueryElapsedTime() + { + LARGE_INTEGER li; + + if ( _fUsingHighResolution && QueryPerformanceCounter( &li ) ) + { + DWORD64 dwCurrentTime = li.QuadPart / _dwPerfCountsPerMillisecond; + + if ( dwCurrentTime < _dwInitTime ) + { + // + // It's theoretically possible that QueryPerformanceCounter + // may return slightly different values on different CPUs. + // In this case, we don't want to return an unexpected value + // so we'll return zero. This is acceptable because + // presumably such a case would only happen for a very short + // time window. + // + // It would be possible to prevent this by ensuring processor + // affinity for all calls to QueryPerformanceCounter, but that + // would be undesirable in the general case because it could + // introduce unnecessary context switches and potentially a + // CPU bottleneck. + // + // Note that this issue also applies to callers doing rapid + // calls to this function. If a caller wants to mitigate + // that, they could enforce the affinitization, or they + // could implement a similar sanity check when comparing + // returned values from this function. + // + + return 0; + } + + return dwCurrentTime - _dwInitTime; + } + + return GetTickCount64() - _dwInitTickCount; + } + + BOOL + QueryUsingHighResolution() + { + return _fUsingHighResolution; + } + +private: + + DWORD64 _dwInitTime; + DWORD64 _dwInitTickCount; + DWORD64 _dwPerfCountsPerMillisecond; + BOOL _fUsingHighResolution; +}; + +#endif // _STTIMER_H \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h new file mode 100644 index 0000000000..1caff82ce3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _TRACELOG_H_ +#define _TRACELOG_H_ + + +#if defined(__cplusplus) +extern "C" { +#endif // __cplusplus + + +typedef struct _TRACE_LOG { + + // + // Signature. + // + + LONG Signature; + + // + // The total number of entries available in the log. + // + + LONG LogSize; + + // + // The index of the next entry to use. + // + + LONG NextEntry; + + // + // The byte size of each entry. + // + + LONG EntrySize; + + // + // Pointer to the start of the circular buffer. + // + + PUCHAR LogBuffer; + + // + // The extra header bytes and actual log entries go here. + // + // BYTE ExtraHeaderBytes[ExtraBytesInHeader]; + // BYTE Entries[LogSize][EntrySize]; + // + +} TRACE_LOG, *PTRACE_LOG; + + +// +// Log header signature. +// + +#define TRACE_LOG_SIGNATURE ((DWORD)'gOlT') +#define TRACE_LOG_SIGNATURE_X ((DWORD)'golX') + + +// +// This macro maps a TRACE_LOG pointer to a pointer to the 'extra' +// data associated with the log. +// + +#define TRACE_LOG_TO_EXTRA_DATA(log) (PVOID)( (log) + 1 ) + + +// +// Manipulators. +// + +PTRACE_LOG +CreateTraceLog( + IN LONG LogSize, + IN LONG ExtraBytesInHeader, + IN LONG EntrySize + ); + +VOID +DestroyTraceLog( + IN PTRACE_LOG Log + ); + +LONG +WriteTraceLog( + IN PTRACE_LOG Log, + IN PVOID Entry + ); + +VOID +ResetTraceLog( + IN PTRACE_LOG Log + ); + + +#if defined(__cplusplus) +} // extern "C" +#endif // __cplusplus + + +#endif // _TRACELOG_H_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h new file mode 100644 index 0000000000..79f5a83ead --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h @@ -0,0 +1,850 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include +#include "rwlock.h" +#include "prime.h" + +template +class TREE_HASH_NODE +{ + template + friend class TREE_HASH_TABLE; + + private: + // Next node in the hash table look-aside + TREE_HASH_NODE<_Record> *_pNext; + + // links in the tree structure + TREE_HASH_NODE * _pParentNode; + TREE_HASH_NODE * _pFirstChild; + TREE_HASH_NODE * _pNextSibling; + + // actual record + _Record * _pRecord; + + // hash value + PCWSTR _pszPath; + DWORD _dwHash; +}; + +template +class TREE_HASH_TABLE +{ +protected: + typedef BOOL + (PFN_DELETE_IF)( + _Record * pRecord, + PVOID pvContext + ); + + typedef VOID + (PFN_APPLY)( + _Record * pRecord, + PVOID pvContext + ); + +public: + TREE_HASH_TABLE( + BOOL fCaseSensitive + ) : _ppBuckets( NULL ), + _nBuckets( 0 ), + _nItems( 0 ), + _fCaseSensitive( fCaseSensitive ) + { + } + + virtual + ~TREE_HASH_TABLE(); + + virtual + VOID + ReferenceRecord( + _Record * pRecord + ) = 0; + + virtual + VOID + DereferenceRecord( + _Record * pRecord + ) = 0; + + virtual + PCWSTR + GetKey( + _Record * pRecord + ) = 0; + + DWORD + Count() + { + return _nItems; + } + + virtual + VOID + Clear(); + + HRESULT + Initialize( + DWORD nBucketSize + ); + + DWORD + CalcHash( + PCWSTR pszKey + ) + { + return _fCaseSensitive ? HashString(pszKey) : HashStringNoCase(pszKey); + } + + virtual + VOID + FindKey( + PCWSTR pszKey, + _Record ** ppRecord + ); + + virtual + HRESULT + InsertRecord( + _Record * pRecord + ); + + virtual + VOID + DeleteKey( + PCWSTR pszKey + ); + + virtual + VOID + DeleteIf( + PFN_DELETE_IF pfnDeleteIf, + PVOID pvContext + ); + + VOID + Apply( + PFN_APPLY pfnApply, + PVOID pvContext + ); + +private: + + BOOL + FindNodeInternal( + PCWSTR pszKey, + DWORD dwHash, + TREE_HASH_NODE<_Record> ** ppNode, + TREE_HASH_NODE<_Record> *** pppPreviousNodeNextPointer = NULL + ); + + HRESULT + AddNodeInternal( + PCWSTR pszPath, + DWORD dwHash, + _Record * pRecord, + TREE_HASH_NODE<_Record> * pParentNode, + TREE_HASH_NODE<_Record> ** ppNewNode + ); + + HRESULT + AllocateNode( + PCWSTR pszPath, + DWORD dwHash, + _Record * pRecord, + TREE_HASH_NODE<_Record> * pParentNode, + TREE_HASH_NODE<_Record> ** ppNewNode + ); + + VOID + DeleteNode( + TREE_HASH_NODE<_Record> * pNode + ) + { + if (pNode->_pRecord != NULL) + { + DereferenceRecord(pNode->_pRecord); + pNode->_pRecord = NULL; + } + + HeapFree(GetProcessHeap(), + 0, + pNode); + } + + VOID + DeleteNodeInternal( + TREE_HASH_NODE<_Record> ** ppPreviousNodeNextPointer, + TREE_HASH_NODE<_Record> * pNode + ); + + VOID + RehashTableIfNeeded( + VOID + ); + + TREE_HASH_NODE<_Record> ** _ppBuckets; + DWORD _nBuckets; + DWORD _nItems; + BOOL _fCaseSensitive; + CWSDRWLock _tableLock; +}; + +template +HRESULT +TREE_HASH_TABLE<_Record>::AllocateNode( + PCWSTR pszPath, + DWORD dwHash, + _Record * pRecord, + TREE_HASH_NODE<_Record> * pParentNode, + TREE_HASH_NODE<_Record> ** ppNewNode +) +{ + // + // Allocate enough extra space for pszPath + // + DWORD cchPath = (DWORD) wcslen(pszPath); + if (cchPath >= ((0xffffffff - sizeof(TREE_HASH_NODE<_Record>))/sizeof(WCHAR) - 1)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + } + TREE_HASH_NODE<_Record> *pNode = (TREE_HASH_NODE<_Record> *)HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(TREE_HASH_NODE<_Record>) + (cchPath+1)*sizeof(WCHAR)); + if (pNode == NULL) + { + return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + } + + memcpy(pNode+1, pszPath, (cchPath+1)*sizeof(WCHAR)); + pNode->_pszPath = (PCWSTR)(pNode+1); + pNode->_dwHash = dwHash; + pNode->_pNext = pNode->_pNextSibling = pNode->_pFirstChild = NULL; + pNode->_pParentNode = pParentNode; + pNode->_pRecord = pRecord; + + *ppNewNode = pNode; + return S_OK; +} + +template +HRESULT +TREE_HASH_TABLE<_Record>::Initialize( + DWORD nBuckets +) +{ + HRESULT hr = S_OK; + + if ( nBuckets == 0 ) + { + hr = E_INVALIDARG; + goto Failed; + } + + hr = _tableLock.Init(); + if ( FAILED( hr ) ) + { + goto Failed; + } + + if (nBuckets >= 0xffffffff/sizeof(TREE_HASH_NODE<_Record> *)) + { + hr = E_INVALIDARG; + goto Failed; + } + + _ppBuckets = (TREE_HASH_NODE<_Record> **)HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + nBuckets*sizeof(TREE_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 +TREE_HASH_TABLE<_Record>::~TREE_HASH_TABLE() +{ + if (_ppBuckets == NULL) + { + return; + } + + _ASSERTE(_nItems == 0); + + HeapFree(GetProcessHeap(), + 0, + _ppBuckets); + _ppBuckets = NULL; + _nBuckets = 0; +} + +template +VOID +TREE_HASH_TABLE<_Record>::Clear() +{ + TREE_HASH_NODE<_Record> *pCurrent; + TREE_HASH_NODE<_Record> *pNext; + + _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 +BOOL +TREE_HASH_TABLE<_Record>::FindNodeInternal( + PCWSTR pszKey, + DWORD dwHash, + TREE_HASH_NODE<_Record> ** ppNode, + TREE_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 +--*/ +{ + TREE_HASH_NODE<_Record> **ppPreviousNodeNextPointer; + TREE_HASH_NODE<_Record> *pNode; + BOOL fFound = FALSE; + + ppPreviousNodeNextPointer = _ppBuckets + (dwHash % _nBuckets); + pNode = *ppPreviousNodeNextPointer; + while (pNode != NULL) + { + if (pNode->_dwHash == dwHash) + { + if (CompareStringOrdinal(pszKey, + -1, + pNode->_pszPath, + -1, + !_fCaseSensitive) == CSTR_EQUAL) + { + fFound = TRUE; + break; + } + } + else if (pNode->_dwHash > dwHash) + { + break; + } + + ppPreviousNodeNextPointer = &(pNode->_pNext); + pNode = *ppPreviousNodeNextPointer; + } + + *ppNode = pNode; + if (pppPreviousNodeNextPointer != NULL) + { + *pppPreviousNodeNextPointer = ppPreviousNodeNextPointer; + } + return fFound; +} + +template +VOID +TREE_HASH_TABLE<_Record>::FindKey( + PCWSTR pszKey, + _Record ** ppRecord +) +{ + TREE_HASH_NODE<_Record> *pNode; + + *ppRecord = NULL; + + DWORD dwHash = CalcHash(pszKey); + + _tableLock.SharedAcquire(); + + if (FindNodeInternal(pszKey, dwHash, &pNode) && + pNode->_pRecord != NULL) + { + ReferenceRecord(pNode->_pRecord); + *ppRecord = pNode->_pRecord; + } + + _tableLock.SharedRelease(); +} + +template +HRESULT +TREE_HASH_TABLE<_Record>::AddNodeInternal( + PCWSTR pszPath, + DWORD dwHash, + _Record * pRecord, + TREE_HASH_NODE<_Record> * pParentNode, + TREE_HASH_NODE<_Record> ** ppNewNode +) +/*++ + Return value is HRESULT indicating sucess or failure + pszPath, dwHash, pRecord - path, hash value and record to be inserted + pParentNode - this will be the parent of the node being inserted + ppNewNode - on successful return, the new node created and inserted + + This function may be called under a read or write lock +--*/ +{ + TREE_HASH_NODE<_Record> *pNewNode; + TREE_HASH_NODE<_Record> *pNextNode; + TREE_HASH_NODE<_Record> **ppNextPointer; + HRESULT hr; + + // + // 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 + // + hr = AllocateNode(pszPath, + dwHash, + pRecord, + pParentNode, + &pNewNode); + if (FAILED(hr)) + { + return hr; + } + + do + { + // + // Find the right place to add this node + // + + if (FindNodeInternal(pszPath, dwHash, &pNextNode, &ppNextPointer)) + { + // + // If node already there, record may still need updating + // + if (pRecord != NULL && + InterlockedCompareExchangePointer((PVOID *)&pNextNode->_pRecord, + pRecord, + NULL) == NULL) + { + ReferenceRecord(pRecord); + hr = S_OK; + } + else + { + hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); + } + + // ownership of pRecord has either passed to existing record or + // not to anyone at all + pNewNode->_pRecord = NULL; + DeleteNode(pNewNode); + *ppNewNode = pNextNode; + return hr; + } + + // + // If another node got inserted in betwen, we will have to retry + // + pNewNode->_pNext = pNextNode; + } while (InterlockedCompareExchangePointer((PVOID *)ppNextPointer, + pNewNode, + pNextNode) != pNextNode); + // pass ownership of pRecord now + if (pRecord != NULL) + { + ReferenceRecord(pRecord); + pRecord = NULL; + } + InterlockedIncrement((LONG *)&_nItems); + + // + // update the parent + // + if (pParentNode != NULL) + { + ppNextPointer = &pParentNode->_pFirstChild; + do + { + pNextNode = *ppNextPointer; + pNewNode->_pNextSibling = pNextNode; + } while (InterlockedCompareExchangePointer((PVOID *)ppNextPointer, + pNewNode, + pNextNode) != pNextNode); + } + + *ppNewNode = pNewNode; + return S_OK; +} + +template +HRESULT +TREE_HASH_TABLE<_Record>::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. +--*/ +{ + PCWSTR pszKey = GetKey(pRecord); + STACK_STRU( strPartialPath, 256); + PWSTR pszPartialPath; + DWORD dwHash; + DWORD cchEnd; + HRESULT hr; + TREE_HASH_NODE<_Record> *pParentNode = NULL; + + hr = strPartialPath.Copy(pszKey); + if (FAILED(hr)) + { + goto Finished; + } + pszPartialPath = strPartialPath.QueryStr(); + + _tableLock.SharedAcquire(); + + // + // First find the lowest parent node present + // + for (cchEnd = strPartialPath.QueryCCH() - 1; cchEnd > 0; cchEnd--) + { + if (pszPartialPath[cchEnd] == L'/' || pszPartialPath[cchEnd] == L'\\') + { + pszPartialPath[cchEnd] = L'\0'; + + dwHash = CalcHash(pszPartialPath); + if (FindNodeInternal(pszPartialPath, dwHash, &pParentNode)) + { + pszPartialPath[cchEnd] = pszKey[cchEnd]; + break; + } + pParentNode = NULL; + } + } + + // + // Now go ahead and add the rest of the tree (including our record) + // + for (; cchEnd <= strPartialPath.QueryCCH(); cchEnd++) + { + if (pszPartialPath[cchEnd] == L'\0') + { + dwHash = CalcHash(pszPartialPath); + hr = AddNodeInternal( + pszPartialPath, + dwHash, + (cchEnd == strPartialPath.QueryCCH()) ? pRecord : NULL, + pParentNode, + &pParentNode); + if (FAILED(hr) && + hr != HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) + { + goto Finished; + } + + pszPartialPath[cchEnd] = pszKey[cchEnd]; + } + } + +Finished: + _tableLock.SharedRelease(); + + if (SUCCEEDED(hr)) + { + RehashTableIfNeeded(); + } + + return hr; +} + +template +VOID +TREE_HASH_TABLE<_Record>::DeleteNodeInternal( + TREE_HASH_NODE<_Record> ** ppNextPointer, + TREE_HASH_NODE<_Record> * pNode +) +/*++ + pNode is the node to be deleted + ppNextPointer is the pointer to the previous node's next pointer pointing + to this node + + This function should be called under write-lock +--*/ +{ + // + // First remove this node from hash table + // + *ppNextPointer = pNode->_pNext; + + // + // Now fixup parent + // + if (pNode->_pParentNode != NULL) + { + ppNextPointer = &pNode->_pParentNode->_pFirstChild; + while (*ppNextPointer != pNode) + { + ppNextPointer = &(*ppNextPointer)->_pNextSibling; + } + *ppNextPointer = pNode->_pNextSibling; + } + + // + // Now remove all children recursively + // + TREE_HASH_NODE<_Record> *pChild = pNode->_pFirstChild; + TREE_HASH_NODE<_Record> *pNextChild; + while (pChild != NULL) + { + pNextChild = pChild->_pNextSibling; + + ppNextPointer = _ppBuckets + (pChild->_dwHash % _nBuckets); + while (*ppNextPointer != pChild) + { + ppNextPointer = &(*ppNextPointer)->_pNext; + } + pChild->_pParentNode = NULL; + DeleteNodeInternal(ppNextPointer, pChild); + + pChild = pNextChild; + } + + DeleteNode(pNode); + _nItems--; +} + +template +VOID +TREE_HASH_TABLE<_Record>::DeleteKey( + PCWSTR pszKey +) +{ + TREE_HASH_NODE<_Record> *pNode; + TREE_HASH_NODE<_Record> **ppPreviousNodeNextPointer; + + DWORD dwHash = CalcHash(pszKey); + + _tableLock.ExclusiveAcquire(); + + if (FindNodeInternal(pszKey, dwHash, &pNode, &ppPreviousNodeNextPointer)) + { + DeleteNodeInternal(ppPreviousNodeNextPointer, pNode); + } + + _tableLock.ExclusiveRelease(); +} + +template +VOID +TREE_HASH_TABLE<_Record>::DeleteIf( + PFN_DELETE_IF pfnDeleteIf, + PVOID pvContext +) +{ + TREE_HASH_NODE<_Record> *pNode; + TREE_HASH_NODE<_Record> **ppPreviousNodeNextPointer; + BOOL fDelete; + + _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 + // + fDelete = FALSE; + if (pNode->_pRecord != NULL) + { + if (pfnDeleteIf(pNode->_pRecord, pvContext)) + { + fDelete = TRUE; + } + } + else if (pNode->_pFirstChild == NULL) + { + fDelete = TRUE; + } + + if (fDelete) + { + if (pNode->_pFirstChild == NULL) + { + DeleteNodeInternal(ppPreviousNodeNextPointer, pNode); + } + else + { + DereferenceRecord(pNode->_pRecord); + pNode->_pRecord = NULL; + } + } + else + { + ppPreviousNodeNextPointer = &pNode->_pNext; + } + + pNode = *ppPreviousNodeNextPointer; + } + } + + _tableLock.ExclusiveRelease(); +} + +template +VOID +TREE_HASH_TABLE<_Record>::Apply( + PFN_APPLY pfnApply, + PVOID pvContext +) +{ + TREE_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 +VOID +TREE_HASH_TABLE<_Record>::RehashTableIfNeeded( + VOID +) +{ + TREE_HASH_NODE<_Record> **ppBuckets; + DWORD nBuckets; + TREE_HASH_NODE<_Record> *pNode; + TREE_HASH_NODE<_Record> *pNextNode; + TREE_HASH_NODE<_Record> **ppNextPointer; + TREE_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(TREE_HASH_NODE<_Record> *)) + { + goto Finished; + } + ppBuckets = (TREE_HASH_NODE<_Record> **)HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + nBuckets*sizeof(TREE_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(); +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE new file mode 100644 index 0000000000..21071075c2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs new file mode 100644 index 0000000000..ee607e28c7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.Web.Utility +{ + internal static class MySqlConnector + { + public static string[] HardCodedAssemblyVersions + { + get + { + return new string[] + { + "MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.4.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.3.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.2.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.0.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.0.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=5.2.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=5.2.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + }; + } + } + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs new file mode 100644 index 0000000000..9dc6dbfc23 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs @@ -0,0 +1,386 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; +using System.Security; +using System.Runtime.Versioning; +using System.Runtime.ConstrainedExecution; +using Microsoft.Win32.SafeHandles; + +namespace Microsoft.Web.Management.PInvoke.AdvApi32 +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct TOKEN_PRIVILEGES + { + public UInt32 PrivilegeCount; + public long Luid; + public UInt32 Attributes; + } + + internal enum TOKEN_INFORMATION_CLASS + { + /// + /// The buffer receives a TOKEN_USER structure that contains the user account of the token. + /// + TokenUser = 1, + + /// + /// The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token. + /// + TokenGroups, + + /// + /// The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token. + /// + TokenPrivileges, + + /// + /// The buffer receives a TOKEN_OWNER structure that contains the default owner security identifier (SID) for newly created objects. + /// + TokenOwner, + + /// + /// The buffer receives a TOKEN_PRIMARY_GROUP structure that contains the default primary group SID for newly created objects. + /// + TokenPrimaryGroup, + + /// + /// The buffer receives a TOKEN_DEFAULT_DACL structure that contains the default DACL for newly created objects. + /// + TokenDefaultDacl, + + /// + /// The buffer receives a TOKEN_SOURCE structure that contains the source of the token. TOKEN_QUERY_SOURCE access is needed to retrieve this information. + /// + TokenSource, + + /// + /// The buffer receives a TOKEN_TYPE value that indicates whether the token is a primary or impersonation token. + /// + TokenType, + + /// + /// The buffer receives a SECURITY_IMPERSONATION_LEVEL value that indicates the impersonation level of the token. If the access token is not an impersonation token, the function fails. + /// + TokenImpersonationLevel, + + /// + /// The buffer receives a TOKEN_STATISTICS structure that contains various token statistics. + /// + TokenStatistics, + + /// + /// The buffer receives a TOKEN_GROUPS structure that contains the list of restricting SIDs in a restricted token. + /// + TokenRestrictedSids, + + /// + /// The buffer receives a DWORD value that indicates the Terminal Services session identifier that is associated with the token. + /// + TokenSessionId, + + /// + /// The buffer receives a TOKEN_GROUPS_AND_PRIVILEGES structure that contains the user SID, the group accounts, the restricted SIDs, and the authentication ID associated with the token. + /// + TokenGroupsAndPrivileges, + + /// + /// Reserved. + /// + TokenSessionReference, + + /// + /// The buffer receives a DWORD value that is nonzero if the token includes the SANDBOX_INERT flag. + /// + TokenSandBoxInert, + + /// + /// Reserved. + /// + TokenAuditPolicy, + + /// + /// The buffer receives a TOKEN_ORIGIN value. + /// + TokenOrigin, + + /// + /// The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token. + /// + TokenElevationType, + + /// + /// The buffer receives a TOKEN_LINKED_TOKEN structure that contains a handle to another token that is linked to this token. + /// + TokenLinkedToken, + + /// + /// The buffer receives a TOKEN_ELEVATION structure that specifies whether the token is elevated. + /// + TokenElevation, + + /// + /// The buffer receives a DWORD value that is nonzero if the token has ever been filtered. + /// + TokenHasRestrictions, + + /// + /// The buffer receives a TOKEN_ACCESS_INFORMATION structure that specifies security information contained in the token. + /// + TokenAccessInformation, + + /// + /// The buffer receives a DWORD value that is nonzero if virtualization is allowed for the token. + /// + TokenVirtualizationAllowed, + + /// + /// The buffer receives a DWORD value that is nonzero if virtualization is enabled for the token. + /// + TokenVirtualizationEnabled, + + /// + /// The buffer receives a TOKEN_MANDATORY_LABEL structure that specifies the token's integrity level. + /// + TokenIntegrityLevel, + + /// + /// The buffer receives a DWORD value that is nonzero if the token has the UIAccess flag set. + /// + TokenUIAccess, + + /// + /// The buffer receives a TOKEN_MANDATORY_POLICY structure that specifies the token's mandatory integrity policy. + /// + TokenMandatoryPolicy, + + /// + /// The buffer receives the token's logon security identifier (SID). + /// + TokenLogonSid, + + /// + /// The maximum value for this enumeration + /// + MaxTokenInfoClass + } + + internal enum TOKEN_ELEVATION_TYPE + { + TokenElevationTypeDefault = 1, + TokenElevationTypeFull, + TokenElevationTypeLimited + } + + [Flags] + internal enum AccessTokenRights : uint + { + STANDARD_RIGHTS_REQUIRED = 0x000F0000, + STANDARD_RIGHTS_READ = 0x00020000, + TOKEN_ASSIGN_PRIMARY = 0x0001, + TOKEN_DUPLICATE = 0x0002, + TOKEN_IMPERSONATE = 0x0004, + TOKEN_QUERY = 0x0008, + TOKEN_QUERY_SOURCE = 0x0010, + TOKEN_ADJUST_PRIVILEGES = 0x0020, + TOKEN_ADJUST_GROUPS = 0x0040, + TOKEN_ADJUST_DEFAULT = 0x0080, + TOKEN_ADJUST_SESSIONID = 0x0100, + TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY, + TOKEN_ALL_ACCESS = + STANDARD_RIGHTS_REQUIRED | + TOKEN_ASSIGN_PRIMARY | + TOKEN_DUPLICATE | + TOKEN_IMPERSONATE | + TOKEN_QUERY | + TOKEN_QUERY_SOURCE | + TOKEN_ADJUST_PRIVILEGES | + TOKEN_ADJUST_GROUPS | + TOKEN_ADJUST_DEFAULT | + TOKEN_ADJUST_SESSIONID + } + + internal static class NativeMethods + { + private const String ADVAPI32 = "advapi32.dll"; + + // TODO: Should be moved into enums? + internal const int READ_CONTROL = 0x00020000; + internal const int SYNCHRONIZE = 0x00100000; + internal const int STANDARD_RIGHTS_READ = READ_CONTROL; + internal const int STANDARD_RIGHTS_WRITE = READ_CONTROL; + + internal const int KEY_QUERY_VALUE = 0x0001; + internal const int KEY_SET_VALUE = 0x0002; + internal const int KEY_CREATE_SUB_KEY = 0x0004; + internal const int KEY_ENUMERATE_SUB_KEYS = 0x0008; + internal const int KEY_NOTIFY = 0x0010; + + internal const int KEY_READ = ((STANDARD_RIGHTS_READ | + KEY_QUERY_VALUE | + KEY_ENUMERATE_SUB_KEYS | + KEY_NOTIFY) + & + (~SYNCHRONIZE)); + + internal const int KEY_WRITE = ((STANDARD_RIGHTS_WRITE | + KEY_SET_VALUE | + KEY_CREATE_SUB_KEY) + & + (~SYNCHRONIZE)); + + internal const int KEY_WOW64_64KEY = 0x0100; + internal const int KEY_WOW64_32KEY = 0x0200; + + internal const int ERROR_MORE_DATA = 0xEA; + internal const int ERROR_ACCESS_DENIED = 0x5; + + internal const int REG_OPTION_NON_VOLATILE = 0x0000; // (default) keys are persisted beyond reboot/unload + internal const int REG_OPTION_VOLATILE = 0x0001; // All keys created by the function are volatile + internal const int REG_OPTION_CREATE_LINK = 0x0002; // They key is a symbolic link + internal const int REG_OPTION_BACKUP_RESTORE = 0x0004; // Use SE_BACKUP_NAME process special privileges + internal const int REG_NONE = 0; // No value type + internal const int REG_SZ = 1; // Unicode nul terminated string + internal const int REG_EXPAND_SZ = 2; // Unicode nul terminated string + internal const int REG_BINARY = 3; // Free form binary + internal const int REG_DWORD = 4; // 32-bit number + internal const int REG_DWORD_LITTLE_ENDIAN = 4; // 32-bit number (same as REG_DWORD) + internal const int REG_DWORD_BIG_ENDIAN = 5; // 32-bit number + internal const int REG_LINK = 6; // Symbolic Link (unicode) + internal const int REG_MULTI_SZ = 7; // Multiple Unicode strings + internal const int REG_RESOURCE_LIST = 8; // Resource list in the resource map + internal const int REG_FULL_RESOURCE_DESCRIPTOR = 9; // Resource list in the hardware description + internal const int REG_RESOURCE_REQUIREMENTS_LIST = 10; + internal const int REG_QWORD = 11; // 64-bit number + + [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool AdjustTokenPrivileges( + SafeHandleZeroIsInvalid TokenHandle, + [MarshalAs(UnmanagedType.Bool)] + bool DisableAllPrivileges, + ref TOKEN_PRIVILEGES NewState, + int len, + IntPtr prev, + IntPtr relen); + + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); + + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetTokenInformation( + SafeHandleZeroIsInvalid TokenHandle, + TOKEN_INFORMATION_CLASS TokenInformationClass, + HGlobalBuffer TokenInformation, + int TokenInformationLength, + out int ReturnLength); + + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool OpenProcessToken( + SafeHandleZeroIsInvalid ProcessHandle, + AccessTokenRights DesiredAccess, + out SafeHandleZeroIsInvalid TokenHandle); + + [DllImport("ADVAPI32.DLL"), + SuppressUnmanagedCodeSecurity, + ResourceExposure(ResourceScope.None), + ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + internal static extern int RegCloseKey(IntPtr hKey); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegOpenKeyEx(SafeRegistryHandle hKey, String lpSubKey, + int ulOptions, int samDesired, out SafeRegistryHandle hkResult); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, [Out] byte[] lpData, + ref int lpcbData); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, ref int lpData, + ref int lpcbData); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, ref long lpData, + ref int lpcbData); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, [Out] char[] lpData, + ref int lpcbData); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, StringBuilder lpData, + ref int lpcbData); + + public static void EnableShutdownPrivilege() + { + const int SE_PRIVILEGE_ENABLED = 0x00000002; + const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; + + bool retVal; + + using (SafeHandleZeroIsInvalid hproc = Kernel32.NativeMethods.GetCurrentProcess()) + { + TOKEN_PRIVILEGES tp; + SafeHandleZeroIsInvalid htok; + retVal = OpenProcessToken(hproc, AccessTokenRights.TOKEN_ADJUST_PRIVILEGES | AccessTokenRights.TOKEN_QUERY, out htok); + if (!retVal) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + + using (htok) + { + tp.PrivilegeCount = 1; + tp.Luid = 0; + tp.Attributes = SE_PRIVILEGE_ENABLED; + retVal = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid); + if (!retVal) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + + retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); + if (!retVal) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + } + } + } + } + + [SecurityCritical] + internal sealed class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid + { + [SecurityCritical] + internal SafeRegistryHandle() + : base(true) + { + } + + [SecurityCritical] + public SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) + : base(ownsHandle) + { + SetHandle(preexistingHandle); + } + + [SecurityCritical] + override protected bool ReleaseHandle() + { + return (Microsoft.Web.Management.PInvoke.AdvApi32.NativeMethods.RegCloseKey(handle) == 0); + } + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs new file mode 100644 index 0000000000..6d6a3209a7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; + +// Any reference to Common.cs should also include Kernel32.cs because +// SafeHandleZeroIsInvalid (from Common.cs) uses CloseHandle (from Kernel32.cs) +namespace Microsoft.Web.Management.PInvoke +{ + internal enum Win32ErrorCode + { + ERROR_FILE_NOT_FOUND = 2, + ERROR_PATH_NOT_FOUND = 3, + ERROR_ACCESS_DENIED = 5, + ERROR_INVALID_HANDLE = 6, + ERROR_INVALID_DRIVE = 15, + ERROR_NO_MORE_FILES = 18, + ERROR_NOT_READY = 21, + ERROR_SHARING_VIOLATION = 32, + ERROR_FILE_EXISTS = 80, + ERROR_INVALID_PARAMETER = 87, // 0x57 + ERROR_INVALID_NAME = 123, // 0x7b + ERROR_BAD_PATHNAME = 161, + ERROR_ALREADY_EXISTS = 183, + ERROR_FILENAME_EXCED_RANGE = 206, + ERROR_OPERATION_ABORTED = 995, + ELEMENT_NOT_FOUND = 0x490 + } + + internal static class Extension + { + public static int AsHRESULT(Win32ErrorCode errorCode) + { + return (int)((uint)errorCode | 0x80070000); + } + } + + internal class SafeHandleZeroIsInvalid : SafeHandle + { + public SafeHandleZeroIsInvalid() + : base(IntPtr.Zero, true) + { + } + + public SafeHandleZeroIsInvalid(IntPtr newHandle) + : base(IntPtr.Zero, true) + { + this.SetHandle(newHandle); + } + + public override bool IsInvalid + { + get + { + return this.handle == IntPtr.Zero; + } + } + + protected override bool ReleaseHandle() + { + return Kernel32.NativeMethods.CloseHandle(this.handle); + } + } + + internal class HGlobalBuffer : SafeHandle + { + private int _size; + + public HGlobalBuffer(int size) + : base(IntPtr.Zero, true) + { + _size = size; + this.handle = Marshal.AllocHGlobal(size); + } + + protected override bool ReleaseHandle() + { + if (!this.IsInvalid) + { + Marshal.FreeHGlobal(this.handle); + this.handle = IntPtr.Zero; + } + + return true; + } + + public override bool IsInvalid + { + get + { + return this.handle == IntPtr.Zero; + } + } + + public T GetCopyAs() + { + return (T)Marshal.PtrToStructure(this.handle, typeof(T)); + } + + public int Size + { + get + { + return _size; + } + } + + public static readonly HGlobalBuffer NULL = new HGlobalBuffer(0); + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs new file mode 100644 index 0000000000..dd3391ff94 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs @@ -0,0 +1,179 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; + +namespace Microsoft.Web.Utility.PInvoke.Fusion +{ + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("CD193BC0-B4BC-11d2-9833-00C04FC31D2E")] + internal interface IAssemblyName + { + [PreserveSig()] + int SetProperty( + int PropertyId, + IntPtr pvProperty, + int cbProperty); + + [PreserveSig()] + int GetProperty( + int PropertyId, + IntPtr pvProperty, + ref int pcbProperty); + + [PreserveSig()] + int Finalize(); + + [PreserveSig()] + int GetDisplayName( + StringBuilder pDisplayName, + ref int pccDisplayName, + int displayFlags); + + [PreserveSig()] + int Reserved(ref Guid guid, + Object obj1, + Object obj2, + String string1, + Int64 llFlags, + IntPtr pvReserved, + int cbReserved, + out IntPtr ppv); + + [PreserveSig()] + int GetName( + ref int pccBuffer, + StringBuilder pwzName); + + [PreserveSig()] + int GetVersion( + out int versionHi, + out int versionLow); + [PreserveSig()] + int IsEqual( + IAssemblyName pAsmName, + int cmpFlags); + + [PreserveSig()] + int Clone(out IAssemblyName pAsmName); + }// IAssemblyName + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")] + internal interface IAssemblyCache + { + [PreserveSig()] + int UninstallAssembly( + int flags, + [MarshalAs(UnmanagedType.LPWStr)] + string assemblyName, + IntPtr refData, + out int disposition); + + [PreserveSig()] + int QueryAssemblyInfo( + int flags, + [MarshalAs(UnmanagedType.LPWStr)] + string assemblyName, + ref AssemblyInfo assemblyInfo); + [PreserveSig()] + int Reserved( + int flags, + IntPtr pvReserved, + out object ppAsmItem, + [MarshalAs(UnmanagedType.LPWStr)] + string assemblyName); + [PreserveSig()] + int Reserved(out object ppAsmScavenger); + + [PreserveSig()] + int InstallAssembly( + int flags, + [MarshalAs(UnmanagedType.LPWStr)] + string assemblyFilePath, + IntPtr refData); + }// IAssemblyCache + + [StructLayout(LayoutKind.Sequential)] + internal struct AssemblyInfo + { + public int cbAssemblyInfo; // size of this structure for future expansion + public int assemblyFlags; + public long assemblySizeInKB; + [MarshalAs(UnmanagedType.LPWStr)] + public string currentAssemblyPath; + public int cchBuf; // size of path buf. + } + + [Flags] + internal enum AssemblyCacheFlags + { + GAC = 2, + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("21b8916c-f28e-11d2-a473-00c04f8ef448")] + internal interface IAssemblyEnum + { + [PreserveSig()] + int GetNextAssembly( + IntPtr pvReserved, + out IAssemblyName ppName, + int flags); + + [PreserveSig()] + int Reset(); + [PreserveSig()] + int Clone(out IAssemblyEnum ppEnum); + } + + [Flags] + internal enum AssemblyNameDisplayFlags + { + VERSION = 0x01, + CULTURE = 0x02, + PUBLIC_KEY_TOKEN = 0x04, + PROCESSORARCHITECTURE = 0x20, + RETARGETABLE = 0x80, + + // This enum might change in the future to include + // more attributes. + ALL = + VERSION + | CULTURE + | PUBLIC_KEY_TOKEN + | PROCESSORARCHITECTURE + | RETARGETABLE + } + + internal enum CreateAssemblyNameObjectFlags + { + CANOF_DEFAULT = 0, + CANOF_PARSE_DISPLAY_NAME = 1, + } + + internal static class NativeMethods + { + [DllImport("fusion.dll")] + public static extern int CreateAssemblyCache( + out IAssemblyCache ppAsmCache, + int reserved); + + [DllImport("fusion.dll")] + public static extern int CreateAssemblyEnum( + out IAssemblyEnum ppEnum, + IntPtr pUnkReserved, + IAssemblyName pName, + AssemblyCacheFlags flags, + IntPtr pvReserved); + + [DllImport("fusion.dll")] + public static extern int CreateAssemblyNameObject( + out IAssemblyName ppAssemblyNameObj, + [MarshalAs(UnmanagedType.LPWStr)] + String szAssemblyName, + CreateAssemblyNameObjectFlags flags, + IntPtr pvReserved); + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs new file mode 100644 index 0000000000..91265956b5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +// Any reference to Common.cs should also include Kernel32.cs because +// SafeHandleZeroIsInvalid (from Common.cs) uses CloseHandle (from Kernel32.cs) +namespace Microsoft.Web.Management.PInvoke.Kernel32 +{ + internal enum OSProductType : byte + { + VER_NT_WORKSTATION = 0x0000001, + VER_NT_SERVER = 0x0000003, + VER_NT_DOMAIN_CONTROLLER = 0x0000002, + } + + [StructLayout(LayoutKind.Sequential)] + internal struct OSVERSIONINFOEX + { + public int dwOSVersionInfoSize; + public int dwMajorVersion; + public int dwMinorVersion; + public int dwBuildNumber; + public int dwPlatformId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string szCSDVersion; + public short wServicePackMajor; + public short wServicePackMinor; + public short wSuiteMask; + public OSProductType wProductType; + public byte wReserved; + + public bool IsServer + { + get + { + return + wProductType == OSProductType.VER_NT_SERVER || + wProductType == OSProductType.VER_NT_DOMAIN_CONTROLLER; + } + } + + public bool IsClient + { + get + { + return + wProductType == OSProductType.VER_NT_WORKSTATION; + } + } + } + + internal static class NativeMethods + { + public static OSVERSIONINFOEX GetVersionEx() + { + OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX(); + osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX)); + if (!GetVersionEx(ref osVersionInfo)) + { + throw new Win32Exception(); + } + + return osVersionInfo; + } + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool CloseHandle(IntPtr hHandle); + + [DllImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + [SuppressMessage("Microsoft.Usage", "CA2205:UseManagedEquivalentsOfWin32Api", Justification = "GetVersionEx returns more information")] + private static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo); + + [DllImport("kernel32.dll", ExactSpelling = true)] + internal static extern SafeHandleZeroIsInvalid GetCurrentProcess(); + + // WARNING: Vista+ ONLY + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool GetProductInfo(uint dwOSMajorVersion, uint dwOSMinorVersion, uint dwSpMajorVersion, uint spMinorVersion, out uint pdwReturnedProductType); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool WritePrivateProfileString(string applicationName, string keyName, string stringValue, string fileName); + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs new file mode 100644 index 0000000000..e6e1ff51bd --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs @@ -0,0 +1,768 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; + +namespace Microsoft.Web.Management.PInvoke.MLang +{ + internal enum HRESULT : uint + { + S_OK = 0x0, + S_FALSE = 0x1, + E_FAIL = 0x80004005, + } + + internal static class NativeMethods + { + [StructLayout(LayoutKind.Explicit, Pack = 4)] + public struct __MIDL_IWinTypes_0009 + { + // Fields + [FieldOffset(0)] + public int hInproc; + [FieldOffset(0)] + public int hRemote; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct _RemotableHandle + { + public int fContext; + public __MIDL_IWinTypes_0009 u; + } + + [ComImport, CoClass(typeof(CMLangConvertCharsetClass)), Guid("D66D6F98-CDAA-11D0-B822-00C04FC9B31F")] + public interface CMLangConvertCharset : IMLangConvertCharset + { + } + + [ComImport, TypeLibType((short)2), Guid("D66D6F99-CDAA-11D0-B822-00C04FC9B31F"), ClassInterface((short)0)] + public class CMLangConvertCharsetClass : IMLangConvertCharset, CMLangConvertCharset + { + // Methods + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DoConversion([In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DoConversionFromUnicode([In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DoConversionToUnicode([In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetDestinationCodePage(out uint puiDstCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetProperty(out uint pdwProperty); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetSourceCodePage(out uint puiSrcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void Initialize([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty); + } + + [ComImport, Guid("C04D65CE-B70D-11D0-B188-00AA0038C969"), CoClass(typeof(CMLangStringClass))] + public interface CMLangString : IMLangString + { + } + + [ComImport, TypeLibType((short)2), Guid("C04D65CF-B70D-11D0-B188-00AA0038C969"), ClassInterface((short)0)] + public class CMLangStringClass : IMLangString, CMLangString, IMLangStringWStr, IMLangStringAStr + { + // Methods + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetAStr([In] int lSrcPos, [In] int lSrcLen, [In] uint uCodePageIn, out uint puCodePageOut, [Out, MarshalAs(UnmanagedType.LPStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern int GetLength(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetStrBufA([In] int lSrcPos, [In] int lSrcMaxLen, out uint puDestCodePage, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufA ppDestBuf, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetStrBufW([In] int lSrcPos, [In] int lSrcMaxLen, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufW ppDestBuf, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetWStr([In] int lSrcPos, [In] int lSrcLen, [Out, MarshalAs(UnmanagedType.LPWStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern int IMLangStringAStr_GetLength(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_Sync([In] int fNoAccess); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern int IMLangStringWStr_GetLength(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringWStr_GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringWStr_SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringWStr_Sync([In] int fNoAccess); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void LockAStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] uint uCodePageIn, [In] int cchRequest, out uint puCodePageOut, [MarshalAs(UnmanagedType.LPStr)] out string ppszDest, out int pcchDest, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void LockWStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] int cchRequest, [MarshalAs(UnmanagedType.LPWStr)] out string ppszDest, out int pcchDest, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetAStr([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetStrBufA([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufA pSrcBuf, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetStrBufW([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufW pSrcBuf, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetWStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void Sync([In] int fNoAccess); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void UnlockAStr([In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void UnlockWStr([In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + } + + [ComImport, Guid("275C23E1-3747-11D0-9FEA-00AA003F8646"), CoClass(typeof(CMultiLanguageClass))] + public interface CMultiLanguage : IMultiLanguage + { + } + + [ComImport, TypeLibType(TypeLibTypeFlags.FCanCreate), ClassInterface(ClassInterfaceType.None), Guid("275C23E2-3747-11D0-9FEA-00AA003F8646")] + public class CMultiLanguageClass : IMultiLanguage, CMultiLanguage, IMLangCodePages, IMLangFontLink, IMLangLineBreakConsole, IMultiLanguage2, IMLangFontLink2, IMultiLanguage3 + { + // Methods + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void BreakLineA([In] uint locale, [In] uint uCodePage, [In] ref sbyte pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void BreakLineML([In, MarshalAs(UnmanagedType.Interface)] CMLangString pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen, [In] int cMinColumns, [In] int cMaxColumns, out int plLineLen, out int plSkipLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void BreakLineW([In] uint locale, [In] ref ushort pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void CodePageToScriptID([In] uint uiCodePage, out byte pSid); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringFromUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringInIStream([In, Out] ref uint pdwMode, [In] uint dwFlag, [In] ref ushort lpFallBack, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmOut); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringToUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DetectCodepageInIStream([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [PreserveSig] + public virtual extern HRESULT DetectInputCodepage([In] MLDETECTCP dwFlag, [In] uint dwPrefWinCodePage, [In] ref byte pSrcStr, [In, Out] ref int pcSrcSize, ref DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DetectOutboundCodePage([In] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] uint cchWideChar, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DetectOutboundCodePageInIStream([In] uint dwFlags, [In, MarshalAs(UnmanagedType.Interface)] IStream pStrIn, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [return: MarshalAs(UnmanagedType.Interface)] + public virtual extern IEnumCodePage EnumCodePages([In] NativeMethods.MIMECONTF grfFlags); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void EnumCodePages([In] uint grfFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnumCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void EnumRfc1766([MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void EnumRfc1766([In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void EnumScripts([In] uint dwFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnumScript); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCharCodePages([In] ushort chSrc, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCodePageDescription([In] uint uiCodePage, [In] uint lcid, [Out, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] int cchWideChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCodePageInfo([In] uint uiCodePage, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCodePageInfo([In] uint uiCodePage, [In] ushort LangId, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetFontUnicodeRanges([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, Out] ref uint puiRanges, out UNICODERANGE pUranges); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetNumberOfScripts(out uint pnScripts); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetRfc1766Info([In] uint locale, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetRfc1766Info([In] uint locale, [In] ushort LangId, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetScriptFontInfo([In] byte sid, [In] uint dwFlags, [In, Out] ref uint puiFonts, out SCRIPFONTINFO pScriptFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink_CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink_CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink_GetCharCodePages([In] ushort chSrc, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink_GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_GetCharCodePages([In] ushort chSrc, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_ResetFontMapping(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringFromUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringInIStream([In, Out] ref uint pdwMode, [In] uint dwFlag, [In] ref ushort lpFallBack, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmOut); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringToUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_DetectCodepageInIStream([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_DetectInputCodepage([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In] ref sbyte pSrcStr, [In, Out] ref int pcSrcSize, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_EnumCodePages([In] NativeMethods.MIMECONTF grfFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnumCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_EnumRfc1766([In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_EnumScripts([In] uint dwFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnumScript); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetCodePageDescription([In] uint uiCodePage, [In] uint lcid, [Out, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] int cchWideChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetCodePageInfo([In] uint uiCodePage, [In] ushort LangId, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetNumberOfScripts(out uint pnScripts); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetRfc1766Info([In] uint locale, [In] ushort LangId, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_IsCodePageInstallable([In] uint uiCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_SetMimeDBSource([In] MIMECONTF dwSource); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ValidateCodePage([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ValidateCodePageEx([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd, [In] uint dwfIODControl); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IsCodePageInstallable([In] uint uiCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In] ushort chSrc, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr pFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hSrcFont, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr phDestFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ResetFontMapping(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetMimeDBSource([In] MIMECONTF dwSource); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ValidateCodePage([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ValidateCodePageEx([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd, [In] uint dwfIODControl); + } + + [ComImport, Guid("275C23E3-3747-11D0-9FEA-00AA003F8646"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumCodePage + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnum); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [PreserveSig] + HRESULT Next([In] uint celt, out MIMECPINFO rgelt, out uint pceltFetched); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Reset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Skip([In] uint celt); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("3DC39D1D-C030-11D0-B81B-00C04FC9B31F")] + public interface IEnumRfc1766 + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnum); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Next([In] uint celt, out RFC1766INFO rgelt, out uint pceltFetched); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Reset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Skip([In] uint celt); + } + + [ComImport, Guid("AE5F1430-388B-11D2-8380-00C04F8F5DA1"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumScript + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnum); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Next([In] uint celt, out SCRIPTINFO rgelt, out uint pceltFetched); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Reset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Skip([In] uint celt); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("359F3443-BD4A-11D0-B188-00AA0038C969")] + public interface IMLangCodePages + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCharCodePages([In] ushort chSrc, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D66D6F98-CDAA-11D0-B822-00C04FC9B31F")] + public interface IMLangConvertCharset + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Initialize([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetSourceCodePage(out uint puiSrcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetDestinationCodePage(out uint puiDstCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetProperty(out uint pdwProperty); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DoConversion([In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DoConversionToUnicode([In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DoConversionFromUnicode([In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + } + + [ComImport, Guid("359F3441-BD4A-11D0-B188-00AA0038C969"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComConversionLoss] + public interface IMLangFontLink : IMLangCodePages + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hSrcFont, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr phDestFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ResetFontMapping(); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("DCCFC162-2B38-11D2-B7EC-00C04F8F5D9A"), ComConversionLoss] + public interface IMLangFontLink2 : IMLangCodePages + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ResetFontMapping(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In] ushort chSrc, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr pFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFontUnicodeRanges([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, Out] ref uint puiRanges, out UNICODERANGE pUranges); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetScriptFontInfo([In] byte sid, [In] uint dwFlags, [In, Out] ref uint puiFonts, out SCRIPFONTINFO pScriptFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CodePageToScriptID([In] uint uiCodePage, out byte pSid); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("F5BE2EE1-BFD7-11D0-B188-00AA0038C969")] + public interface IMLangLineBreakConsole + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void BreakLineML([In, MarshalAs(UnmanagedType.Interface)] CMLangString pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen, [In] int cMinColumns, [In] int cMaxColumns, out int plLineLen, out int plSkipLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void BreakLineW([In] uint locale, [In] ref ushort pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void BreakLineA([In] uint locale, [In] uint uCodePage, [In] ref sbyte pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip); + } + + [ComImport, Guid("C04D65CE-B70D-11D0-B188-00AA0038C969"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMLangString + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Sync([In] int fNoAccess); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + int GetLength(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("C04D65D2-B70D-11D0-B188-00AA0038C969")] + public interface IMLangStringAStr : IMLangString + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetAStr([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetStrBufA([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufA pSrcBuf, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetAStr([In] int lSrcPos, [In] int lSrcLen, [In] uint uCodePageIn, out uint puCodePageOut, [Out, MarshalAs(UnmanagedType.LPStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStrBufA([In] int lSrcPos, [In] int lSrcMaxLen, out uint puDestCodePage, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufA ppDestBuf, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void LockAStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] uint uCodePageIn, [In] int cchRequest, out uint puCodePageOut, [MarshalAs(UnmanagedType.LPStr)] out string ppszDest, out int pcchDest, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void UnlockAStr([In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComConversionLoss, Guid("D24ACD23-BA72-11D0-B188-00AA0038C969")] + public interface IMLangStringBufA + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStatus(out int plFlags, out int pcchBuf); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void LockBuf([In] int cchOffset, [In] int cchMaxLock, [Out] IntPtr ppszBuf, out int pcchBuf); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void UnlockBuf([In] ref sbyte pszBuf, [In] int cchOffset, [In] int cchWrite); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Insert([In] int cchOffset, [In] int cchMaxInsert, out int pcchActual); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Delete([In] int cchOffset, [In] int cchDelete); + } + + [ComImport, ComConversionLoss, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D24ACD21-BA72-11D0-B188-00AA0038C969")] + public interface IMLangStringBufW + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStatus(out int plFlags, out int pcchBuf); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void LockBuf([In] int cchOffset, [In] int cchMaxLock, [Out] IntPtr ppszBuf, out int pcchBuf); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void UnlockBuf([In] ref ushort pszBuf, [In] int cchOffset, [In] int cchWrite); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Insert([In] int cchOffset, [In] int cchMaxInsert, out int pcchActual); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Delete([In] int cchOffset, [In] int cchDelete); + } + + [ComImport, Guid("C04D65D0-B70D-11D0-B188-00AA0038C969"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMLangStringWStr : IMLangString + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetWStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetStrBufW([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufW pSrcBuf, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetWStr([In] int lSrcPos, [In] int lSrcLen, [Out, MarshalAs(UnmanagedType.LPWStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStrBufW([In] int lSrcPos, [In] int lSrcMaxLen, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufW ppDestBuf, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void LockWStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] int cchRequest, [MarshalAs(UnmanagedType.LPWStr)] out string ppszDest, out int pcchDest, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void UnlockWStr([In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen); + } + + [ComImport, Guid("275C23E1-3747-11D0-9FEA-00AA003F8646"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMultiLanguage + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCodePageInfo([In] uint uiCodePage, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [return: MarshalAs(UnmanagedType.Interface)] + IEnumCodePage EnumCodePages([In] NativeMethods.MIMECONTF grfFlags); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void EnumRfc1766([MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetRfc1766Info([In] uint locale, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + } + + [ComImport, Guid("DCCFC164-2B38-11D2-B7EC-00C04F8F5D9A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMultiLanguage2 + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCodePageInfo([In] uint uiCodePage, [In] ushort LangId, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void EnumCodePages([In] uint grfFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnumCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void EnumRfc1766([In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetRfc1766Info([In] uint locale, [In] ushort LangId, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringInIStream([In, Out] ref uint pdwMode, [In] uint dwFlag, [In] ref ushort lpFallBack, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmOut); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringToUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringFromUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DetectCodepageInIStream([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [PreserveSig] + HRESULT DetectInputCodepage([In] MLDETECTCP dwFlag, [In] uint dwPrefWinCodePage, [In] ref byte pSrcStr, [In, Out] ref int pcSrcSize, [In, Out] ref DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ValidateCodePage([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCodePageDescription([In] uint uiCodePage, [In] uint lcid, [Out, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] int cchWideChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void IsCodePageInstallable([In] uint uiCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetMimeDBSource([In] MIMECONTF dwSource); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetNumberOfScripts(out uint pnScripts); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void EnumScripts([In] uint dwFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnumScript); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ValidateCodePageEx([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd, [In] uint dwfIODControl); + } + + [ComImport, Guid("4E5868AB-B157-4623-9ACC-6A1D9CAEBE04"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMultiLanguage3 : IMultiLanguage2 + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DetectOutboundCodePage([In] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] uint cchWideChar, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DetectOutboundCodePageInIStream([In] uint dwFlags, [In, MarshalAs(UnmanagedType.Interface)] IStream pStrIn, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar); + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct DetectEncodingInfo + { + public uint nLangID; + public uint nCodePage; + public int nDocPercent; + public int nConfidence; + } + + public enum MIMECONTF + { + MIMECONTF_BROWSER = 2, + MIMECONTF_EXPORT = 0x400, + MIMECONTF_IMPORT = 8, + MIMECONTF_MAILNEWS = 1, + MIMECONTF_MIME_IE4 = 0x10000000, + MIMECONTF_MIME_LATEST = 0x20000000, + MIMECONTF_MIME_REGISTRY = 0x40000000, + MIMECONTF_MINIMAL = 4, + MIMECONTF_PRIVCONVERTER = 0x10000, + MIMECONTF_SAVABLE_BROWSER = 0x200, + MIMECONTF_SAVABLE_MAILNEWS = 0x100, + MIMECONTF_VALID = 0x20000, + MIMECONTF_VALID_NLS = 0x40000 + } + + [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] + public struct MIMECPINFO + { + public uint dwFlags; + public uint uiCodePage; + public uint uiFamilyCodePage; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x40)] + public string wszDescription; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string wszWebCharset; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string wszHeaderCharset; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string wszBodyCharset; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] + public string wszFixedWidthFont; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] + public string wszProportionalFont; + public byte bGDICharset; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct MIMECSETINFO + { + public uint uiCodePage; + public uint uiInternetEncoding; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] + public ushort[] wszCharset; + } + + public enum MLSTR_FLAGS + { + MLSTR_READ = 1, + MLSTR_WRITE = 2 + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct RFC1766INFO + { + public uint lcid; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public ushort[] wszRfc1766; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] + public ushort[] wszLocaleName; + } + + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct SCRIPFONTINFO + { + public long scripts; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] + public ushort[] wszFont; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct SCRIPTINFO + { + public byte ScriptId; + public uint uiCodePage; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x30)] + public ushort[] wszDescription; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] + public ushort[] wszFixedWidthFont; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] + public ushort[] wszProportionalFont; + } + + public enum MLDETECTCP + { + MLDETECTCP_NONE = 0, + MLDETECTCP_7BIT = 1, + MLDETECTCP_8BIT = 2, + MLDETECTCP_DBCS = 4, + MLDETECTCP_HTML = 8, + MLDETECTCP_NUMBER = 16 + } + + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct STATSTG + { + [MarshalAs(UnmanagedType.LPWStr)] + public string pwcsName; + public uint type; + public ulong cbSize; + public System.Runtime.InteropServices.ComTypes.FILETIME mtime; + public System.Runtime.InteropServices.ComTypes.FILETIME ctime; + public System.Runtime.InteropServices.ComTypes.FILETIME atime; + public uint grfMode; + public uint grfLocksSupported; + public Guid clsid; + public uint grfStateBits; + public uint reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 2)] + public struct UNICODERANGE + { + public ushort wcFrom; + public ushort wcTo; + } + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs new file mode 100644 index 0000000000..b158632572 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.Web.Management.PInvoke.User32 +{ + internal enum WindowMessage + { + PBS_SMOOTH = 0x1, + PBS_MARQUEE = 0x8, + WM_SETREDRAW = 0xB, + PBM_SETMARQUEE = 0x400 + 10, + } + + [Flags] + internal enum ExitWindows : uint + { + // + // ONE of the following five: + // + LogOff = 0x00, + ShutDown = 0x01, + Reboot = 0x02, + PowerOff = 0x08, + RestartApps = 0x40, + + // + // plus AT MOST ONE of the following two: + // + Force = 0x04, + ForceIfHung = 0x10, + } + + [Flags] + internal enum ShutdownReason : uint + { + MajorApplication = 0x00040000, + MajorHardware = 0x00010000, + MajorLegacyApi = 0x00070000, + MajorOperatingSystem = 0x00020000, + MajorOther = 0x00000000, + MajorPower = 0x00060000, + MajorSoftware = 0x00030000, + MajorSystem = 0x00050000, + + MinorBlueScreen = 0x0000000F, + MinorCordUnplugged = 0x0000000b, + MinorDisk = 0x00000007, + MinorEnvironment = 0x0000000c, + MinorHardwareDriver = 0x0000000d, + MinorHotfix = 0x00000011, + MinorHung = 0x00000005, + MinorInstallation = 0x00000002, + MinorMaintenance = 0x00000001, + MinorMMC = 0x00000019, + MinorNetworkConnectivity = 0x00000014, + MinorNetworkCard = 0x00000009, + MinorOther = 0x00000000, + MinorOtherDriver = 0x0000000e, + MinorPowerSupply = 0x0000000a, + MinorProcessor = 0x00000008, + MinorReconfig = 0x00000004, + MinorSecurity = 0x00000013, + MinorSecurityFix = 0x00000012, + MinorSecurityFixUninstall = 0x00000018, + MinorServicePack = 0x00000010, + MinorServicePackUninstall = 0x00000016, + MinorTermSrv = 0x00000020, + MinorUnstable = 0x00000006, + MinorUpgrade = 0x00000003, + MinorWMI = 0x00000015, + + FlagUserDefined = 0x40000000, + FlagPlanned = 0x80000000 + } + + internal static class NativeMethods + { + [DllImport("User32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr SendMessage(IntPtr hWnd, WindowMessage msg, int wParam, int lParam); + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason); + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs new file mode 100644 index 0000000000..520c923505 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Diagnostics; + +namespace Microsoft.Web.Management.PInvoke.UxTheme +{ + internal static class NativeMethods + { + [DllImport("UxTheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] + public extern static void SetWindowTheme(IntPtr hWnd, string textSubAppName, string textSubIdList); + + [DllImport("uxtheme.dll", CharSet = CharSet.Unicode, PreserveSig = true)] + private static extern int GetCurrentThemeName(StringBuilder pszThemeFileName, int dwMaxNameChars, StringBuilder pszColorBuff, int dwMaxColorChars, StringBuilder pszSizeBuff, int cchMaxSizeChars); + + public static bool TryGetCurrentThemeName(out string themeName, out string color, out string size) + { + StringBuilder nameBuilder = new StringBuilder(512); + StringBuilder colorBuilder = new StringBuilder(512); + StringBuilder sizeBuilder = new StringBuilder(512); + int hr = GetCurrentThemeName(nameBuilder, nameBuilder.Capacity, colorBuilder, colorBuilder.Capacity, sizeBuilder, sizeBuilder.Capacity); + if (hr == 0) + { + themeName = nameBuilder.ToString(); + color = colorBuilder.ToString(); + size = sizeBuilder.ToString(); + return true; + } + else + { + themeName = null; + color = null; + size = null; + if (hr != Extension.AsHRESULT(Win32ErrorCode.ELEMENT_NOT_FOUND)) + { + Debug.Fail("GetCurrentThemeName returned: " + hr.ToString()); + } + + return false; + } + } + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets new file mode 100644 index 0000000000..0222289f2c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs new file mode 100644 index 0000000000..fccf038061 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs @@ -0,0 +1,456 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Reflection; +using System.Resources; + +namespace Microsoft.Web.Utility +{ +#if PSEUDOLOCALIZER_ENABLED || DEBUG + + /// + /// Class that pseudo-localizes resources from a RESX file by intercepting calls to the managed wrapper class. + /// + internal static class PseudoLocalizer + { + private static bool _shouldPseudoLocalize; + private static double _plocPaddingLengthRatio; + + static PseudoLocalizer() + { + _shouldPseudoLocalize = false; + int plocLengthPaddingPercentage = 50; +#if DEBUG + string plocValue = Environment.GetEnvironmentVariable("PSEUDOLOCALIZE"); + if (!string.IsNullOrEmpty(plocValue)) + { + _shouldPseudoLocalize = true; + int.TryParse(plocValue, out plocLengthPaddingPercentage); + if (plocLengthPaddingPercentage < 10) + { + plocLengthPaddingPercentage = 50; + } + } +#endif // DEBUG + + _plocPaddingLengthRatio = plocLengthPaddingPercentage * 0.01; + if (_plocPaddingLengthRatio < 0.1) + { + DebugTrace("ploc should be at least 10% padded"); + } + +#if PSEUDOLOCALIZER_ENABLED + _shouldPseudoLocalize = true; +#endif // PSEUDOLOCALIZER_ENABLED + } + + public static bool ShouldPseudoLocalize + { + get + { + return _shouldPseudoLocalize; + } + } + + // Need to use this method instead of tracing/debugging directly otherwise + // the application will not be able to disable asserts from the exe.config file. + // this is because this code is run very early on in the app before the + // default trace listener has had a chance to initialize its settings + // correctly + private static void DebugTrace(string format, params object[] args) + { + ////only uncomment these lines when actually debugging something + ////otherwise the application wont be able to toggle the assert ui + ////if (args == null || args.Length == 0) + ////{ + //// Debug.WriteLine(format); + ////} + ////else + ////{ + //// Debug.WriteLine(format, args); + ////} + } + + /// + /// Enables pseudo-localization on any type that is of the form {AssemblyName}.Resources + /// + /// + /// true if succeeded, false if failed. + public static bool TryEnableAssembly(Assembly assembly) + { + bool retVal = false; + if (assembly != null) + { + AssemblyName assemblyName = assembly.GetName(); + string resourceTypeName = assemblyName.Name + ".Resources"; + try + { + Type resourceType = assembly.GetType(resourceTypeName, false); + if (resourceType != null) + { + Enable(resourceType); + retVal = true; + } + else + { + DebugTrace("PLOC: no type {0} found in the assembly {1}", + resourceTypeName, + assembly.FullName); + } + } + catch (Exception ex) + { + DebugTrace(ex.ToString()); + } + } + else + { + DebugTrace("assembly should not be null"); + } + + return retVal; + } + + /// + /// Enables pseudo-localization for the specified RESX managed wrapper class. + /// + /// Type of the RESX managed wrapper class. + [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ResourceManager", Justification = "Name of property.")] + [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "resourceMan", Justification = "Name of field.")] + public static void Enable(Type resourcesType) + { + if (null == resourcesType) + { + throw new ArgumentNullException("resourcesType"); + } + + // Get the ResourceManager property + var resourceManagerProperty = resourcesType.GetProperty("ResourceManager", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); + if (null == resourceManagerProperty) + { + throw new NotSupportedException("RESX managed wrapper class does not contain the expected internal/public static ResourceManager property."); + } + + // Get the ResourceManager value (ensures the resourceMan field gets initialized) + var resourceManagerValue = resourceManagerProperty.GetValue(null, null) as ResourceManager; + if (null == resourceManagerValue) + { + throw new NotSupportedException("RESX managed wrapper class returned null for the ResourceManager property getter."); + } + + // Get the resourceMan field + var resourceManField = resourcesType.GetField("resourceMan", BindingFlags.Static | BindingFlags.NonPublic); + if (null == resourceManField) + { + throw new NotSupportedException("RESX managed wrapper class does not contain the expected private static resourceMan field."); + } + + // Create a substitute ResourceManager to do the pseudo-localization + var resourceManSubstitute = new PseudoLocalizerResourceManager( + _plocPaddingLengthRatio, + resourceManagerValue.BaseName, + resourcesType.Assembly); + + // Replace the resourceMan field value + resourceManField.SetValue(null, resourceManSubstitute); + } + + /// + /// Enables Pseudo-localization for all assemblies that get loaded from the current + /// host. Within the assemblie, only types that are of the form {AssemblyName}.Resources + /// will get pseudo-localization enabled. + /// + public static void EnableAutoPseudoLocalizationFromHostExecutable() + { + if (ShouldPseudoLocalize) + { + //set up pseudo-localization for ourselves + TryEnableAssembly(Assembly.GetExecutingAssembly()); + + //set up pseudo-localization for anything that gets loaded later + AppDomain.CurrentDomain.AssemblyLoad += + new AssemblyLoadEventHandler(OnCurrentDomainAssemblyLoad); + } + } + + public static string PseudoLocalizeString(string str) + { + return PseudoLocalizerResourceManager.PseudoLocalizeString( + _plocPaddingLengthRatio, + str); + } + + private static void OnCurrentDomainAssemblyLoad(object sender, + AssemblyLoadEventArgs args) + { + Assembly assembly = args.LoadedAssembly; + bool isThisMyAssembly; + if (!assembly.GlobalAssemblyCache) + { + isThisMyAssembly = true; + } + else if (assembly.FullName.StartsWith("Microsoft.Web", + StringComparison.OrdinalIgnoreCase)) + { + isThisMyAssembly = true; + } + else + { + isThisMyAssembly = false; + } + + if (isThisMyAssembly) + { + TryEnableAssembly(assembly); + } + } + + /// + /// Class that overrides default ResourceManager behavior by pseudo-localizing its content. + /// + private class PseudoLocalizerResourceManager : ResourceManager + { + /// + /// Stores a Dictionary for character translations. + /// + private static Dictionary _translations = CreateTranslationsMap(); + + private static Dictionary CreateTranslationsMap() + { + // Map standard "English" characters to similar-looking counterparts from other languages + Dictionary translations = new Dictionary + { + { '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', 'Ž' }, + }; + + return translations; + } + + private double _paddingLengthRatio; + + /// + /// Initializes a new instance of the PseudoLocalizerResourceManager class. + /// + /// The root name of the resource file without its extension but including any fully qualified namespace name. + /// The main assembly for the resources. + public PseudoLocalizerResourceManager(double paddingLengthRatio, + string baseName, + Assembly assembly) + : base(baseName, assembly) + { + _paddingLengthRatio = paddingLengthRatio; + } + + /// + /// Returns the value of the specified String resource. + /// + /// The name of the resource to get. + /// The value of the resource localized for the caller's current culture settings. + public override string GetString(string name) + { + return PseudoLocalizeString(base.GetString(name)); + } + + /// + /// Gets the value of the String resource localized for the specified culture. + /// + /// The name of the resource to get. + /// The CultureInfo object that represents the culture for which the resource is localized. + /// The value of the resource localized for the specified culture. + public override string GetString(string name, CultureInfo culture) + { + return PseudoLocalizeString(base.GetString(name, culture)); + } + + private string PseudoLocalizeString(string str) + { + return PseudoLocalizeString(_paddingLengthRatio, str); + } + + /// + /// Pseudo-localizes a string. + /// + /// Input string. + /// Pseudo-localized string. + internal static string PseudoLocalizeString(double paddingLengthRatio, string str) + { + const string minprefix = "["; + const string minsuffix = "]"; + + // Create a new string with the "translated" values of each character + var translatedChars = new char[str.Length]; + if (IsXamlString(str)) + { + DoCaseTranslation(str, translatedChars); + } + else + { + DoFunkyCharacterTranslation(str, translatedChars); + } + + string mungedString = new string(translatedChars); + + int padLengthPerSide = GetPaddingLengthPerSide( + str.Length, + paddingLengthRatio, + minprefix.Length + minsuffix.Length); + + string extraPadding = new string('=', padLengthPerSide); + string finalString = string.Concat(minprefix, extraPadding, mungedString, extraPadding, minsuffix); + + return finalString; + } + + private static int GetPaddingLengthPerSide(int originalStringLength, double paddingRatio, int minPadLength) + { + int padLengthPerSide; + double exactTotalPadding = (originalStringLength * paddingRatio); + padLengthPerSide = (int)(exactTotalPadding + 1) / 2; + if (padLengthPerSide < 1) + { + padLengthPerSide = 1; + } + + return padLengthPerSide; + } + + private static void DoCaseTranslation(string str, char[] translatedChars) + { + bool inXamlTag = false; + for (var i = 0; i < str.Length; i++) + { + var c = str[i]; + + if (inXamlTag) + { + translatedChars[i] = c; + if (c == '>') + { + inXamlTag = false; + } + } + else + { + translatedChars[i] = (i % 2) == 0 ? char.ToUpper(c) : char.ToLower(c); + if (c == '<' && str.IndexOf('>', i) > -1) + { + inXamlTag = true; + } + } + } + } + + private static void DoFunkyCharacterTranslation(string str, char[] translatedChars) + { + for (var i = 0; i < str.Length; i++) + { + var c = str[i]; + translatedChars[i] = _translations.ContainsKey(c) ? _translations[c] : c; + } + } + + private static bool IsXamlString(string str) + { + // check if this string has a '<' followed by a '>' and assume it's a xaml string if so + int lessThanIndex = str.IndexOf('<'); + if (lessThanIndex > -1) + { + if (str.IndexOf('>', lessThanIndex) > -1) + { + return true; + } + } + + return false; + } + } + } +#else + /// + /// Dummy class needed to keep the public interface be identical in debug and retail builds + /// + internal static class PseudoLocalizer + { + public static bool ShouldPseudoLocalize + { + get + { + return false; + } + } + + public static bool TryEnableAssembly(Assembly assembly) + { + return true; + } + + public static void Enable(Type resourcesType) + { + } + + public static void EnableAutoPseudoLocalizationFromHostExecutable() + { + } + + public static string PseudoLocalizeString(string str) + { + return str; + } + } +#endif +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.administration.dll b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.administration.dll new file mode 100644 index 0000000000..5c786c3d92 Binary files /dev/null and b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.administration.dll differ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.management.dll b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.management.dll new file mode 100644 index 0000000000..cbae9ccf92 Binary files /dev/null and b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.management.dll differ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs new file mode 100644 index 0000000000..f284d02d0e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Net; +using System.Text; + +namespace Microsoft.WebMatrix.Utility +{ + /// + /// This AuthenticationModule implements basic authentication but uses UTF8 Encoding to support international characters. + /// Unfortunately the System.Net implementation uses the Default encoding which breaks with them. + /// + internal class AuthenticationModule : IAuthenticationModule + { + private const string AuthenticationTypeName = "Basic"; + private static AuthenticationModule _module = null; + private static object _lock = new object(); + + public static void InstantiateIfNeeded() + { + lock (_lock) + { + if (_module == null) + { + _module = new AuthenticationModule(); + } + } + } + + private AuthenticationModule() + { + AuthenticationManager.Unregister(AuthenticationTypeName); + AuthenticationManager.Register(this); + } + + string IAuthenticationModule.AuthenticationType + { + get + { + return AuthenticationTypeName; + } + } + + bool IAuthenticationModule.CanPreAuthenticate + { + get + { + return true; + } + } + + Authorization IAuthenticationModule.Authenticate(string challenge, WebRequest request, ICredentials credentials) + { + HttpWebRequest httpWebRequest = request as HttpWebRequest; + if (httpWebRequest == null) + { + return null; + } + + // Verify that the challenge is a Basic Challenge + if (challenge == null || !challenge.StartsWith(AuthenticationTypeName, StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + return Authenticate(httpWebRequest, credentials); + } + + Authorization IAuthenticationModule.PreAuthenticate(WebRequest request, ICredentials credentials) + { + HttpWebRequest httpWebRequest = request as HttpWebRequest; + + if (httpWebRequest == null) + { + return null; + } + + return Authenticate(httpWebRequest, credentials); + } + + private Authorization Authenticate(HttpWebRequest httpWebRequest, ICredentials credentials) + { + if (credentials == null) + { + return null; + } + + // Get the username and password from the credentials + NetworkCredential nc = credentials.GetCredential(httpWebRequest.RequestUri, AuthenticationTypeName); + if (nc == null) + { + return null; + } + + ICredentialPolicy policy = AuthenticationManager.CredentialPolicy; + if (policy != null && !policy.ShouldSendCredential(httpWebRequest.RequestUri, httpWebRequest, nc, this)) + { + return null; + } + + string domain = nc.Domain; + + string basicTicket = (!String.IsNullOrEmpty(domain) ? (domain + "\\") : "") + nc.UserName + ":" + nc.Password; + byte[] bytes = Encoding.UTF8.GetBytes(basicTicket); + + string header = AuthenticationTypeName + " " + Convert.ToBase64String(bytes); + return new Authorization(header, true); + } + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs new file mode 100644 index 0000000000..b3a6c24c2e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; + +namespace Microsoft.WebMatrix.Utility +{ + internal class ExceptionHelper + { + private const int PublicKeyTokenLength = 8; + + /// + /// This will return a list of assemblies that are present in the call stack for + /// the input exception. The list CAN have duplicates. + /// + /// + /// + public static IEnumerable GetAssembliesInCallStack(Exception exception) + { + // an AggregateException might have multiple inner exceptions, so we handle it specially + AggregateException aggregateException = exception as AggregateException; + if (exception == null) + { + return Enumerable.Empty(); + } + else if (aggregateException == null) + { + return GetAssembliesInSingleException(exception).Concat(GetAssembliesInCallStack(exception.InnerException)); + } + else + { + return aggregateException.Flatten().InnerExceptions.SelectMany(ex => GetAssembliesInCallStack(ex)); + } + } + + private static IEnumerable GetAssembliesInSingleException(Exception exception) + { + // some exceptions (like AggregateException) don't have an associated stacktrace + if (exception != null && exception.StackTrace != null) + { + StackTrace stackTrace = new StackTrace(exception, false); + foreach (StackFrame frame in stackTrace.GetFrames()) + { + // DeclaringType can be null for lambdas created by Reflection.Emit + Type declaringType = frame.GetMethod().DeclaringType; + if (declaringType != null) + { + Assembly currentAssembly = declaringType.Assembly; + Debug.Assert(currentAssembly != null, "currentAssembly must not be null"); + if (currentAssembly != null) + { + yield return currentAssembly; + } + } + } + } + } + + public static IEnumerable RemoveAssembliesThatAreIntheGAC(IEnumerable input) + { + foreach (Assembly assembly in input) + { + if (!assembly.GlobalAssemblyCache) + { + yield return assembly; + } + } + } + + public static IEnumerable RemoveAssembliesThatAreSignedWithToken(IEnumerable input, byte[] publicKeyToken) + { + Debug.Assert(publicKeyToken.Length == PublicKeyTokenLength, "public key tokens should be 8 bytes"); + foreach (Assembly assembly in input) + { + byte[] currentToken = assembly.GetName().GetPublicKeyToken(); + bool shouldReturn; + if (currentToken.Length == 0) + { + // unsigned assembly + shouldReturn = true; + } + else if (AreTokensTheSame(currentToken, publicKeyToken)) + { + // tokens are the same skip the assembly + shouldReturn = false; + } + else + { + // didnt match anything, return it + shouldReturn = true; + } + + if (shouldReturn) + { + yield return assembly; + } + } + } + + private static bool AreTokensTheSame(byte[] token1, byte[] token2) + { + Debug.Assert( + token1.Length == PublicKeyTokenLength && + token2.Length == PublicKeyTokenLength, + "public key tokens should be 8 bytes"); + + for (int i = 0; i < PublicKeyTokenLength; i++) + { + if (token1[i] != token2[i]) + { + return false; + } + } + + return true; + } + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs new file mode 100644 index 0000000000..2dbd5c8ff1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs @@ -0,0 +1,192 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Diagnostics; + +namespace Microsoft.Web.Utility +{ + // need to include \common\Managed\NativeMethods\Fusion.cs in your project to use this class + internal static class GACManagedAccess + { + public static List GetAssemblyList(string assemblyName) + { + return GetAssemblyList(assemblyName, true); + } + + public static List GetAssemblyList(string assemblyName, bool getPhysicalPath) + { + if (string.IsNullOrEmpty(assemblyName)) + { + throw new ArgumentNullException("assemblyName"); + } + + List assemblyList = new List(); + using (GacAssembly gacAssembly = new GacAssembly(assemblyName)) + { + while (true) + { + if (gacAssembly.GetNextAssembly()) + { + if (getPhysicalPath) + { + using (GACAssemblyCache gacAssemblyCache = new GACAssemblyCache(assemblyName, gacAssembly.FullAssemblyName)) + { + assemblyList.Add(gacAssemblyCache.AssemblyPath); + } + } + else + { + assemblyList.Add(gacAssembly.FullAssemblyName); + } + } + else + { + break; + } + } + } + + return assemblyList; + } + } + + internal class GacAssembly : IDisposable + { + internal GacAssembly(string assemblyName) + { + _assemblyName = assemblyName; + int hResult = PInvoke.Fusion.NativeMethods.CreateAssemblyNameObject( + out _fusionName, + _assemblyName, + PInvoke.Fusion.CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME, + IntPtr.Zero); + + if (hResult >= 0) + { + hResult = PInvoke.Fusion.NativeMethods.CreateAssemblyEnum( + out _assemblyEnum, + IntPtr.Zero, + _fusionName, + PInvoke.Fusion.AssemblyCacheFlags.GAC, + IntPtr.Zero); + } + + if (hResult < 0 || _assemblyEnum == null) + { + throw Marshal.GetExceptionForHR(hResult); + } + } + + internal bool GetNextAssembly() + { + int hResult = _assemblyEnum.GetNextAssembly((IntPtr)0, out _fusionName, 0); + + if (hResult < 0 || _fusionName == null) + { + return false; + } + + return true; + } + + internal string FullAssemblyName + { + get + { + StringBuilder sDisplayName = new StringBuilder(1024); + int iLen = 1024; + + int hrLocal = _fusionName.GetDisplayName( + sDisplayName, + ref iLen, + (int)PInvoke.Fusion.AssemblyNameDisplayFlags.ALL); + + if (hrLocal < 0) + { + throw Marshal.GetExceptionForHR(hrLocal); + } + + return sDisplayName.ToString(); + } + } + + internal PInvoke.Fusion.IAssemblyName FusionName + { + get + { + return _fusionName; + } + } + + public void Dispose() + { + PInvoke.Fusion.IAssemblyName tempName = _fusionName; + if (tempName != null) + { + _fusionName = null; + Marshal.ReleaseComObject(tempName); + } + + PInvoke.Fusion.IAssemblyEnum tempEnum = _assemblyEnum; + if (tempEnum != null) + { + _assemblyEnum = null; + Marshal.ReleaseComObject(tempEnum); + } + } + + private string _assemblyName; + private PInvoke.Fusion.IAssemblyEnum _assemblyEnum; + private PInvoke.Fusion.IAssemblyName _fusionName; + } + + internal class GACAssemblyCache : IDisposable + { + internal GACAssemblyCache(string assemblyName, string fullAssemblyName) + { + PInvoke.Fusion.AssemblyInfo aInfo = new PInvoke.Fusion.AssemblyInfo(); + aInfo.cchBuf = 1024; + aInfo.currentAssemblyPath = new string('\0', aInfo.cchBuf); + + int hResult = PInvoke.Fusion.NativeMethods.CreateAssemblyCache(out _assemblyCache, 0); + + if (hResult == 0) + { + hResult = _assemblyCache.QueryAssemblyInfo(0, fullAssemblyName, ref aInfo); + } + + if (hResult != 0) + { + Marshal.GetExceptionForHR(hResult); + } + + _assemblyPath = aInfo.currentAssemblyPath; + } + + internal string AssemblyPath + { + get + { + return _assemblyPath; + } + } + + public void Dispose() + { + PInvoke.Fusion.IAssemblyCache temp = _assemblyCache; + if (temp != null) + { + _assemblyCache = null; + Marshal.ReleaseComObject(temp); + } + } + + private string _assemblyPath; + private PInvoke.Fusion.IAssemblyCache _assemblyCache; + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs new file mode 100644 index 0000000000..2f5a9c93c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Collections; +using System.Net; + +namespace Microsoft.Web.Utility +{ + internal static class WebUtility + { + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification="We want to count any error as host doesn't exist")] + public static bool IsLocalMachine(string serverName, bool useDns) + { + if (String.Equals(serverName, Environment.MachineName, StringComparison.CurrentCultureIgnoreCase) || + String.Equals(serverName, "localhost", StringComparison.OrdinalIgnoreCase) || + String.Equals(serverName, "127.0.0.1") || + String.Equals(serverName, "::1")) + { + return true; + } + + if (useDns) + { + try + { + ArrayList serverAddressesList = new ArrayList(); + ArrayList currentMachineAddressesList = new ArrayList(); + + IPAddress ownAddress = IPAddress.Parse("127.0.0.1"); + + // All the IP addresses of the hostname specified by the user + IPAddress[] serverAddress = Dns.GetHostAddresses(serverName); + serverAddressesList.AddRange(serverAddress); + + /// All the IP addresses of the current machine + IPAddress[] currentMachineAddress = Dns.GetHostAddresses(Environment.MachineName); + currentMachineAddressesList.AddRange(currentMachineAddress); + + // The address 127.0.0.1 also refers to the current machine + currentMachineAddressesList.Add(ownAddress); + + // If any of the addresses for the current machine is the same + // as the address for the hostname specified by the user + // then use a local connection + foreach (IPAddress address in currentMachineAddressesList) + { + if (serverAddressesList.Contains(address)) + { + return true; + } + } + } + catch + { + // If the Dns class throws an exception the host propbably does not + // exist so we return false + } + } + + return false; + } + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md new file mode 100644 index 0000000000..77fc8404c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md @@ -0,0 +1,18 @@ +Microsoft IIS Common +-------------------------------- + +The repository contains common resources shared by IIS Out-Of-Band (OOB) products. + +### Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc new file mode 100644 index 0000000000..98b1593b3b --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#define RC_VERSION_INTERNAL_NAME "Common.UnitTests\0" +#define RC_VERSION_ORIGINAL_FILE_NAME "Common.UnitTests.dll\0" +#define RC_VERSION_FILE_DESCRIPTION "Common.UnitTests0" +#include diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp new file mode 100644 index 0000000000..2fc97d6f95 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "dbgutil.h" +#include + +DECLARE_DEBUG_PRINT_OBJECT( "test" ); + +VOID PrintLevel( DWORD level ) +{ + DWORD old = DEBUG_FLAGS_VAR; + DEBUG_FLAGS_VAR = level; + + DBGPRINTF(( DBG_CONTEXT, "Some Data %d\n", 47 )); + DBGINFO(( DBG_CONTEXT, "Some Info %s\n", "info" )); + DBGWARN(( DBG_CONTEXT, "Some Info %s\n", "warning" )); + DBGERROR(( DBG_CONTEXT, "Some Info %s\n", "error" )); + + DEBUG_FLAGS_VAR = old; +} + + +#pragma managed + +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; + +[TestClass] +public ref class DebugUtilitiesTests +{ +public: + + [ClassInitialize] + static void InitializeDebugObjects(TestContext) + { + CREATE_DEBUG_PRINT_OBJECT; + + _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); + } + + [TestMethod] + void TestDbgError() + { + PrintLevel( DEBUG_FLAGS_ERROR ); + } + + [TestMethod] + void TestPrintAny() + { + PrintLevel( DEBUG_FLAGS_ANY ); + } + + [TestMethod] + void TestPrintError() + { + DBGERROR_HR( E_FAIL ); + DBGERROR_STATUS( 47 ); + } + + [TestMethod] + void TestPrintWarn() + { + PrintLevel( DEBUG_FLAGS_WARN ); + } + + [TestMethod] + void TestPrintInfo() + { + PrintLevel( DEBUG_FLAGS_INFO ); + } +}; \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp new file mode 100644 index 0000000000..c0fb29f5a2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "hashtable.h" +#include "hashfn.h" +#include "my_hash.h" + +VOID +CountHash( + MY_OBJ * , //pRecord, + PVOID pVoid +) +{ + DWORD * pActualCount = (DWORD*) pVoid; + ++(*pActualCount); +} + + +#pragma managed + +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; + +[TestClass] +public ref class HashTableTests +{ +public: + + [TestMethod] + void AddTwoRecordsTest() + { + MY_HASH hash; + HRESULT hr; + hr = hash.Initialize(32); + + Assert::AreEqual(S_OK, hr, L"Invalid hash table initialization"); + + MY_OBJ one(L"one"); + hr = hash.InsertRecord(&one); + Assert::AreEqual(S_OK, hr, L"Cannot add element 'one'"); + + MY_OBJ two(L"two"); + hr = hash.InsertRecord(&two); + Assert::AreEqual(S_OK, hr, L"Cannot add element 'two'"); + + DWORD ActualCount = 0; + hash.Apply(CountHash, &ActualCount); + Assert::AreEqual((DWORD)2, ActualCount, L"ActualCount != 2"); + + hash.Clear(); + } +}; diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp new file mode 100644 index 0000000000..9f54467e77 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "hybrid_array.h" + +// +// Cannot support mixed native/managed code for BUFFER class +// because of alignment. We need to run the test as native. +// +#include + + +void HybridArrayTest() +{ + HRESULT hr; + + { + HYBRID_ARRAY arrPointers; + Assert::AreEqual(32, arrPointers.QueryCapacity(), L"Invalid initial length"); + } + + { + HYBRID_ARRAY arrIntegers; + int SourceArray[] = {1, 2, 3, 4}; + hr = arrIntegers.Copy( SourceArray ); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(_countof(SourceArray), arrIntegers.QueryCapacity()); + } + + { + HYBRID_ARRAY arrIntegers; + int* pOriginal = arrIntegers.QueryArray(); + int SourceArray[] = {1, 2, 3, 4}; + hr = arrIntegers.Copy( SourceArray ); + int* pNew = arrIntegers.QueryArray(); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(_countof(SourceArray), arrIntegers.QueryCapacity(), L"Size should be like source"); + Assert::AreNotEqual((__int64)pNew, (__int64)pOriginal, L"Pointer should be different"); + + Assert::AreEqual(1, arrIntegers[0], L"Index 0 failed."); + Assert::AreEqual(2, arrIntegers.QueryItem(1), L"Index 1 failed."); + Assert::AreEqual(3, arrIntegers.QueryItem(2), L"Index 2 failed."); + Assert::AreEqual(4, arrIntegers[3], L"Index 3 failed."); + } + + { + HYBRID_ARRAY arrIntegers; + hr = arrIntegers.EnsureCapacity(100, false); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(100, arrIntegers.QueryCapacity()); + } + + { + HYBRID_ARRAY arrIntegers; + arrIntegers[0] = 123; + arrIntegers[1] = 999; + hr = arrIntegers.EnsureCapacity(100, true /*copy previous*/); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(100, arrIntegers.QueryCapacity()); + Assert::AreEqual(123, arrIntegers[0], L"Index resize 0 failed."); + Assert::AreEqual(999, arrIntegers[1], L"Index resize 1 failed."); + + } + + { + HYBRID_ARRAY arrIntegers; + arrIntegers[0] = 123; + arrIntegers[1] = 999; + hr = arrIntegers.EnsureCapacity(100, true /*copy previous*/, true /*trivial assign*/); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(100, arrIntegers.QueryCapacity()); + Assert::AreEqual(123, arrIntegers[0], L"Index resize trivial 0 failed."); + Assert::AreEqual(999, arrIntegers[1], L"Index resize trivial 1 failed."); + + } +} + + +#pragma managed + +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; + +[TestClass] +public ref class ArrayTests +{ +public: + + [TestMethod] + void HybridArrayTest() + { + ::HybridArrayTest(); + } + +}; diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h new file mode 100644 index 0000000000..71417dc77b --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +class MY_OBJ +{ + public: + MY_OBJ(PCWSTR pstr) + : _pstr(pstr) + {} + + PCWSTR GetString() + { + return _pstr; + } + + private: + PCWSTR _pstr; +}; + +class MY_HASH : public HASH_TABLE +{ + public: + VOID + ReferenceRecord( + MY_OBJ * //pRecord + ) + {} + + VOID + DereferenceRecord( + MY_OBJ * //pRecord + ) + {} + + PCWSTR + ExtractKey( + MY_OBJ * pRecord + ) + { + return pRecord->GetString(); + } + + DWORD + CalcKeyHash( + PCWSTR key + ) + { + return HashString(key); + } + + BOOL + EqualKeys( + PCWSTR key1, + PCWSTR key2 + ) + { + return (wcscmp(key1, key2) == 0); + } +}; + +void TestHash(); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx new file mode 100644 index 0000000000..16c76d9540 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +// Native-only by default +#pragma unmanaged +#include diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp new file mode 100644 index 0000000000..0b987e9b58 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp @@ -0,0 +1,680 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "buffer.h" +#include "stringu.h" +#include "stringa.h" + +// +// Cannot support mixed native/managed code for BUFFER class +// because of alignment. We need to run the test as native. +// +#include + +void TestBuffer() +{ + // + // 104 == 8 byte size rounded, why is this needed? + // + STACK_BUFFER( bufStack, 104 ); + BUFFER bufReg; + BUFFER* pBuf = new BUFFER; + + // + // QueryPtr + // + Assert::IsNotNull( bufStack.QueryPtr( ) ); + Assert::IsNotNull( bufReg.QueryPtr( ) ); + Assert::IsNotNull( pBuf->QueryPtr( ) ); + + // + // QuerySize + // + Assert::IsTrue( 104 == bufStack.QuerySize( ) ); + Assert::IsTrue( INLINED_BUFFER_LEN == bufReg.QuerySize( ) ); + Assert::IsTrue( INLINED_BUFFER_LEN == pBuf->QuerySize( ) ); + + // + // Resize + // + Assert::IsTrue( bufStack.Resize( 64 ) ); + Assert::IsTrue( bufReg.Resize( 128) ); + Assert::IsTrue( pBuf->Resize( 256 ) ); + + // + // Resize again + // + Assert::IsTrue( bufStack.Resize( 512, true ) ); + Assert::IsTrue( bufReg.Resize( 512, true ) ); + Assert::IsTrue( pBuf->Resize( 512, true ) ); + + // + // Resize again + // + Assert::IsTrue( bufStack.Resize( 1024, false ) ); + Assert::IsTrue( bufReg.Resize( 1024, false ) ); + Assert::IsTrue( pBuf->Resize( 1024, false ) ); + + // + // write to mem + // + ZeroMemory( bufStack.QueryPtr( ), bufStack.QuerySize( ) ); + ZeroMemory( bufReg.QueryPtr( ), bufReg.QuerySize( ) ); + ZeroMemory( pBuf->QueryPtr( ), pBuf->QuerySize( ) ); + + delete pBuf; +} + +void TestStraOverrun() +{ + STACK_STRA( straStack, 3 ); + wchar_t Input[] = {0x65f6, 0x0}; + HRESULT hr; + + hr = straStack.CopyW(Input); + Assert::IsTrue( SUCCEEDED(hr) ); + Assert::AreEqual( 3, straStack.QueryCCH(), L"Invalid string length." ); + Assert::AreEqual( 4, straStack.QuerySizeCCH(), L"Invalid buffer length." ); +} + +#define LOWER_A_THING L"ä" +#define UPPER_A_THING L"Ä" + +void TestStru() +{ + STACK_STRU( struStack, 104 ); + STRU struReg; + wchar_t buf[100]; + DWORD cbBuf = sizeof( buf ); + + // + // IsEmpty + // + Assert::IsTrue( struStack.IsEmpty( ) ); + Assert::IsTrue( L'\0' == struStack.QueryStr()[0] ); + Assert::IsTrue( struReg.IsEmpty( ) ); + + // + // Copy psz + // CopyA psz + // + Assert::IsTrue( SUCCEEDED( struStack.Copy( L"hello" ) ) ); + Assert::IsTrue( SUCCEEDED( struReg.CopyA( "hello" ) ) ); + + // + // Equal + // + Assert::IsTrue( struStack.Equals( L"hello" ) ); + Assert::IsTrue( !struStack.Equals( L"goodbye" ) ); + Assert::IsTrue( !struStack.Equals( L"" ) ); + + STRU strHELLO; + Assert::IsTrue( SUCCEEDED( strHELLO.Copy( L"HELLO" ) ) ); + + Assert::IsTrue( struStack.Equals( &struReg ) ); + Assert::IsTrue( struStack.Equals( struReg ) ); + + Assert::IsTrue( !struStack.Equals( &strHELLO ) ); + Assert::IsTrue( !struStack.Equals( strHELLO ) ); + + Assert::IsTrue( struStack.Equals( &strHELLO, TRUE ) ); + Assert::IsTrue( struStack.Equals( strHELLO, TRUE ) ); + + Assert::IsTrue( struStack.Equals( L"helLO", TRUE ) ); + + + Assert::IsTrue( STRU::Equals( L"Hello", L"Hello" ) ); + Assert::IsTrue( STRU::Equals( L"Hello", L"Hello", FALSE ) ); + Assert::IsTrue( STRU::Equals( L"Hello", L"Hello", TRUE ) ); + + Assert::IsFalse( STRU::Equals( L"hello", L"Hello" ) ); + Assert::IsFalse( STRU::Equals( L"hello", L"Hello", FALSE ) ); + Assert::IsTrue( STRU::Equals( L"hello", L"Hello", TRUE ) ); + + Assert::IsFalse( STRU::Equals( L"hello", L"goodbye" ) ); + Assert::IsFalse( STRU::Equals( L"hello", L"goodbye", FALSE ) ); + Assert::IsFalse( STRU::Equals( L"hello", L"goodbye", TRUE ) ); + + Assert::IsFalse( STRU::Equals( (PCWSTR)NULL, (PCWSTR)NULL ) ); + Assert::IsFalse( STRU::Equals( L"hello", (PCWSTR)NULL ) ); + Assert::IsFalse( STRU::Equals( (PCWSTR)NULL, L"hello" ) ); + + + + // + // Query* + // + Assert::IsTrue( 5 * sizeof( wchar_t ) == struStack.QueryCB( ) ); + Assert::IsTrue( 5 == struStack.QueryCCH( ) ); + Assert::IsTrue( 6 <= struStack.QuerySizeCCH( ) ); + Assert::IsTrue( L'h' == *( struStack.QueryStr( ) ) ); + + // + // Resize + // + Assert::IsTrue( SUCCEEDED( struReg.Resize( 7 ) ) ); + Assert::IsTrue( 7 == struReg.QuerySizeCCH( ) ); + + // + // SyncWithBuffer + // + *(struStack.QueryStr() + 5) = L'\0'; + Assert::AreEqual(S_OK, struStack.SyncWithBuffer( )); + Assert::IsTrue( 5 == struStack.QueryCCH( ) ); + + // + // Reset + // + struStack.Reset( ); + Assert::IsTrue( 0 == wcslen( struStack.QueryStr( ) ) ); + + // + // Append* + // + Assert::IsTrue( SUCCEEDED( struStack.Append( L"hell" ) ) ); + Assert::IsTrue( SUCCEEDED( struStack.Append( L"o", 1 ) ) ); + Assert::IsTrue( SUCCEEDED( struStack.Append( &struReg ) ) ); + Assert::IsTrue( SUCCEEDED( struStack.AppendA( "hell" ) ) ); + Assert::IsTrue( SUCCEEDED( struStack.AppendA( "0", 1, CP_ACP ) ) ); + Assert::IsTrue( 15 == wcslen( struStack.QueryStr( ) ) ); + + // + // CopyToBuffer + // + Assert::IsTrue( SUCCEEDED( struStack.CopyToBuffer( buf, &cbBuf ) ) ); + Assert::IsTrue( 15 == wcslen( buf ) ); + Assert::IsTrue( 16 * sizeof( wchar_t ) == cbBuf ); + + // + // Trim + // + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" \n\tHello World! \n\t ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"Hello World!")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" Test test") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"Test test")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"Test test ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"Test test")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" Test test ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"Test test")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"")); + + // + // StartsWith + // + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"Just the facts, please.") ) ); + Assert::IsTrue( struStack.StartsWith(L"Just the facts, please.") ); + Assert::IsTrue( struStack.StartsWith(L"Just") ); + Assert::IsTrue( struStack.StartsWith(L"Just the") ); + Assert::IsTrue( !struStack.StartsWith(L"just the") ); + Assert::IsTrue( struStack.StartsWith(L"just The", TRUE) ); + Assert::IsTrue( !struStack.StartsWith((LPCWSTR) NULL, TRUE) ); + Assert::IsTrue( !struStack.StartsWith(L"Just the facts, please...") ); + + // + // EndsWith + // + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"The beginning of the end of the beginning.") ) ); + Assert::IsTrue( struStack.EndsWith(L"The beginning of the end of the beginning.") ); + Assert::IsTrue( struStack.EndsWith(L".") ); + Assert::IsTrue( struStack.EndsWith(L"of the beginning.") ); + Assert::IsTrue( !struStack.EndsWith(L"Beginning.") ); + Assert::IsTrue( struStack.EndsWith(L"Beginning.", TRUE) ); + Assert::IsTrue( struStack.EndsWith(L"tHe BeGiNnIng.", TRUE) ); + Assert::IsTrue( !struStack.EndsWith((LPCWSTR) NULL, TRUE) ); + Assert::IsTrue( !struStack.EndsWith(L" The beginning of the end of the beginning.") ); + + // + // IndexOf + // + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"01234567890") ) ); + Assert::IsTrue( 0 == struStack.IndexOf( L'0' ) ); + Assert::IsTrue( 1 == struStack.IndexOf( L'1' ) ); + Assert::IsTrue( 2 == struStack.IndexOf( L'2', 1 ) ); + Assert::IsTrue( 10 == struStack.IndexOf( L'0', 1 ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L'A' ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L'0', 20 ) ); + + Assert::IsTrue( 0 == struStack.IndexOf( L"0123" ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L"0123", 1 ) ); + Assert::IsTrue( 0 == struStack.IndexOf( L"01234567890" ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L"012345678901" ) ); + Assert::IsTrue( 1 == struStack.IndexOf( L"1234" ) ); + Assert::IsTrue( 1 == struStack.IndexOf( L"1234", 1 ) ); + Assert::IsTrue( -1 == struStack.IndexOf( (PCWSTR)NULL ) ); + Assert::IsTrue( 0 == struStack.IndexOf( L"" ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L"", 20 ) ); + + // + // LastIndexOf + // + Assert::IsTrue( 10 == struStack.LastIndexOf( L'0' ) ); + Assert::IsTrue( 1 == struStack.LastIndexOf( L'1' ) ); + Assert::IsTrue( 2 == struStack.LastIndexOf( L'2', 1 ) ); + Assert::IsTrue( 10 == struStack.LastIndexOf( L'0', 1 ) ); + Assert::IsTrue( -1 == struStack.LastIndexOf( L'A' ) ); + Assert::IsTrue( -1 == struStack.LastIndexOf( L'0', 20 ) ); + + // + // SetLen + // + Assert::IsTrue( SUCCEEDED( struStack.SetLen( 2 ) ) ); + Assert::IsTrue( 2 == struStack.QueryCCH( ) ); + +#if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + // + // OS-locale case-insensitive compare + // Note how the two case-insensitive comparisons have different expected results + // + Assert::IsTrue( SUCCEEDED( struStack.Copy( LOWER_A_THING ) ) ); + Assert::IsTrue( SUCCEEDED( struReg.Copy( UPPER_A_THING ) ) ); + Assert::IsTrue( !struStack.Equals( &struReg ) ); + Assert::IsTrue( struStack.Equals( &struReg, TRUE ) ); + Assert::IsTrue( 0 != _wcsicmp( LOWER_A_THING, UPPER_A_THING ) ); + +#endif + + Assert::IsTrue( SUCCEEDED( struReg.SafeSnwprintf( L"%s%d", L"Hello", 10 ) ) ); + + // + // Fail since there is no null-terminating char. + // + struStack.Reset(); + struStack.Resize(200); + memset(struStack.QueryStr(), 'x', 200 * sizeof(WCHAR)); + Assert::AreNotEqual(S_OK, struStack.SyncWithBuffer()); +} + +void TestStra() +{ + STACK_STRA( straStack, 104 ); + STRA straReg; + char buf[100]; + DWORD cbBuf = sizeof( buf ); + + // + // IsEmpty + // + Assert::IsTrue( straStack.IsEmpty( ) ); + Assert::IsTrue( '\0' == straStack.QueryStr()[0] ); + Assert::IsTrue( straReg.IsEmpty( ) ); + + // + // Copy psz + // CopyW psz + // + Assert::IsTrue( SUCCEEDED( straStack.Copy( "hello" ) ) ); + Assert::IsTrue( SUCCEEDED( straReg.CopyW( L"hello" ) ) ); + + // + // Equal + // + Assert::IsTrue( straStack.Equals( "hello" ) ); + Assert::IsTrue( straStack.Equals( &straReg ) ); + Assert::IsTrue( straStack.Equals( "helLO", TRUE ) ); + + + Assert::IsTrue( STRA::Equals( "Hello", "Hello" ) ); + Assert::IsTrue( STRA::Equals( "Hello", "Hello", FALSE ) ); + Assert::IsTrue( STRA::Equals( "Hello", "Hello", TRUE ) ); + + Assert::IsFalse( STRA::Equals( "hello", "Hello" ) ); + Assert::IsFalse( STRA::Equals( "hello", "Hello", FALSE ) ); + Assert::IsTrue( STRA::Equals( "hello", "Hello", TRUE ) ); + + Assert::IsFalse( STRA::Equals( "hello", "goodbye" ) ); + Assert::IsFalse( STRA::Equals( "hello", "goodbye", FALSE ) ); + Assert::IsFalse( STRA::Equals( "hello", "goodbye", TRUE ) ); + + Assert::IsFalse( STRA::Equals( (PCSTR)NULL, (PCSTR)NULL ) ); + Assert::IsFalse( STRA::Equals( "hello", (PCSTR)NULL ) ); + Assert::IsFalse( STRA::Equals( (PCSTR)NULL, "hello" ) ); + + // + // Query* + // + Assert::IsTrue( 5 * sizeof( char ) == straStack.QueryCB( ) ); + Assert::IsTrue( 5 == straStack.QueryCCH( ) ); + Assert::IsTrue( 6 <= straStack.QuerySizeCCH( ) ); + Assert::IsTrue( 'h' == *( straStack.QueryStr( ) ) ); + + // + // Resize + // + Assert::IsTrue( SUCCEEDED( straReg.Resize( 7 ) ) ); + Assert::IsTrue( 7 == straReg.QuerySizeCCH( ) ); + + // + // SyncWithBuffer + // + *(straStack.QueryStr() + 5) = L'\0'; + Assert::AreEqual(S_OK, straStack.SyncWithBuffer( )); + Assert::IsTrue( 5 == straStack.QueryCCH( ) ); + + // + // Reset + // + straStack.Reset( ); + Assert::IsTrue( 0 == strlen( straStack.QueryStr( ) ) ); + + // + // Append* + // + Assert::IsTrue( SUCCEEDED( straStack.Append( "hell" ) ) ); + Assert::IsTrue( SUCCEEDED( straStack.Append( "o", 1 ) ) ); + Assert::IsTrue( SUCCEEDED( straStack.Append( &straReg ) ) ); + Assert::IsTrue( SUCCEEDED( straStack.AppendW( L"hell" ) ) ); + Assert::IsTrue( SUCCEEDED( straStack.AppendW( L"0", 1, CP_ACP ) ) ); + Assert::IsTrue( 15 == strlen( straStack.QueryStr( ) ) ); + + // + // CopyToBuffer + // + Assert::IsTrue( SUCCEEDED( straStack.CopyToBuffer( buf, &cbBuf ) ) ); + Assert::IsTrue( 15 == strlen( buf ) ); + Assert::IsTrue( 16 * sizeof( char ) == cbBuf ); + + // + // Trim + // + Assert::IsTrue( SUCCEEDED( straStack.Copy(" \n\tHello World! \n\t ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("Hello World!")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy(" Test test") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("Test test")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy("Test test ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("Test test")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy(" Test test ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("Test test")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy(" ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy(" ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy("") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("")); + + // + // StartsWith + // + Assert::IsTrue( SUCCEEDED( straStack.Copy("Just the facts, please.") ) ); + Assert::IsTrue( straStack.StartsWith("Just the facts, please.") ); + Assert::IsTrue( straStack.StartsWith("Just") ); + Assert::IsTrue( straStack.StartsWith("Just the") ); + Assert::IsTrue( !straStack.StartsWith("just the") ); + Assert::IsTrue( straStack.StartsWith("just The", TRUE) ); + Assert::IsTrue( !straStack.StartsWith((LPCSTR) NULL, TRUE) ); + Assert::IsTrue( !straStack.StartsWith("Just the facts, please...") ); + + // + // EndsWith + // + Assert::IsTrue( SUCCEEDED( straStack.Copy("The beginning of the end of the beginning.") ) ); + Assert::IsTrue( straStack.EndsWith("The beginning of the end of the beginning.") ); + Assert::IsTrue( straStack.EndsWith(".") ); + Assert::IsTrue( straStack.EndsWith("of the beginning.") ); + Assert::IsTrue( !straStack.EndsWith("Beginning.") ); + Assert::IsTrue( straStack.EndsWith("Beginning.", TRUE) ); + Assert::IsTrue( straStack.EndsWith("tHe BeGiNnIng.", TRUE) ); + Assert::IsTrue( !straStack.EndsWith((LPCSTR) NULL, TRUE) ); + Assert::IsTrue( !straStack.EndsWith(" The beginning of the end of the beginning.") ); + + // + // IndexOf + // + Assert::IsTrue( SUCCEEDED( straStack.Copy("01234567890") ) ); + Assert::IsTrue( 0 == straStack.IndexOf( '0' ) ); + Assert::IsTrue( 1 == straStack.IndexOf( '1' ) ); + Assert::IsTrue( 2 == straStack.IndexOf( '2', 1 ) ); + Assert::IsTrue( 10 == straStack.IndexOf( '0', 1 ) ); + Assert::IsTrue( -1 == straStack.IndexOf( 'A' ) ); + Assert::IsTrue( -1 == straStack.IndexOf( '0', 20 ) ); + + Assert::IsTrue( 0 == straStack.IndexOf( "0123" ) ); + Assert::IsTrue( -1 == straStack.IndexOf( "0123", 1 ) ); + Assert::IsTrue( 0 == straStack.IndexOf( "01234567890" ) ); + Assert::IsTrue( -1 == straStack.IndexOf( "012345678901" ) ); + Assert::IsTrue( 1 == straStack.IndexOf( "1234" ) ); + Assert::IsTrue( 1 == straStack.IndexOf( "1234", 1 ) ); + Assert::IsTrue( -1 == straStack.IndexOf( (PCSTR)NULL ) ); + Assert::IsTrue( 0 == straStack.IndexOf( "" ) ); + Assert::IsTrue( -1 == straStack.IndexOf( "", 20 ) ); + + // + // LastIndexOf + // + Assert::IsTrue( 10 == straStack.LastIndexOf( '0' ) ); + Assert::IsTrue( 1 == straStack.LastIndexOf( '1' ) ); + Assert::IsTrue( 2 == straStack.LastIndexOf( '2', 1 ) ); + Assert::IsTrue( 10 == straStack.LastIndexOf( '0', 1 ) ); + Assert::IsTrue( -1 == straStack.LastIndexOf( 'A' ) ); + Assert::IsTrue( -1 == straStack.LastIndexOf( '0', 20 ) ); + + // + // SetLen + // + Assert::IsTrue( SUCCEEDED( straStack.SetLen( 2 ) ) ); + Assert::IsTrue( 2 == straStack.QueryCCH( ) ); + + + // + // Convert. + // + { + STRA str; + wchar_t psz[] = {0x41, L'Ã', 0x0}; + char pszA[] = {0x41, 'Ã', 0x0}; + Assert::IsTrue( SUCCEEDED(str.CopyW((LPCWSTR)psz, 2, CP_ACP )) ); + Assert::IsTrue( 0 == strcmp( pszA, str.QueryStr() ) ); + } + // + // Empty + // + { + STRA str; + wchar_t psz[] = {0x0}; + char pszA[] = {0x0}; + Assert::IsTrue( SUCCEEDED(str.CopyW((LPCWSTR)psz, 0, CP_ACP )) ); + Assert::IsTrue( 0 == strcmp( pszA, str.QueryStr() ) ); + } + + // + // Fail since there is no null-terminating char. + // + straStack.Reset(); + straStack.Resize(200); + memset(straStack.QueryStr(), 'x', 200); + Assert::AreNotEqual(S_OK, straStack.SyncWithBuffer()); +} + +VOID +AsciiAssert(char * str1, char * str2, size_t length) +{ + for ( size_t index = 0; index < length; ++index ) + { + Assert::AreEqual(str1[index], str2[index]); + } +} + +void +TestStraUnicode() +{ + STRA str; + HRESULT hr = S_OK; + + // + // Tool used to convert unicode to UTF-8 code points and hexadecimal code points: + // http://rishida.net/scripts/uniview/conversion.php + // + + // + // Input values to play with. + // + + // Real unicode string. + LPCWSTR InputRealUnicode = L"?q=世加"; + + // This is the same value than InputRealUnicode, but represented as an array. + wchar_t InputRealUnicodeArray[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0x4E16, // 世 + 0x52A0, // 加 + 0x00 // L'\0' + }; + + wchar_t InputAscii[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0x7F, // 127 + 0x00 // L'\0' + }; + + // Fake unicode + // UTF-8 code units in 'wchar_t' chars instead of 'char' chars. + // This is how WinHttp returns the query string. + wchar_t InputFakeUnicode[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0xE4, // 1st code unit for '世' + 0xB8, // 2nd code unit for '世' + 0x96, // 3rd code unit for '世' + 0xE5, // 1st code unit for '加' + 0x8A, // 2nd code unit for '加' + 0xA0, // 3rd code unit for '加' + 0x00 // L'\0' + }; + + // + // Expected values after translation. + // + + unsigned char ExpectedAsciiCodeUnits[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0xE4, // 1st code unit for '世' + 0xB8, // 2nd code unit for '世' + 0x96, // 3rd code unit for '世' + 0xE5, // 1st code unit for '加' + 0x8A, // 2nd code unit for '加' + 0xA0, // 3rd code unit for '加' + 0x00 // L'\0' + }; + + char ExpectedAscii[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0x7F, // 127 + 0x00 // L'\0' + }; + + // + // Act and Assert. + // + + hr = str.CopyW(InputRealUnicode); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(9UL, str.QueryCCH(), L"Invalid real unicode query string length."); + AsciiAssert( (char*)ExpectedAsciiCodeUnits, str.QueryStr(), str.QueryCCH() ); + + hr = str.CopyW(InputRealUnicodeArray); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(9UL, str.QueryCCH(), L"Invalid real unicode query string length."); + AsciiAssert( (char*)ExpectedAsciiCodeUnits, str.QueryStr(), str.QueryCCH() ); + + hr = str.CopyWTruncate(InputFakeUnicode); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(9UL, str.QueryCCH(), L"Invalid truncated fake unicode query string length."); + AsciiAssert( (char*)ExpectedAsciiCodeUnits, str.QueryStr(), str.QueryCCH() ); + + hr = str.CopyWTruncate(InputAscii); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(4UL, str.QueryCCH(), L"Invalid truncated ASCII query string length."); + AsciiAssert( ExpectedAscii, str.QueryStr(), str.QueryCCH() ); + + hr = str.CopyW(InputAscii); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(4UL, str.QueryCCH(), L"Invalid CopyW ASCII query string length."); + AsciiAssert( ExpectedAscii, str.QueryStr(), str.QueryCCH() ); + +} + +#pragma managed + +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; + +[TestClass] +public ref class StringTests +{ +public: + + [TestMethod] + void BufferTest() + { + ::TestBuffer(); + } + + [TestMethod] + void StruTest() + { + ::TestStru(); + } + + [TestMethod] + void StraTest() + { + ::TestStra(); + } + + [TestMethod] + void TestStraOverrun() + { + ::TestStraOverrun(); + } + + [TestMethod] + void StraUnicodeTest() + { + ::TestStraUnicode(); + } +}; diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj new file mode 100644 index 0000000000..35768b0006 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj @@ -0,0 +1,79 @@ + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {B54A8F61-60DE-4AD9-87CA-D102F230678E} + Win32Proj + Lib + CommonLib + + + + StaticLibrary + v141 + + + false + + + + $(ProjectDir)..\include;$(IncludePath) + iiscommon + + + + true + precomp.h + _LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + + + + + + + + + + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx new file mode 100644 index 0000000000..262c010a2a --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx @@ -0,0 +1,443 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#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::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; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp new file mode 100644 index 0000000000..9685b233c8 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp @@ -0,0 +1,1734 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +SetElementProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + IN CONST VARIANT * varPropValue + ) +{ + HRESULT hr = NOERROR; + + CComPtr pPropElement; + + BSTR bstrPropName = SysAllocString( szPropName ); + + if( !bstrPropName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrPropName, + &pPropElement ); + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pPropElement->put_Value( *varPropValue ); + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + if( bstrPropName ) + { + SysFreeString( bstrPropName ); + bstrPropName = NULL; + } + + return hr; +} + +HRESULT +SetElementStringProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + IN CONST WCHAR * szPropValue + ) +{ + HRESULT hr; + VARIANT varPropValue; + VariantInit(&varPropValue); + + hr = VariantAssign(&varPropValue, szPropValue); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty(pElement, szPropName, &varPropValue); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + VariantClear(&varPropValue); + return hr; +} + +HRESULT +GetElementStringProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + OUT BSTR * pbstrPropValue + ) +{ + HRESULT hr = S_OK; + BSTR bstrPropName = SysAllocString( szPropName ); + IAppHostProperty* pProperty = NULL; + + *pbstrPropValue = NULL; + + if (!bstrPropName) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrPropName, &pProperty ); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pProperty->get_StringValue( pbstrPropValue ); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + if (pProperty) + { + pProperty->Release(); + } + + if (bstrPropName) + { + SysFreeString( bstrPropName ); + } + + return hr; +} + + +HRESULT +GetElementStringProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + OUT STRU * pstrPropValue + ) +{ + HRESULT hr = S_OK; + BSTR bstrPropName = SysAllocString( szPropName ); + IAppHostProperty* pProperty = NULL; + BSTR bstrPropValue = NULL; + + if (!bstrPropName) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrPropName, &pProperty ); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pProperty->get_StringValue( &bstrPropValue ); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pstrPropValue->Copy(bstrPropValue); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + if (pProperty) + { + pProperty->Release(); + } + + if (bstrPropValue) + { + SysFreeString( bstrPropValue ); + } + + if (bstrPropName) + { + SysFreeString( bstrPropName ); + } + + return hr; +} + +HRESULT +GetElementChildByName( + IN IAppHostElement * pElement, + IN LPCWSTR pszElementName, + OUT IAppHostElement ** ppChildElement +) +{ + BSTR bstrElementName = SysAllocString(pszElementName); + if (bstrElementName == NULL) + { + return E_OUTOFMEMORY; + } + HRESULT hr = pElement->GetElementByName(bstrElementName, + ppChildElement); + SysFreeString(bstrElementName); + return hr; +} + +HRESULT +GetElementBoolProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT bool * pBool +) +{ + BOOL fValue; + HRESULT hr = GetElementBoolProperty(pElement, + pszPropertyName, + &fValue); + if (SUCCEEDED(hr)) + { + *pBool = !!fValue; + } + return hr; +} + +HRESULT +GetElementBoolProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT BOOL * pBool +) +{ + HRESULT hr = S_OK; + BSTR bstrPropertyName = NULL; + IAppHostProperty * pProperty = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrPropertyName = SysAllocString( pszPropertyName ); + if ( bstrPropertyName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + // Now ask for the property and if it succeeds it is returned directly back. + hr = pElement->GetPropertyByName( bstrPropertyName, &pProperty ); + if ( FAILED ( hr ) ) + { + goto exit; + } + + // Now let's get the property and then extract it from the Variant. + hr = pProperty->get_Value( &varValue ); + if ( FAILED ( hr ) ) + { + goto exit; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_BOOL ); + if ( FAILED ( hr ) ) + { + goto exit; + } + + // extract the value + *pBool = ( V_BOOL( &varValue ) == VARIANT_TRUE ); + +exit: + + VariantClear( &varValue ); + + if ( bstrPropertyName != NULL ) + { + SysFreeString( bstrPropertyName ); + bstrPropertyName = NULL; + } + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + return hr; + +} + +HRESULT +GetElementDWORDProperty( + IN IAppHostElement * pSitesCollectionEntry, + IN LPCWSTR pwszName, + OUT DWORD * pdwValue +) +{ + HRESULT hr = S_OK; + IAppHostProperty * pProperty = NULL; + BSTR bstrName = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrName = SysAllocString( pwszName ); + if ( bstrName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto error; + } + + hr = pSitesCollectionEntry->GetPropertyByName( bstrName, + &pProperty ); + if ( FAILED ( hr ) ) + { + goto error; + } + + hr = pProperty->get_Value( &varValue ); + if ( FAILED ( hr ) ) + { + goto error; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_UI4 ); + if ( FAILED ( hr ) ) + { + goto error; + } + + // extract the value + *pdwValue = varValue.ulVal; + +error: + + VariantClear( &varValue ); + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + if ( bstrName != NULL ) + { + SysFreeString( bstrName ); + bstrName = NULL; + } + + return hr; +} + +HRESULT +GetElementINTProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT INT * pintValue +) +{ + HRESULT hr = S_OK; + IAppHostProperty * pProperty = NULL; + BSTR bstrName = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrName = SysAllocString( pszPropertyName ); + if ( bstrName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto error; + } + + hr = pElement->GetPropertyByName( bstrName, + &pProperty ); + if ( FAILED( hr ) ) + { + goto error; + } + + hr = pProperty->get_Value( &varValue ); + if ( FAILED( hr ) ) + { + goto error; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_I4 ); + if ( FAILED( hr ) ) + { + goto error; + } + + // extract the value + *pintValue = varValue.intVal; + +error: + + VariantClear( &varValue ); + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + if ( bstrName != NULL ) + { + SysFreeString( bstrName ); + bstrName = NULL; + } + + return hr; +} + +HRESULT +GetElementLONGLONGProperty( + IN IAppHostElement * pSitesCollectionEntry, + IN LPCWSTR pwszName, + OUT LONGLONG * pllValue +) +{ + HRESULT hr = S_OK; + IAppHostProperty * pProperty = NULL; + BSTR bstrName = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrName = SysAllocString( pwszName ); + if ( bstrName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto error; + } + + hr = pSitesCollectionEntry->GetPropertyByName( bstrName, + &pProperty ); + if ( FAILED ( hr ) ) + { + goto error; + } + + hr = pProperty->get_Value( &varValue ); + if ( FAILED ( hr ) ) + { + goto error; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_I8 ); + if ( FAILED ( hr ) ) + { + goto error; + } + + // extract the value + *pllValue = varValue.ulVal; + +error: + + VariantClear( &varValue ); + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + if ( bstrName != NULL ) + { + SysFreeString( bstrName ); + bstrName = NULL; + } + + return hr; +} + +HRESULT +GetElementRawTimeSpanProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT ULONGLONG * pulonglong +) +{ + HRESULT hr = S_OK; + BSTR bstrPropertyName = NULL; + IAppHostProperty * pProperty = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrPropertyName = SysAllocString( pszPropertyName ); + if ( bstrPropertyName == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + goto Finished; + } + + // Now ask for the property and if it succeeds it is returned directly back + hr = pElement->GetPropertyByName( bstrPropertyName, &pProperty ); + if ( FAILED ( hr ) ) + { + goto Finished; + } + + // Now let's get the property and then extract it from the Variant. + hr = pProperty->get_Value( &varValue ); + if ( FAILED ( hr ) ) + { + goto Finished; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_UI8 ); + if ( FAILED ( hr ) ) + { + goto Finished; + } + + // extract the value + *pulonglong = varValue.ullVal; + + +Finished: + + VariantClear( &varValue ); + + if ( bstrPropertyName != NULL ) + { + SysFreeString( bstrPropertyName ); + bstrPropertyName = NULL; + } + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + return hr; + +} // end of Config_GetRawTimeSpanProperty + +HRESULT +DeleteElementFromCollection( + IAppHostElementCollection *pCollection, + CONST WCHAR * szKeyName, + CONST WCHAR * szKeyValue, + ULONG BehaviorFlags, + BOOL * pfDeleted + ) +{ + HRESULT hr = NOERROR; + ULONG index; + + VARIANT varIndex; + VariantInit( &varIndex ); + + *pfDeleted = FALSE; + + hr = FindElementInCollection( + pCollection, + szKeyName, + szKeyValue, + BehaviorFlags, + &index + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (hr == S_FALSE) + { + // + // Not found. + // + + goto exit; + } + + varIndex.vt = VT_UI4; + varIndex.ulVal = index; + + hr = pCollection->DeleteElement( varIndex ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + *pfDeleted = TRUE; + +exit: + + return hr; +} + +HRESULT +DeleteAllElementsFromCollection( + IAppHostElementCollection *pCollection, + CONST WCHAR * szKeyName, + CONST WCHAR * szKeyValue, + ULONG BehaviorFlags, + UINT * pNumDeleted + ) +{ + HRESULT hr = S_OK; + UINT numDeleted = 0; + BOOL fDeleted = TRUE; + + while (fDeleted) + { + hr = DeleteElementFromCollection( + pCollection, + szKeyName, + szKeyValue, + BehaviorFlags, + &fDeleted + ); + + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + break; + } + + if (fDeleted) + { + numDeleted++; + } + } + + *pNumDeleted = numDeleted; + return hr; +} + +BOOL +FindCompareCaseSensitive( + CONST WCHAR * szLookupValue, + CONST WCHAR * szKeyValue + ) +{ + return !wcscmp(szLookupValue, szKeyValue); +} + +BOOL +FindCompareCaseInsensitive( + CONST WCHAR * szLookupValue, + CONST WCHAR * szKeyValue + ) +{ + return !_wcsicmp(szLookupValue, szKeyValue); +} + +typedef +BOOL +(*PFN_FIND_COMPARE_PROC)( + CONST WCHAR *szLookupValue, + CONST WCHAR *szKeyValue + ); + +HRESULT +FindElementInCollection( + IAppHostElementCollection *pCollection, + CONST WCHAR * szKeyName, + CONST WCHAR * szKeyValue, + ULONG BehaviorFlags, + OUT ULONG * pIndex + ) +{ + HRESULT hr = NOERROR; + + CComPtr pElement; + CComPtr pKeyProperty; + + VARIANT varIndex; + VariantInit( &varIndex ); + + VARIANT varKeyValue; + VariantInit( &varKeyValue ); + + DWORD count; + DWORD i; + + BSTR bstrKeyName = NULL; + PFN_FIND_COMPARE_PROC compareProc; + + compareProc = (BehaviorFlags & FIND_ELEMENT_CASE_INSENSITIVE) + ? &FindCompareCaseInsensitive + : &FindCompareCaseSensitive; + + bstrKeyName = SysAllocString( szKeyName ); + if( !bstrKeyName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pCollection->get_Count( &count ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for( i = 0; i < count; i++ ) + { + varIndex.vt = VT_UI4; + varIndex.ulVal = i; + + hr = pCollection->get_Item( varIndex, + &pElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto tryNext; + } + + hr = pElement->GetPropertyByName( bstrKeyName, + &pKeyProperty ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto tryNext; + } + + hr = pKeyProperty->get_Value( &varKeyValue ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto tryNext; + } + + if ((compareProc)(szKeyValue, varKeyValue.bstrVal)) + { + *pIndex = i; + break; + } + +tryNext: + + pElement.Release(); + pKeyProperty.Release(); + + VariantClear( &varKeyValue ); + } + + if (i >= count) + { + hr = S_FALSE; + } + +exit: + + SysFreeString( bstrKeyName ); + VariantClear( &varKeyValue ); + + return hr; +} + +HRESULT +VariantAssign( + IN OUT VARIANT * pv, + IN CONST WCHAR * sz + ) +{ + if( !pv || !sz ) + { + return E_INVALIDARG; + } + + HRESULT hr = NOERROR; + + BSTR bstr = SysAllocString( sz ); + if( !bstr ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = VariantClear( pv ); + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + pv->vt = VT_BSTR; + pv->bstrVal = bstr; + bstr = NULL; + +exit: + + SysFreeString( bstr ); + + return hr; +} + +HRESULT +GetLocationFromFile( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szLocationPath, + OUT IAppHostConfigLocation ** ppLocation, + OUT BOOL * pFound + ) +{ + HRESULT hr = NOERROR; + + CComPtr pLocationCollection; + CComPtr pLocation; + + BSTR bstrLocationPath = NULL; + + *ppLocation = NULL; + *pFound = FALSE; + + hr = GetLocationCollection( pAdminMgr, + szConfigPath, + &pLocationCollection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + DWORD count; + DWORD i; + VARIANT varIndex; + VariantInit( &varIndex ); + + hr = pLocationCollection->get_Count( &count ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for( i = 0; i < count; i++ ) + { + varIndex.vt = VT_UI4; + varIndex.ulVal = i; + + hr = pLocationCollection->get_Item( varIndex, + &pLocation ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pLocation->get_Path( &bstrLocationPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( 0 == wcscmp ( szLocationPath, bstrLocationPath ) ) + { + *pFound = TRUE; + *ppLocation = pLocation.Detach(); + break; + } + + + pLocation.Release(); + + SysFreeString( bstrLocationPath ); + bstrLocationPath = NULL; + } + +exit: + + SysFreeString( bstrLocationPath ); + + return hr; +} + +HRESULT +GetSectionFromLocation( + IN IAppHostConfigLocation * pLocation, + IN CONST WCHAR * szSectionName, + OUT IAppHostElement ** ppSectionElement, + OUT BOOL * pFound + ) +{ + HRESULT hr = NOERROR; + + CComPtr pSectionElement; + + DWORD count; + DWORD i; + + VARIANT varIndex; + VariantInit( &varIndex ); + + BSTR bstrSectionName = NULL; + + *pFound = FALSE; + *ppSectionElement = NULL; + + hr = pLocation->get_Count( &count ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for( i = 0; i < count; i++ ) + { + varIndex.vt = VT_UI4; + varIndex.ulVal = i; + + + hr = pLocation->get_Item( varIndex, + &pSectionElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSectionElement->get_Name( &bstrSectionName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( 0 == wcscmp ( szSectionName, bstrSectionName ) ) + { + *pFound = TRUE; + *ppSectionElement = pSectionElement.Detach(); + break; + } + + pSectionElement.Release(); + + SysFreeString( bstrSectionName ); + bstrSectionName = NULL; + } + +exit: + + SysFreeString( bstrSectionName ); + + return hr; +} + + +HRESULT +GetAdminElement( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName, + OUT IAppHostElement ** pElement +) +{ + HRESULT hr = S_OK; + BSTR bstrConfigPath = NULL; + BSTR bstrElementName = NULL; + + bstrConfigPath = SysAllocString(szConfigPath); + bstrElementName = SysAllocString(szElementName); + + if (bstrConfigPath == NULL || bstrElementName == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrElementName, + bstrConfigPath, + pElement ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + if ( bstrElementName != NULL ) + { + SysFreeString(bstrElementName); + bstrElementName = NULL; + } + if ( bstrConfigPath != NULL ) + { + SysFreeString(bstrConfigPath); + bstrConfigPath = NULL; + } + + return hr; +} + + +HRESULT +ClearAdminElement( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName + ) +{ + HRESULT hr; + CComPtr pElement; + + hr = GetAdminElement( + pAdminMgr, + szConfigPath, + szElementName, + &pElement + ); + + if (FAILED(hr)) + { + if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + hr = S_OK; + } + else + { + DBGERROR_HR(hr); + } + + goto exit; + } + + hr = pElement->Clear(); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + + +HRESULT +ClearElementFromAllSites( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName + ) +{ + HRESULT hr; + CComPtr pSitesCollection; + CComPtr pSiteElement; + CComPtr pChildCollection; + ENUM_INDEX index; + BOOL found; + + // + // Enumerate the sites, remove the specified elements. + // + + hr = GetSitesCollection( + pAdminMgr, + szConfigPath, + &pSitesCollection + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + for (hr = FindFirstElement(pSitesCollection, &index, &pSiteElement) ; + SUCCEEDED(hr) ; + hr = FindNextElement(pSitesCollection, &index, &pSiteElement)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = pSiteElement->get_ChildElements(&pChildCollection); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (pChildCollection) + { + hr = ClearChildElementsByName( + pChildCollection, + szElementName, + &found + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + } + + pSiteElement.Release(); + } + +exit: + + return hr; + +} + + +HRESULT +ClearElementFromAllLocations( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName + ) +{ + HRESULT hr; + CComPtr pLocationCollection; + CComPtr pLocation; + CComPtr pChildCollection; + ENUM_INDEX index; + + // + // Enum the tags, remove the specified elements. + // + + hr = GetLocationCollection( + pAdminMgr, + szConfigPath, + &pLocationCollection + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + for (hr = FindFirstLocation(pLocationCollection, &index, &pLocation) ; + SUCCEEDED(hr) ; + hr = FindNextLocation(pLocationCollection, &index, &pLocation)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = ClearLocationElements(pLocation, szElementName); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + pLocation.Release(); + } + +exit: + + return hr; + +} + +HRESULT +ClearLocationElements( + IN IAppHostConfigLocation * pLocation, + IN CONST WCHAR * szElementName + ) +{ + HRESULT hr; + CComPtr pElement; + ENUM_INDEX index; + BOOL matched; + + for (hr = FindFirstLocationElement(pLocation, &index, &pElement) ; + SUCCEEDED(hr) ; + hr = FindNextLocationElement(pLocation, &index, &pElement)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = CompareElementName(pElement, szElementName, &matched); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (matched) + { + pElement->Clear(); + } + + pElement.Release(); + } + +exit: + + return hr; +} + +HRESULT +CompareElementName( + IN IAppHostElement * pElement, + IN CONST WCHAR * szNameToMatch, + OUT BOOL * pMatched + ) +{ + HRESULT hr; + BSTR bstrElementName = NULL; + + *pMatched = FALSE; // until proven otherwise + + hr = pElement->get_Name(&bstrElementName); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if( 0 == wcscmp ( szNameToMatch, bstrElementName ) ) + { + *pMatched = TRUE; + } + +exit: + + SysFreeString(bstrElementName); + return hr; +} + + +HRESULT +ClearChildElementsByName( + IN IAppHostChildElementCollection * pCollection, + IN CONST WCHAR * szElementName, + OUT BOOL * pFound + ) +{ + HRESULT hr; + CComPtr pElement; + ENUM_INDEX index; + BOOL matched; + + *pFound = FALSE; + + for (hr = FindFirstChildElement(pCollection, &index, &pElement) ; + SUCCEEDED(hr) ; + hr = FindNextChildElement(pCollection, &index, &pElement)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = CompareElementName(pElement, szElementName, &matched); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (matched) + { + hr = pElement->Clear(); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + *pFound = TRUE; + } + + pElement.Release(); + } + +exit: + + return hr; +} + + +HRESULT +GetSitesCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostElementCollection ** pSitesCollection + ) +{ + HRESULT hr; + CComPtr pSitesElement; + BSTR bstrConfigPath; + BSTR bstrSitesSectionName; + + bstrConfigPath = SysAllocString(szConfigPath); + bstrSitesSectionName = SysAllocString(L"system.applicationHost/sites"); + *pSitesCollection = NULL; + + if (bstrConfigPath == NULL || bstrSitesSectionName == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + // + // Chase down the sites collection. + // + + hr = pAdminMgr->GetAdminSection( bstrSitesSectionName, + bstrConfigPath, + &pSitesElement ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSitesElement->get_Collection(pSitesCollection); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString(bstrSitesSectionName); + SysFreeString(bstrConfigPath); + return hr; +} + + +HRESULT +GetLocationCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostConfigLocationCollection ** pLocationCollection + ) +{ + HRESULT hr; + BSTR bstrConfigPath; + CComPtr pConfigMgr; + CComPtr pConfigFile; + + bstrConfigPath = SysAllocString(szConfigPath); + *pLocationCollection = NULL; + + if (bstrConfigPath == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->get_ConfigManager(&pConfigMgr); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigMgr->GetConfigFile(bstrConfigPath, &pConfigFile); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigFile->get_Locations(pLocationCollection); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString(bstrConfigPath); + return hr; +} + + +HRESULT +FindFirstElement( + IN IAppHostElementCollection * pCollection, + OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + hr = pCollection->get_Count(&pIndex->Count); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + return hr; + } + + VariantInit(&pIndex->Index); + pIndex->Index.vt = VT_UI4; + pIndex->Index.ulVal = 0; + + return FindNextElement(pCollection, pIndex, pElement); +} + +HRESULT +FindNextElement( + IN IAppHostElementCollection * pCollection, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + *pElement = NULL; + + if (pIndex->Index.ulVal >= pIndex->Count) + { + return S_FALSE; + } + + hr = pCollection->get_Item(pIndex->Index, pElement); + + if (SUCCEEDED(hr)) + { + pIndex->Index.ulVal++; + } + + return hr; +} + +HRESULT +FindFirstChildElement( + IN IAppHostChildElementCollection * pCollection, + OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + hr = pCollection->get_Count(&pIndex->Count); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + return hr; + } + + VariantInit(&pIndex->Index); + pIndex->Index.vt = VT_UI4; + pIndex->Index.ulVal = 0; + + return FindNextChildElement(pCollection, pIndex, pElement); +} + +HRESULT +FindNextChildElement( + IN IAppHostChildElementCollection * pCollection, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + *pElement = NULL; + + if (pIndex->Index.ulVal >= pIndex->Count) + { + return S_FALSE; + } + + hr = pCollection->get_Item(pIndex->Index, pElement); + + if (SUCCEEDED(hr)) + { + pIndex->Index.ulVal++; + } + + return hr; +} + +HRESULT +FindFirstLocation( + IN IAppHostConfigLocationCollection * pCollection, + OUT ENUM_INDEX * pIndex, + OUT IAppHostConfigLocation ** pLocation + ) +{ + HRESULT hr; + + hr = pCollection->get_Count(&pIndex->Count); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + return hr; + } + + VariantInit(&pIndex->Index); + pIndex->Index.vt = VT_UI4; + pIndex->Index.ulVal = 0; + + return FindNextLocation(pCollection, pIndex, pLocation); +} + +HRESULT +FindNextLocation( + IN IAppHostConfigLocationCollection * pCollection, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostConfigLocation ** pLocation + ) +{ + HRESULT hr; + + *pLocation = NULL; + + if (pIndex->Index.ulVal >= pIndex->Count) + { + return S_FALSE; + } + + hr = pCollection->get_Item(pIndex->Index, pLocation); + + if (SUCCEEDED(hr)) + { + pIndex->Index.ulVal++; + } + + return hr; +} + +HRESULT +FindFirstLocationElement( + IN IAppHostConfigLocation * pLocation, + OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + hr = pLocation->get_Count(&pIndex->Count); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + return hr; + } + + VariantInit(&pIndex->Index); + pIndex->Index.vt = VT_UI4; + pIndex->Index.ulVal = 0; + + return FindNextLocationElement(pLocation, pIndex, pElement); +} + +HRESULT +FindNextLocationElement( + IN IAppHostConfigLocation * pLocation, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + *pElement = NULL; + + if (pIndex->Index.ulVal >= pIndex->Count) + { + return S_FALSE; + } + + hr = pLocation->get_Item(pIndex->Index, pElement); + + if (SUCCEEDED(hr)) + { + pIndex->Index.ulVal++; + } + + return hr; +} + +HRESULT +GetSharedConfigEnabled( + BOOL * pfIsSharedConfig +) +/*++ + +Routine Description: + Search the configuration for the shared configuration property. + +Arguments: + + pfIsSharedConfig - true if shared configuration is enabled + +Return Value: + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + IAppHostAdminManager *pAdminManager = NULL; + + BSTR bstrSectionName = NULL; + BSTR bstrConfigPath = NULL; + + IAppHostElement * pConfigRedirSection = NULL; + + + bstrSectionName = SysAllocString( L"configurationRedirection" ); + + if ( bstrSectionName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + bstrConfigPath = SysAllocString( L"MACHINE/REDIRECTION" ); + if ( bstrConfigPath == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( CLSID_AppHostAdminManager, + NULL, + CLSCTX_INPROC_SERVER, + IID_IAppHostAdminManager, + (VOID **)&pAdminManager ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminManager->GetAdminSection( bstrSectionName, + bstrConfigPath, + &pConfigRedirSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetElementBoolProperty( pConfigRedirSection, + L"enabled", + pfIsSharedConfig ); + + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pConfigRedirSection->Release(); + pConfigRedirSection = NULL; + + +exit: + + // + // dump config exception to setup log file (if available) + // + + if ( pConfigRedirSection != NULL ) + { + pConfigRedirSection->Release(); + } + + if ( pAdminManager != NULL ) + { + pAdminManager->Release(); + } + + if ( bstrConfigPath != NULL ) + { + SysFreeString( bstrConfigPath ); + } + + if ( bstrSectionName != NULL ) + { + SysFreeString( bstrSectionName ); + } + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx new file mode 100644 index 0000000000..26e601fac4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx @@ -0,0 +1,482 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#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; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx new file mode 100644 index 0000000000..a856b997f1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx @@ -0,0 +1,247 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +static const CHAR* s_rgchMonths[] = { + "Jan", "Feb", "Mar", "Apr", + "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" +}; + +// Custom hash table for make_month() for mapping "Apr" to 4 +static const CHAR MonthIndexTable[64] = { + -1,'A', 2, 12, -1, -1, -1, 8, // A to G + -1, -1, -1, -1, 7, -1,'N', -1, // F to O + 9, -1,'R', -1, 10, -1, 11, -1, // P to W + -1, 5, -1, -1, -1, -1, -1, -1, // X to Z + -1,'A', 2, 12, -1, -1, -1, 8, // a to g + -1, -1, -1, -1, 7, -1,'N', -1, // f to o + 9, -1,'R', -1, 10, -1, 11, -1, // p to w + -1, 5, -1, -1, -1, -1, -1, -1 // x to z +}; + +static const BYTE TensDigit[10] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 }; + +WORD +iis_2atoi( + __in_ecount(2) PCHAR s + ) +/*++ + + Converts a 2 character string to integer + + Arguments: + s String to convert + + Returns: + numeric equivalent, 0 on failure. +--*/ +{ + + DWORD tens = s[0] - '0'; + DWORD ones = s[1] - '0'; + + if ( (tens <= 9) && (ones <= 9) ) { + return((WORD)(TensDigit[tens] + ones)); + } + return(0); +} + +WORD +make_month( + __in_ecount(3) PCHAR s + ) +{ + UCHAR monthIndex; + UCHAR c; + LPCSTR monthString; + + // + // use the third character as the index + // + + c = (s[2] - 0x40) & 0x3F; + + monthIndex = MonthIndexTable[c]; + + if ( monthIndex < 13 ) { + goto verify; + } + + // + // ok, we need to look at the second character + // + + if ( monthIndex == 'N' ) { + + // + // we got an N which we need to resolve further + // + + // + // if s[1] is 'u' then Jun, if 'a' then Jan + // + + if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) { + monthIndex = 1; + } else { + monthIndex = 6; + } + + } else if ( monthIndex == 'R' ) { + + // + // if s[1] is 'a' then March, if 'p' then April + // + + if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) { + monthIndex = 3; + } else { + monthIndex = 4; + } + } else { + goto error_exit; + } + +verify: + + monthString = s_rgchMonths[monthIndex-1]; + + if ( (s[0] == monthString[0]) && + (s[1] == monthString[1]) && + (s[2] == monthString[2]) ) { + + return(monthIndex); + + } else if ( (toupper(s[0]) == monthString[0]) && + (tolower(s[1]) == monthString[1]) && + (tolower(s[2]) == monthString[2]) ) { + + return monthIndex; + } + +error_exit: + return(0); + +} // make_month + +BOOL +StringTimeToFileTime( + IN const CHAR * pszTime, + OUT ULONGLONG * pulTime + ) +/*++ + + Converts a string representation of a GMT time (three different + varieties) to an NT representation of a file time. + + We handle the following variations: + + Sun, 06 Nov 1994 08:49:37 GMT (RFC 822 updated by RFC 1123) + Sunday, 06-Nov-94 08:49:37 GMT (RFC 850) + Sun Nov 6 08:49:37 1994 (ANSI C's asctime() format + + Arguments: + pszTime String representation of time field + pliTime large integer containing the time in NT format. + + Returns: + TRUE on success and FALSE on failure. + + History: + + Johnl 24-Jan-1995 Modified from WWW library + +--*/ +{ + + CHAR * s; + SYSTEMTIME st; + + if (pszTime == NULL) { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + st.wMilliseconds = 0; + + if ((s = (CHAR*) strchr(pszTime, ','))) { + + DWORD len; + + // + // Thursday, 10-Jun-93 01:29:59 GMT + // or: Thu, 10 Jan 1993 01:29:59 GMT */ + // + + s++; + + while (*s && *s==' ') s++; + len = (DWORD)strlen(s); + + if (len < 18) { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if ( *(s+2) == '-' ) { /* First format */ + + st.wDay = (WORD) atoi(s); + st.wMonth = (WORD) make_month(s+3); + st.wYear = (WORD) atoi(s+7); + st.wHour = (WORD) atoi(s+10); + st.wMinute = (WORD) atoi(s+13); + st.wSecond = (WORD) atoi(s+16); + + } else { /* Second format */ + + if (len < 20) { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + st.wDay = iis_2atoi(s); + st.wMonth = make_month(s+3); + st.wYear = iis_2atoi(s+7) * 100 + iis_2atoi(s+9); + st.wHour = iis_2atoi(s+12); + st.wMinute = iis_2atoi(s+15); + st.wSecond = iis_2atoi(s+18); + + } + } else { /* Try the other format: Wed Jun 9 01:29:59 1993 GMT */ + + s = (CHAR *) pszTime; + while (*s && *s==' ') s++; + + if ((int)strlen(s) < 24) { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + st.wDay = (WORD) atoi(s+8); + st.wMonth = (WORD) make_month(s+4); + st.wYear = (WORD) atoi(s+20); + st.wHour = (WORD) atoi(s+11); + st.wMinute = (WORD) atoi(s+14); + st.wSecond = (WORD) atoi(s+17); + } + + // + // Adjust for dates with only two digits + // + + if ( st.wYear < 1000 ) { + if ( st.wYear < 50 ) { + st.wYear += 2000; + } else { + st.wYear += 1900; + } + } + + if (!SystemTimeToFileTime(&st, (FILETIME *)pulTime)) { + return FALSE; + } + return(TRUE); +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx new file mode 100644 index 0000000000..26eacdb244 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx @@ -0,0 +1,480 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +//#include +#include +//# include + +#include + +// +// 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 = (DWORD)(::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. + + History: + MuraliK 11-30-94 +--*/ +{ + 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. + + History: + MuraliK 20-Nov-1996 +--*/ +{ + 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; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx new file mode 100644 index 0000000000..e6972534bb --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx @@ -0,0 +1,414 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +//#include +#include +//# include + +#include + +// +// 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 = (DWORD)(::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. + + History: + MuraliK 20-Nov-1996 +--*/ +{ + 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; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx new file mode 100644 index 0000000000..48b41fdd1c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx @@ -0,0 +1,890 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" +#include "normalize.h" +#include "stringa.h" + +BOOL g_fEnableNonUTF8; +BOOL g_fEnableDBCS; +BOOL g_fIsSystemDBCS; +static BOOL g_fFavorDBCS; + +#ifndef STACK_STRA +#define STACK_STRA(name, size) CHAR __ach##name[size]; \ + STRA name(__ach##name, sizeof(__ach##name) / sizeof(CHAR)) +#endif + +HRESULT +InitializeNormalizeUrl( + VOID +) +{ + HKEY hKey; + DWORD dwType; + DWORD dwData; + DWORD cbData; + WORD wPrimaryLangID; + + // + // Read the registry settings on how to handle URLs + // + + g_fEnableNonUTF8 = TRUE; + g_fEnableDBCS = FALSE; + g_fFavorDBCS = FALSE; + + if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, + L"System\\CurrentControlSet\\Services\\http\\Parameters", + 0, + KEY_READ, + &hKey ) == ERROR_SUCCESS ) + { + cbData = sizeof( dwData ); + if ( RegQueryValueEx( hKey, + L"EnableNonUTF8", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_fEnableNonUTF8 = !!dwData; + } + + if ( g_fEnableNonUTF8 ) + { + cbData = sizeof( dwData ); + + if ( RegQueryValueEx( hKey, + L"EnableDBCS", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_fEnableDBCS = !!dwData; + } + } + else + { + g_fEnableDBCS = FALSE; + } + + if ( g_fEnableDBCS ) + { + cbData = sizeof( dwData ); + + if ( RegQueryValueEx( hKey, + L"FavorDBCS", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_fFavorDBCS = !!dwData; + } + } + else + { + g_fFavorDBCS = FALSE; + } + + RegCloseKey( hKey ); + } + + + wPrimaryLangID = PRIMARYLANGID( GetSystemDefaultLangID() ); + + g_fIsSystemDBCS = ( wPrimaryLangID == LANG_JAPANESE || + wPrimaryLangID == LANG_CHINESE || + wPrimaryLangID == LANG_KOREAN ); + + return NO_ERROR; +} + +// +// Private constants. +// + +#define ACTION_NOTHING 0x00000000 +#define ACTION_EMIT_CH 0x00010000 +#define ACTION_EMIT_DOT_CH 0x00020000 +#define ACTION_EMIT_DOT_DOT_CH 0x00030000 +#define ACTION_BACKUP 0x00040000 +#define ACTION_MASK 0xFFFF0000 + + +// +// Private globals. +// + +INT p_StateTable[16] = + { + // state 0 + 0 , // other + 0 , // "." + 4 , // EOS + 1 , // "\" + + // state 1 + 0 , // other + 2 , // "." + 4 , // EOS + 1 , // "\" + + // state 2 + 0 , // other + 3 , // "." + 4 , // EOS + 1 , // "\" + + // state 3 + 0 , // other + 0 , // "." + 4 , // EOS + 1 // "\" + }; + + + +INT p_ActionTable[16] = + { + // state 0 + ACTION_EMIT_CH, // other + ACTION_EMIT_CH, // "." + ACTION_EMIT_CH, // EOS + ACTION_EMIT_CH, // "\" + + // state 1 + ACTION_EMIT_CH, // other + ACTION_NOTHING, // "." + ACTION_EMIT_CH, // EOS + ACTION_NOTHING, // "\" + + // state 2 + ACTION_EMIT_DOT_CH, // other + ACTION_NOTHING, // "." + ACTION_EMIT_CH, // EOS + ACTION_NOTHING, // "\" + + // state 3 + ACTION_EMIT_DOT_DOT_CH, // other + ACTION_EMIT_DOT_DOT_CH, // "." + ACTION_BACKUP, // EOS + ACTION_BACKUP // "\" + }; + +// since max states = 4, we calculat the index by multiplying with 4. +# define IndexFromState( st) ( (st) * 4) + + +// the following table provides the index for various ISA Latin1 characters +// in the incoming URL. +// It assumes that the URL is ISO Latin1 == ASCII +INT p_rgIndexForChar[] = { + + 2, // null char + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 thru 10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 11 thru 20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21 thru 30 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 31 thru 40 + 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, // 41 thru 50 46 = '.' 47 = '/' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 51 thru 60 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 61 thru 70 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 71 thru 80 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 81 thru 90 + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, // 91 thru 100 92 = '\\' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 101 thru 110 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 111 thru 120 + 0, 0, 0, 0, 0, 0, 0, 0 // 121 thru 128 +}; + +#define IS_UTF8_TRAILBYTE(ch) (((ch) & 0xc0) == 0x80) + + +/******************************************************************* + + NAME: IsUTF8URL + + ENTRY: pszPath - The path to sanitize. + + HISTORY: + atsusk 06-Jan-1998 Created. + +********************************************************************/ + +BOOL IsUTF8URL(__in LPSTR pszPath) +{ + CHAR ch; + + if ( g_fFavorDBCS ) + { + return ( MultiByteToWideChar( CP_ACP, + MB_ERR_INVALID_CHARS, + pszPath, + -1, + NULL, + 0) == 0); + } + + while (ch = *pszPath++) { + + if (ch & 0x80) { + wchar_t wch; + int iLen; + BOOL bDefault = FALSE; + char chTrail1; + char chTrail2; + + chTrail1 = *pszPath++; + if (chTrail1) { + chTrail2 = *pszPath; + } else { + chTrail2 = 0; + } + + if ( ((ch & 0xF0) == 0xE0) && + IS_UTF8_TRAILBYTE(chTrail1) && + IS_UTF8_TRAILBYTE(chTrail2) ) { + + // handle three byte case + // 1110xxxx 10xxxxxx 10xxxxxx + wch = (wchar_t) (((ch & 0x0f) << 12) | + ((chTrail1 & 0x3f) << 6) | + (chTrail2 & 0x3f)); + pszPath++; + + } else + if ( ((ch & 0xE0) == 0xC0) && + IS_UTF8_TRAILBYTE(chTrail1) ) { + + // handle two byte case + // 110xxxxx 10xxxxxx + + wch = (wchar_t) (((ch & 0x1f) << 6) | (chTrail1 & 0x3f)); + + } else + return FALSE; + + iLen = WideCharToMultiByte( CP_ACP, + WC_NO_BEST_FIT_CHARS, + &wch, + 1, + NULL, + 0, + NULL, + &bDefault ); + + if (bDefault == TRUE || iLen == 0 || iLen > 2) + return FALSE; + } + } + + return TRUE; +} // IsUTF8URL() + + +/******************************************************************* + + NAME: CanonURL + + SYNOPSIS: Sanitizes a path by removing bogus path elements. + + As expected, "/./" entries are simply removed, and + "/../" entries are removed along with the previous + path element. + + To maintain compatibility with URL path semantics + additional transformations are required. All backward + slashes "\\" are converted to forward slashes. Any + repeated forward slashes (such as "///") are mapped to + single backslashes. + + A state table (see the p_StateTable global at the + beginning of this file) is used to perform most of + the transformations. The table's rows are indexed + by current state, and the columns are indexed by + the current character's "class" (either slash, dot, + NULL, or other). Each entry in the table consists + of the new state tagged with an action to perform. + See the ACTION_* constants for the valid action + codes. + + ENTRY: pszPath - The path to sanitize. + fIsDBCSLocale - Indicates the server is in a + locale that uses DBCS. + + HISTORY: + KeithMo 07-Sep-1994 Created. + MuraliK 28-Apr-1995 Adopted this for symbolic paths + +********************************************************************/ +INT +CanonURL( + __inout LPSTR pszPath, + BOOL fIsDBCSLocale + ) +{ + UCHAR * pszSrc; + UCHAR * pszDest; + DWORD ch; + INT index; + BOOL fDBCS = FALSE; + DWORD cchMultiByte = 0; + + DBG_ASSERT( pszPath != NULL ); + + // + // Always look for UTF8 except when DBCS characters are detected + // + BOOL fScanForUTF8 = IsUTF8URL(pszPath); + + // If fScanForUTF8 is true, this URL is UTF8. don't recognize DBCS. + if (fIsDBCSLocale && fScanForUTF8) { + fIsDBCSLocale = FALSE; + } + + // + // Start our scan at the first character + // + + pszSrc = pszDest = (UCHAR *) pszPath; + + // + // State 0 is the initial state. + // + index = 0; // State = 0 + + // + // Loop until we enter state 4 (the final, accepting state). + // + + do { + + // + // Grab the next character from the path and compute its + // next state. While we're at it, map any forward + // slashes to backward slashes. + // + + index = IndexFromState( p_StateTable[index]); // 4 = # states + ch = (DWORD ) *pszSrc++; + + // + // If this is a DBCS trailing byte - skip it + // + + if ( !fIsDBCSLocale ) + { + index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]); + } + else + { + if ( fDBCS ) + { + // + // If this is a 0 terminator, we need to set next + // state accordingly + // + + if ( ch == 0 ) + { + index += p_rgIndexForChar[ ch ]; + } + + // + // fDBCS == TRUE means this byte was a trail byte. + // index is implicitly set to zero. + // + fDBCS = FALSE; + } + else + { + index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]); + + if ( IsDBCSLeadByte( (UCHAR)ch ) ) + { + // + // This is a lead byte, so the next is a trail. + // + fDBCS = TRUE; + } + } + } + + // + // Interesting UTF8 characters always have the top bit set + // + + if ( (ch & 0x80) && fScanForUTF8 ) + { + wchar_t wch; + UCHAR mbstr[2]; + + // + // This is a UTF8 character, convert it here. + // index is implicitly set to zero. + // + if ( cchMultiByte < 2 ) + { + char chTrail1; + char chTrail2; + + chTrail1 = *pszSrc; + if (chTrail1) { + chTrail2 = *(pszSrc+1); + } else { + chTrail2 = 0; + } + wch = 0; + + if ((ch & 0xf0) == 0xe0) + { + // handle three byte case + // 1110xxxx 10xxxxxx 10xxxxxx + + wch = (wchar_t) (((ch & 0x0f) << 12) | + ((chTrail1 & 0x3f) << 6) | + (chTrail2 & 0x3f)); + + cchMultiByte = WideCharToMultiByte( CP_ACP, + WC_NO_BEST_FIT_CHARS, + &wch, + 1, + (LPSTR) mbstr, + 2, + NULL, + NULL ); + + ch = mbstr[0]; + pszSrc += (3 - cchMultiByte); + + // WinSE 12843: Security Fix, Index should be updated for this character + index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]); + + } else if ((ch & 0xe0) == 0xc0) + { + // handle two byte case + // 110xxxxx 10xxxxxx + + wch = (wchar_t) (((ch & 0x1f) << 6) | (chTrail1 & 0x3f)); + + cchMultiByte = WideCharToMultiByte( CP_ACP, + WC_NO_BEST_FIT_CHARS, + &wch, + 1, + (LPSTR) mbstr, + 2, + NULL, + NULL ); + + ch = mbstr[0]; + pszSrc += (2 - cchMultiByte); + + // WinSE 12843: Security Fix, Index should be updated for this character + index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]); + } + + } else { + // + // get ready to emit 2nd byte of converted character + // + ch = mbstr[1]; + cchMultiByte = 0; + } + } + + + // + // Perform the action associated with the state. + // + + switch( p_ActionTable[index] ) + { + case ACTION_EMIT_DOT_DOT_CH : + *pszDest++ = '.'; + /* fall through */ + + case ACTION_EMIT_DOT_CH : + *pszDest++ = '.'; + /* fall through */ + + case ACTION_EMIT_CH : + *pszDest++ = (CHAR ) ch; + /* fall through */ + + case ACTION_NOTHING : + break; + + case ACTION_BACKUP : + if( (pszDest > ( (UCHAR *) pszPath + 1 ) ) && (*pszPath == '/')) + { + pszDest--; + DBG_ASSERT( *pszDest == '/' ); + + *pszDest = '\0'; + pszDest = (UCHAR *) strrchr( pszPath, '/') + 1; + } + + *pszDest = '\0'; + break; + + default : + DBG_ASSERT( !"Invalid action code in state table!" ); + index = IndexFromState(0) + 2; // move to invalid state + DBG_ASSERT( p_StateTable[index] == 4); + *pszDest++ = '\0'; + break; + } + + } while( p_StateTable[index] != 4 ); + + // + // point to terminating nul + // only do the check if we aren't about to go outside of the number + // of elements in the table. + // + if ( ( index < ( sizeof(p_ActionTable) / sizeof(p_ActionTable[0]) ) ) + && p_ActionTable[index] == ACTION_EMIT_CH ) + { + pszDest--; + } + + DBG_ASSERT(*pszDest == '\0' && pszDest > (UCHAR*) pszPath); + + return (INT)DIFF(pszDest - (UCHAR*)pszPath); +} // CanonURL() + + + +HRESULT +NormalizeUrl( + __inout LPSTR pszStart + ) +/*++ + +Routine Description: + + Normalize URL + +Arguments: + + strUrl - URL to be updated to a canonical URI + +Return value: + + TRUE if no error, otherwise FALSE + +--*/ +{ + CHAR * pchParams; + LPSTR pszSlash; + LPSTR pszURL; + LPSTR pszValue; + STACK_STRA( strChgUrl, MAX_PATH ); + HRESULT hr; + DWORD cchInput; + + if ( pszStart == NULL ) + { + return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + + cchInput = (DWORD)strlen( pszStart ); + + if ( *pszStart != '/' ) + { + // + // assume HTTP URL, skip protocol & host name by + // searching for 1st '/' following "//" + // + // We handle this information as a "Host:" header. + // It will be overwritten by the real header if it is + // present. + // + // We do not check for a match in this case. + // + + if ( (pszSlash = strchr( pszStart, '/' )) && pszSlash[1] == '/' ) + { + pszSlash += 2; + if ( pszURL = strchr( pszSlash, '/' ) ) + { + // + // update pointer to URL to point to the 1st slash + // following host name + // + + pszValue = pszURL; + } + else + { + // + // if no single slash following host name + // consider the URL to be empty. + // + + pszValue = pszSlash + strlen( pszSlash ); + } + + memmove( pszStart, pszValue, strlen(pszValue)+1 ); + } + + // + // if no double slash, this is not a fully qualified URL + // and we leave it alone. + // + } + + // + // Check for a question mark which indicates this URL contains some + // parameters and break the two apart if found + // + + if ( (pchParams = strchr( pszStart, '?' )) ) + { + *pchParams = '\0'; + } + + // + // Unescape wants a STR ( sigh ) + // + + hr = strChgUrl.Copy( (CHAR*)pszStart ); + + if ( FAILED( hr ) ) + { + return hr; + } + + strChgUrl.Unescape(); + + hr = StringCchCopyNA( pszStart, cchInput + 1, strChgUrl.QueryStr(), cchInput ); + if ( FAILED( hr ) ) + { + return hr; + } + + // + // Canonicalize the URL + // + + CanonURL( pszStart, g_fIsSystemDBCS ); + + return NO_ERROR; +} + + + + +HRESULT +NormalizeUrlOld( + __inout LPSTR pszUrl +) +/*++ + +Routine Description: + + NormalizeUrl wrapper (used by ISAPI filter and extension support functions) + +Parameters: + + pszUrl - On entry, the URL to be normalized + On return, the normalized URL + (size of normalized URL is always <= not normalized URL) + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = NO_ERROR; + + if ( pszUrl ) + { + STACK_BUFFER( buffUrlOutput, MAX_PATH ); + STACK_STRA( strUrlA, MAX_PATH ); + LPWSTR szQueryString; + DWORD cchData; + DWORD cbOutput; + + cchData = (DWORD)strlen( pszUrl ); + + // + // Prepare the Output string + // + + if ( !buffUrlOutput.Resize( ( cchData + 1 ) *sizeof( WCHAR ) ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + // + // Normalize it + // + + hr = UlCleanAndCopyUrl( + pszUrl, + cchData, + &cbOutput, + (WCHAR *) buffUrlOutput.QueryPtr(), + &szQueryString + ); + + if ( FAILED( hr ) ) + { + return hr; + } + + // + // Terminate the string at the query so that the + // query string doesn't appear in the output. IIS 5 + // truncated in this way. + // + + if ( szQueryString != NULL ) + { + ((WCHAR *) buffUrlOutput.QueryPtr())[ cbOutput - wcslen( szQueryString )] = 0; + } + + // + // Write the normalized URL over the input data + // + + hr = strUrlA.CopyW( (WCHAR *) buffUrlOutput.QueryPtr() ); + + if ( FAILED( hr ) ) + { + return hr; + } + + // + // Normalized string will never be longer than the original one + // + + DBG_ASSERT( strUrlA.QueryCCH() <= cchData ); + + hr = StringCchCopyA( pszUrl, cchData + 1, strUrlA.QueryStr() ); + if ( FAILED( hr ) ) + { + return hr; + } + + hr = NO_ERROR; + } + else + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + return hr; +} + + +HRESULT +NormalizeUrlW( + __inout LPWSTR pszUrl +) +/*++ + +Routine Description: + + unicode version of NormalizeUrl wrapper (used by ISAPI filter and extension support functions) + +Parameters: + + pszUrl - On entry, the URL to be normalized + On return, the normalized URL + (size of normalized URL is always <= not normalized URL) + +Return Value: + + HRESULT + +--*/ +{ + + HRESULT hr = NO_ERROR; + + if ( pszUrl ) + { + STACK_BUFFER( buffUrlOutput, MAX_PATH ); + STACK_STRA( strUrlA, MAX_PATH ); + LPWSTR szQueryString; + DWORD cchData; + DWORD cbOutput; + + cchData = (DWORD)wcslen( pszUrl ); + + hr = strUrlA.CopyWToUTF8Escaped( pszUrl ); + + if ( FAILED( hr ) ) + { + return hr; + } + + // + // Prepare Output string + // + + if ( !buffUrlOutput.Resize( ( cchData + 1 ) *sizeof( WCHAR ) ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + // + // Normalize it + // + + hr = UlCleanAndCopyUrl( + strUrlA.QueryStr(), + strUrlA.QueryCB(), + &cbOutput, + (WCHAR *) buffUrlOutput.QueryPtr(), + &szQueryString + ); + + if ( FAILED( hr ) ) + { + return hr; + } + + + // + // Terminate the string at the query so that the + // query string doesn't appear in the output. IIS 5 + // truncated in this way. + // + + if ( szQueryString != NULL ) + { + ((WCHAR *) buffUrlOutput.QueryPtr())[ cbOutput - wcslen( szQueryString )] = 0; + } + + // + // normalized string will never be longer than the original one + // + + DBG_ASSERT( cbOutput <= cchData * sizeof( WCHAR ) ); + + // + // Write the normalized URL over the input data + // + + hr = StringCchCopyW( pszUrl, cchData+1, (WCHAR *) buffUrlOutput.QueryPtr() ); + if ( FAILED( hr ) ) + { + return hr; + } + + hr = NO_ERROR; + } + else + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config new file mode 100644 index 0000000000..21d9344493 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h new file mode 100644 index 0000000000..8f578b2ad3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include +#include +#pragma warning( disable:4127 ) +#include +#include +#include + +#include "macros.h" +#include "stringu.h" +#include "stringa.h" +#include "dbgutil.h" +#include "ntassert.h" +#include "ahutil.h" +#include "acache.h" +#include "base64.hxx" diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp new file mode 100644 index 0000000000..6380535473 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp @@ -0,0 +1,1767 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +STRA::STRA( + VOID +) : m_cchLen( 0 ) +{ + *( QueryStr() ) = '\0'; +} + +STRA::STRA( + __inout_ecount(cchInit) CHAR* pbInit, + __in DWORD cchInit +) : m_Buff( pbInit, cchInit * sizeof( CHAR ) ), + m_cchLen(0) +/*++ + Description: + + Used by STACK_STRA. Initially populates underlying buffer with pbInit. + + pbInit is not freed. + + Arguments: + + pbInit - initial memory to use + cchInit - count, in characters, of pbInit + + Returns: + + None. + +--*/ +{ + _ASSERTE( NULL != pbInit ); + _ASSERTE( cchInit > 0 ); + _ASSERTE( pbInit[0] == '\0' ); +} + +BOOL +STRA::IsEmpty( + VOID +) const +{ + return ( m_cchLen == 0 ); +} + +BOOL +STRA::Equals( + __in PCSTR pszRhs, + __in BOOL fIgnoreCase /*= FALSE*/ +) const +{ + _ASSERTE( NULL != pszRhs ); + + if( fIgnoreCase ) + { + return ( 0 == _stricmp( QueryStr(), pszRhs ) ); + } + + return ( 0 == strcmp( QueryStr(), pszRhs ) ); +} + +BOOL +STRA::Equals( + __in const STRA * pstrRhs, + __in BOOL fIgnoreCase /*= FALSE*/ +) const +{ + _ASSERTE( NULL != pstrRhs ); + return Equals( pstrRhs->QueryStr(), fIgnoreCase ); +} + +BOOL +STRA::Equals( + __in const STRA & strRhs, + __in BOOL fIgnoreCase /*= FALSE*/ +) const +{ + return Equals( strRhs.QueryStr(), fIgnoreCase ); +} + +DWORD +STRA::QueryCB( + VOID +) const +// +// Returns the number of bytes in the string excluding the terminating NULL +// +{ + return m_cchLen * sizeof( CHAR ); +} + +DWORD +STRA::QueryCCH( + VOID +) const +// +// Returns the number of characters in the string excluding the terminating NULL +// +{ + return m_cchLen; +} + +DWORD +STRA::QuerySizeCCH( + VOID +) const +// +// Returns size of the underlying storage buffer, in characters +// +{ + return m_Buff.QuerySize() / sizeof( CHAR ); +} + +DWORD +STRA::QuerySize( + VOID +) const +// +// Returns the size of the storage buffer in bytes +// +{ + return m_Buff.QuerySize(); +} + +__nullterminated +__bcount(this->m_cchLen) +CHAR * +STRA::QueryStr( + VOID +) const +// +// Return the string buffer +// +{ + return m_Buff.QueryPtr(); +} + +VOID +STRA::Reset( + VOID +) +// +// Resets the internal string to be NULL string. Buffer remains cached. +// +{ + _ASSERTE( QueryStr() != NULL ); + *(QueryStr()) = '\0'; + m_cchLen = 0; +} + +HRESULT +STRA::Resize( + __in DWORD cchSize +) +{ + if( !m_Buff.Resize( cchSize * sizeof( CHAR ) ) ) + { + return E_OUTOFMEMORY; + } + + return S_OK; +} + +HRESULT +STRA::SyncWithBuffer( + VOID +) +// +// Recalculate the length of the string, etc. because we've modified +// the buffer directly. +// +{ + HRESULT hr; + size_t size; + hr = StringCchLengthA( QueryStr(), + QuerySizeCCH(), + &size ); + if ( SUCCEEDED( hr ) ) + { + m_cchLen = static_cast(size); + } + return hr; +} + +HRESULT +STRA::Copy( + __in PCSTR pszCopy +) +{ + HRESULT hr; + size_t cbLen; + hr = StringCbLengthA( pszCopy, + STRSAFE_MAX_CCH, + &cbLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return Copy( pszCopy, cbLen ); +} + + +HRESULT +STRA::Copy( + __in_ecount(cchLen) + PCSTR pszCopy, + __in SIZE_T cbLen +) +// +// Copy the contents of another string to this one +// +{ + _ASSERTE( cbLen <= MAXDWORD ); + + return AuxAppend( + pszCopy, + static_cast(cbLen), + 0 + ); +} + +HRESULT +STRA::Copy( + __in const STRA * pstrRhs +) +{ + _ASSERTE( pstrRhs != NULL ); + return Copy( pstrRhs->QueryStr(), pstrRhs->QueryCCH() ); +} + +HRESULT +STRA::Copy( + __in const STRA & strRhs +) +{ + return Copy( strRhs.QueryStr(), strRhs.QueryCCH() ); +} + +HRESULT +STRA::CopyW( + __in PCWSTR pszCopyW +) +{ + HRESULT hr; + size_t cchLen; + hr = StringCchLengthW( pszCopyW, + STRSAFE_MAX_CCH, + &cchLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return CopyW( pszCopyW, cchLen ); +} + +HRESULT +STRA::CopyWTruncate( + __in PCWSTR pszCopyWTruncate +) +{ + HRESULT hr; + size_t cchLen; + hr = StringCchLengthW( pszCopyWTruncate, + STRSAFE_MAX_CCH, + &cchLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return CopyWTruncate( pszCopyWTruncate, cchLen ); +} + +HRESULT +STRA::CopyWTruncate( + __in_ecount(cchLen) + PCWSTR pszCopyWTruncate, + __in SIZE_T cchLen +) +// +// The "Truncate" methods do not do proper conversion. They do a (CHAR) caste +// +{ + _ASSERTE( cchLen <= MAXDWORD ); + + return AuxAppendWTruncate( + pszCopyWTruncate, + static_cast(cchLen), + 0 + ); +} + +HRESULT +STRA::Append( + __in PCSTR pszAppend +) +{ + HRESULT hr; + size_t cbLen; + hr = StringCbLengthA( pszAppend, + STRSAFE_MAX_CCH, + &cbLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return Append( pszAppend, cbLen ); +} + +HRESULT +STRA::Append( + __in_ecount(cchLen) + PCSTR pszAppend, + __in SIZE_T cbLen +) +{ + _ASSERTE( cbLen <= MAXDWORD ); + if ( cbLen == 0 ) + { + return S_OK; + } + return AuxAppend( + pszAppend, + static_cast(cbLen), + QueryCB() + ); +} + +HRESULT +STRA::Append( + __in const STRA * pstrRhs +) +{ + _ASSERTE( pstrRhs != NULL ); + return Append( pstrRhs->QueryStr(), pstrRhs->QueryCCH() ); +} + +HRESULT +STRA::Append( + __in const STRA & strRhs +) +{ + return Append( strRhs.QueryStr(), strRhs.QueryCCH() ); +} + +HRESULT +STRA::AppendWTruncate( + __in PCWSTR pszAppendWTruncate +) +{ + HRESULT hr; + size_t cchLen; + hr = StringCchLengthW( pszAppendWTruncate, + STRSAFE_MAX_CCH, + &cchLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return AppendWTruncate( pszAppendWTruncate, cchLen ); +} + +HRESULT +STRA::AppendWTruncate( + __in_ecount(cchLen) + PCWSTR pszAppendWTruncate, + __in SIZE_T cchLen +) +// +// The "Truncate" methods do not do proper conversion. They do a (CHAR) caste +// +{ + _ASSERTE( cchLen <= MAXDWORD ); + if ( cchLen == 0 ) + { + return S_OK; + } + return AuxAppendWTruncate( + pszAppendWTruncate, + static_cast(cchLen), + QueryCB() + ); +} + +HRESULT +STRA::CopyToBuffer( + __out_bcount(*pcb) CHAR* pszBuffer, + __inout DWORD * pcb +) const +// +// Makes a copy of the stored string into the given buffer +// +{ + _ASSERTE( NULL != pszBuffer ); + _ASSERTE( NULL != pcb ); + + HRESULT hr = S_OK; + DWORD cbNeeded = QueryCB() + sizeof( CHAR ); + + if( *pcb < cbNeeded ) + { + hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ); + goto Finished; + } + + memcpy( pszBuffer, QueryStr(), cbNeeded ); + +Finished: + + *pcb = cbNeeded; + + return hr; +} + +HRESULT +STRA::SetLen( + __in DWORD cchLen +) +/*++ + * +Routine Description: + + Set the length of the string and null terminate, if there + is sufficient buffer already allocated. Will not reallocate. + +Arguments: + + cchLen - The number of characters in the new string. + +Return Value: + + HRESULT + +--*/ +{ + if( cchLen >= QuerySizeCCH() ) + { + return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + + *( QueryStr() + cchLen ) = '\0'; + m_cchLen = cchLen; + + return S_OK; +} + + +HRESULT +STRA::SafeSnprintf( + __in __format_string + PCSTR pszFormatString, + ... +) +/*++ + +Routine Description: + + Writes to a STRA, growing it as needed. It arbitrarily caps growth at 64k chars. + +Arguments: + + pszFormatString - printf format + ... - printf args + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + va_list argsList; + va_start( argsList, pszFormatString ); + + hr = SafeVsnprintf(pszFormatString, argsList); + + va_end( argsList ); + return hr; +} + +HRESULT +STRA::SafeVsnprintf( + __in __format_string + PCSTR pszFormatString, + va_list argsList +) +/*++ + +Routine Description: + + Writes to a STRA, growing it as needed. It arbitrarily caps growth at 64k chars. + +Arguments: + + pszFormatString - printf format + argsList - printf va_list + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + int cchOutput; + int cchNeeded; + + // + // Format the incoming message using vsnprintf() + // so that the overflows are captured + // + cchOutput = _vsnprintf_s( + QueryStr(), + QuerySizeCCH(), + QuerySizeCCH() - 1, + pszFormatString, + argsList + ); + + if( cchOutput == -1 ) + { + // + // Couldn't fit this in the original STRU size. + // + cchNeeded = _vscprintf( pszFormatString, argsList ); + if( cchNeeded > 64 * 1024 ) + { + // + // If we're trying to produce a string > 64k chars, then + // there is probably a problem + // + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + + // + // _vscprintf doesn't include terminating null character + // + cchNeeded++; + + hr = Resize( cchNeeded ); + if( FAILED( hr ) ) + { + goto Finished; + } + + cchOutput = _vsnprintf_s( + QueryStr(), + QuerySizeCCH(), + QuerySizeCCH() - 1, + pszFormatString, + argsList + ); + if( -1 == cchOutput ) + { + // + // This should never happen, cause we should already have correctly sized memory + // + _ASSERTE( FALSE ); + + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + } + + // + // always null terminate at the last WCHAR + // + QueryStr()[ QuerySizeCCH() - 1 ] = L'\0'; + + // + // we directly touched the buffer - therefore: + // + hr = SyncWithBuffer(); + if( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + if( FAILED( hr ) ) + { + Reset(); + } + + return hr; +} + +bool +FShouldEscapeUtf8( + BYTE ch + ) +{ + if ( ( ch >= 128 ) ) + { + return true; + } + + return false; +} + +bool +FShouldEscapeUrl( + BYTE ch + ) +{ + if ( ( ch >= 128 || + ch <= 32 || + ch == '<' || + ch == '>' || + ch == '%' || + ch == '?' || + ch == '#' ) && + !( ch == '\n' || ch == '\r' ) ) + { + return true; + } + + return false; +} + +HRESULT +STRA::Escape( + VOID +) +/*++ + +Routine Description: + + Escapes a STRA + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + return EscapeInternal( FShouldEscapeUrl ); +} + +HRESULT +STRA::EscapeUtf8( + VOID +) +/*++ + +Routine Description: + + Escapes the high-bit chars in a STRA. LWS, CR, LF & controls are untouched. + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + return EscapeInternal( FShouldEscapeUtf8 ); +} + + +HRESULT +STRA::EscapeInternal( + PFN_F_SHOULD_ESCAPE pfnFShouldEscape +) +/*++ + +Routine Description: + + Escapes a STRA according to the predicate function passed in + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + LPCSTR pch = QueryStr(); + __analysis_assume( pch != NULL ); + int i = 0; + BYTE ch; + HRESULT hr = S_OK; + BOOL fRet = FALSE; + SIZE_T NewSize = 0; + + // Set to true if any % escaping occurs + BOOL fEscapingDone = FALSE; + + // + // If there are any characters that need to be escaped we copy the entire string + // character by character into straTemp, escaping as we go, then at the end + // copy all of straTemp over. Don't modify InlineBuffer directly. + // + CHAR InlineBuffer[512]; + InlineBuffer[0] = '\0'; + STRA straTemp(InlineBuffer, sizeof(InlineBuffer)/sizeof(*InlineBuffer)); + + _ASSERTE( pch ); + + while (ch = pch[i]) + { + // + // Escape characters that are in the non-printable range + // but ignore CR and LF + // + + if ( pfnFShouldEscape( ch ) ) + { + if (FALSE == fEscapingDone) + { + // first character in the string that needed escaping + fEscapingDone = TRUE; + + // guess that the size needs to be larger than + // what we used to have times two + NewSize = QueryCCH() * 2; + if ( NewSize > MAXDWORD ) + { + hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + return hr; + } + + hr = straTemp.Resize( static_cast(NewSize) ); + + if (FAILED(hr)) + { + return hr; + } + + // Copy all of the previous buffer into buffTemp, only if it is not the first character: + + if ( i > 0) + { + hr = straTemp.Copy(QueryStr(), + i * sizeof(CHAR)); + if (FAILED(hr)) + { + return hr; + } + } + } + + // resize the temporary (if needed) with the slop of the entire buffer length + // this fixes constant reallocation if the entire string needs to be escaped + NewSize = QueryCCH() + 2 * sizeof(CHAR) + 1 * sizeof(CHAR); + if ( NewSize > MAXDWORD ) + { + hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + return hr; + } + + fRet = straTemp.m_Buff.Resize( NewSize ); + if ( !fRet ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } + + // + // Create the string to append for the current character + // + + CHAR chHex[3]; + chHex[0] = '%'; + + // + // Convert the low then the high character to hex + // + + UINT nLowDigit = (UINT)(ch % 16); + chHex[2] = TODIGIT( nLowDigit ); + + ch /= 16; + + UINT nHighDigit = (UINT)(ch % 16); + + chHex[1] = TODIGIT( nHighDigit ); + + // + // Actually append the converted character to the end of the temporary + // + hr = straTemp.Append(chHex, 3); + if (FAILED(hr)) + { + return hr; + } + } + else + { + // if no escaping done, no need to copy + if (fEscapingDone) + { + // if ANY escaping done, copy current character into new buffer + straTemp.Append(&pch[i], 1); + } + } + + // inspect the next character in the string + i++; + } + + if (fEscapingDone) + { + // the escaped string is now in straTemp + hr = Copy(straTemp); + } + + return hr; + +} // EscapeInternal() + +VOID +STRA::Unescape( + VOID +) +/*++ + +Routine Description: + + Unescapes a STRA + + Supported escape sequences are: + %uxxxx unescapes Unicode character xxxx into system codepage + %xx unescapes character xx + % without following hex digits is ignored + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + CHAR *pScan; + CHAR *pDest; + CHAR *pNextScan; + WCHAR wch; + DWORD dwLen; + BOOL fChanged = FALSE; + + // + // Now take care of any escape characters + // + pDest = pScan = strchr(QueryStr(), '%'); + + while (pScan) + { + if ((pScan[1] == 'u' || pScan[1] == 'U') && + SAFEIsXDigit(pScan[2]) && + SAFEIsXDigit(pScan[3]) && + SAFEIsXDigit(pScan[4]) && + SAFEIsXDigit(pScan[5])) + { + wch = TOHEX(pScan[2]) * 4096 + TOHEX(pScan[3]) * 256 + + TOHEX(pScan[4]) * 16 + TOHEX(pScan[5]); + + dwLen = WideCharToMultiByte(CP_ACP, + WC_NO_BEST_FIT_CHARS, + &wch, + 1, + (LPSTR) pDest, + 6, + NULL, + NULL); + + pDest += dwLen; + pScan += 6; + fChanged = TRUE; + } + else if (SAFEIsXDigit(pScan[1]) && SAFEIsXDigit(pScan[2])) + { + *pDest = TOHEX(pScan[1]) * 16 + TOHEX(pScan[2]); + + pDest ++; + pScan += 3; + fChanged = TRUE; + } + else // Not an escaped char, just a '%' + { + if (fChanged) + { + *pDest = *pScan; + } + + pDest++; + pScan++; + } + + // + // Copy all the information between this and the next escaped char + // + pNextScan = strchr(pScan, '%'); + + if (fChanged) // pScan!=pDest, so we have to copy the char's + { + if (!pNextScan) // That was the last '%' in the string + { + memmove(pDest, + pScan, + QueryCCH() - DIFF(pScan - QueryStr()) + 1); + } + else + { + // There is another '%', move intermediate chars + if ((dwLen = (DWORD)DIFF(pNextScan - pScan)) != 0) + { + memmove(pDest, + pScan, + dwLen); + pDest += dwLen; + } + } + } + + pScan = pNextScan; + } + + if (fChanged) + { + m_cchLen = (DWORD)strlen(QueryStr()); // for safety recalc the length + } + + return; +} + +HRESULT +STRA::CopyWToUTF8Unescaped( + __in LPCWSTR cpchStr +) +{ + return STRA::CopyWToUTF8Unescaped(cpchStr, (DWORD) wcslen(cpchStr)); +} + +HRESULT +STRA::CopyWToUTF8Unescaped( + __in_ecount(cch) + LPCWSTR cpchStr, + __in DWORD cch +) +{ + HRESULT hr = S_OK; + int iRet; + + if (cch == 0) + { + Reset(); + return S_OK; + } + + iRet = ConvertUnicodeToUTF8(cpchStr, + &m_Buff, + cch); + if (-1 == iRet) + { + // could not convert + hr = HRESULT_FROM_WIN32(GetLastError()); + goto Finished; + } + + m_cchLen = iRet; + + _ASSERTE(strlen(m_Buff.QueryPtr()) == m_cchLen); +Finished: + return hr; +} + +HRESULT +STRA::CopyWToUTF8Escaped( + __in LPCWSTR cpchStr +) +{ + return STRA::CopyWToUTF8Escaped(cpchStr, (DWORD) wcslen(cpchStr)); +} + +HRESULT +STRA::CopyWToUTF8Escaped( + __in_ecount(cch) + LPCWSTR cpchStr, + __in DWORD cch +) +{ + HRESULT hr = S_OK; + + hr = CopyWToUTF8Unescaped(cpchStr, cch); + if (FAILED(hr)) + { + goto Finished; + } + + hr = Escape(); + if (FAILED(hr)) + { + goto Finished; + } + + hr = S_OK; +Finished: + return hr; +} + +HRESULT +STRA::AuxAppend( + __in_ecount(cbLen) + LPCSTR pStr, + __in DWORD cbLen, + __in DWORD cbOffset +) +{ + _ASSERTE( NULL != pStr ); + _ASSERTE( cbOffset <= QueryCB() ); + + ULONGLONG cb64NewSize = (ULONGLONG)cbOffset + cbLen + sizeof( CHAR ); + if( cb64NewSize > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + + if( m_Buff.QuerySize() < cb64NewSize ) + { + if( !m_Buff.Resize( static_cast(cb64NewSize) ) ) + { + return E_OUTOFMEMORY; + } + } + + memcpy( reinterpret_cast(m_Buff.QueryPtr()) + cbOffset, pStr, cbLen ); + + m_cchLen = cbLen + cbOffset; + + *( QueryStr() + m_cchLen ) = '\0'; + + return S_OK; +} + +HRESULT +STRA::AuxAppendW( + __in_ecount(cchAppendW) + PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset, + __in UINT CodePage, + __in BOOL fFailIfNoTranslation, + __in DWORD dwFlags +) +{ + HRESULT hr = S_OK; + DWORD cbAvailable = 0; + DWORD cbRet = 0; + + // + // There are only two expect places to append + // + _ASSERTE( 0 == cbOffset || QueryCB() == cbOffset ); + + if ( cchAppendW == 0 ) + { + goto Finished; + } + + // + // start by assuming 1 char to 1 char will be enough space + // + if( !m_Buff.Resize( cbOffset + cchAppendW + sizeof( CHAR ) ) ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + cbAvailable = m_Buff.QuerySize() - cbOffset; + + cbRet = WideCharToMultiByte( + CodePage, + dwFlags, + pszAppendW, + cchAppendW, + QueryStr() + cbOffset, + cbAvailable, + NULL, + NULL + ); + if( 0 != cbRet ) + { + if(!m_Buff.Resize(cbOffset + cbRet + 1)) + { + hr = E_OUTOFMEMORY; + } + + // + // not zero --> success, so we're done + // + goto Finished; + } + + // + // We only know how to handle ERROR_INSUFFICIENT_BUFFER + // + hr = HRESULT_FROM_WIN32( GetLastError() ); + if( hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) ) + { + goto Finished; + } + + // + // Reset HResult because we need to get the number of bytes needed + // + hr = S_OK; + cbRet = WideCharToMultiByte( + CodePage, + dwFlags, + pszAppendW, + cchAppendW, + NULL, + 0, + NULL, + NULL + ); + if( 0 == cbRet ) + { + // + // no idea how we could ever reach here + // + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + + if( !m_Buff.Resize( cbOffset + cbRet + 1) ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + cbAvailable = m_Buff.QuerySize() - cbOffset; + + cbRet = WideCharToMultiByte( + CodePage, + dwFlags, + pszAppendW, + cchAppendW, + QueryStr() + cbOffset, + cbAvailable, + NULL, + NULL + ); + if( 0 == cbRet ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + +Finished: + + if( SUCCEEDED( hr ) && 0 != cbRet ) + { + m_cchLen = cbRet + cbOffset; + } + + // + // ensure we're still NULL terminated in the right spot + // (regardless of success or failure) + // + QueryStr()[m_cchLen] = '\0'; + + return hr; +} + +HRESULT +STRA::AuxAppendWTruncate( + __in_ecount(cchAppendW) + __in PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset +) +// +// Cheesey WCHAR --> CHAR conversion +// +{ + HRESULT hr = S_OK; + CHAR* pszBuffer; + + _ASSERTE( NULL != pszAppendW ); + _ASSERTE( 0 == cbOffset || cbOffset == QueryCB() ); + + if( !pszAppendW ) + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Finished; + } + + ULONGLONG cbNeeded = (ULONGLONG)cbOffset + cchAppendW + sizeof( CHAR ); + if( cbNeeded > MAXDWORD ) + { + hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + goto Finished; + } + + if( !m_Buff.Resize( static_cast(cbNeeded) ) ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + // + // Copy/convert the UNICODE string over (by making two bytes into one) + // + pszBuffer = QueryStr() + cbOffset; + for( DWORD i = 0; i < cchAppendW; i++ ) + { + pszBuffer[i] = static_cast(pszAppendW[i]); + } + + m_cchLen = cchAppendW + cbOffset; + *( QueryStr() + m_cchLen ) = '\0'; + +Finished: + + return hr; +} + +// static +int +STRA::ConvertUnicodeToCodePage( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __inout BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen, + __in UINT uCodePage +) +{ + _ASSERTE(NULL != pszSrcUnicodeString); + _ASSERTE(NULL != pbufDstAnsiString); + + BOOL bTemp; + int iStrLen = 0; + DWORD dwFlags; + + if (uCodePage == CP_ACP) + { + dwFlags = WC_NO_BEST_FIT_CHARS; + } + else + { + dwFlags = 0; + } + + iStrLen = WideCharToMultiByte(uCodePage, + dwFlags, + pszSrcUnicodeString, + dwStringLen, + (LPSTR)pbufDstAnsiString->QueryPtr(), + (int)pbufDstAnsiString->QuerySize(), + NULL, + NULL); + if ((iStrLen == 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { + iStrLen = WideCharToMultiByte(uCodePage, + dwFlags, + pszSrcUnicodeString, + dwStringLen, + NULL, + 0, + NULL, + NULL); + if (iStrLen != 0) { + // add one just for the extra NULL + bTemp = pbufDstAnsiString->Resize(iStrLen + 1); + if (!bTemp) + { + iStrLen = 0; + } + else + { + iStrLen = WideCharToMultiByte(uCodePage, + dwFlags, + pszSrcUnicodeString, + dwStringLen, + (LPSTR)pbufDstAnsiString->QueryPtr(), + (int)pbufDstAnsiString->QuerySize(), + NULL, + NULL); + } + + } + } + + if (0 != iStrLen && + pbufDstAnsiString->Resize(iStrLen + 1)) + { + // insert a terminating NULL into buffer for the dwStringLen+1 in the case that the dwStringLen+1 was not a NULL. + ((CHAR*)pbufDstAnsiString->QueryPtr())[iStrLen] = '\0'; + } + else + { + iStrLen = -1; + } + + return iStrLen; +} + +// static +HRESULT +STRA::ConvertUnicodeToMultiByte( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __in BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen +) +{ + return ConvertUnicodeToCodePage( pszSrcUnicodeString, + pbufDstAnsiString, + dwStringLen, + CP_ACP ); +} + +// static +HRESULT +STRA::ConvertUnicodeToUTF8( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __in BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen +) +{ + return ConvertUnicodeToCodePage( pszSrcUnicodeString, + pbufDstAnsiString, + dwStringLen, + CP_UTF8 ); +} + +/*++ + +Routine Description: + + Removes leading and trailing whitespace + +--*/ + +VOID +STRA::Trim() +{ + PSTR pszString = QueryStr(); + DWORD cchNewLength = m_cchLen; + DWORD cchLeadingWhitespace = 0; + DWORD cchTempLength = 0; + + for (LONG ixString = m_cchLen - 1; ixString >= 0; ixString--) + { + if (isspace((unsigned char) pszString[ixString]) != 0) + { + pszString[ixString] = '\0'; + cchNewLength--; + } + else + { + break; + } + } + + cchTempLength = cchNewLength; + for (DWORD ixString = 0; ixString < cchTempLength; ixString++) + { + if (isspace((unsigned char) pszString[ixString]) != 0) + { + cchLeadingWhitespace++; + cchNewLength--; + } + else + { + break; + } + } + + if (cchNewLength == 0) + { + + Reset(); + } + else if (cchLeadingWhitespace > 0) + { + memmove(pszString, pszString + cchLeadingWhitespace, cchNewLength * sizeof(CHAR)); + pszString[cchNewLength] = '\0'; + } + + SyncWithBuffer(); +} + +/*++ + +Routine Description: + + Compares the string to the provided prefix to check for equality + +Arguments: + + pStraPrefix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if prefix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::StartsWith( + __in const STRA * pStraPrefix, + __in bool fIgnoreCase) const +{ + _ASSERTE( pStraPrefix != NULL ); + return StartsWith(pStraPrefix->QueryStr(), fIgnoreCase); +} + +/*++ + +Routine Description: + + Compares the string to the provided prefix to check for equality + +Arguments: + + straPrefix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if prefix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::StartsWith( + __in const STRA & straPrefix, + __in bool fIgnoreCase) const +{ + return StartsWith(straPrefix.QueryStr(), fIgnoreCase); +} + +/*++ + +Routine Description: + + Compares the string to the provided prefix to check for equality + +Arguments: + + pszPrefix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if prefix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::StartsWith( + __in PCSTR pszPrefix, + __in bool fIgnoreCase) const +{ + HRESULT hr = S_OK; + BOOL fMatch = FALSE; + size_t cchPrefix = 0; + + if (pszPrefix == NULL) + { + goto Finished; + } + + hr = StringCchLengthA( pszPrefix, + STRSAFE_MAX_CCH, + &cchPrefix ); + if (FAILED(hr)) + { + goto Finished; + } + + _ASSERTE( cchPrefix <= MAXDWORD ); + + if (cchPrefix > m_cchLen) + { + goto Finished; + } + + if( fIgnoreCase ) + { + fMatch = ( 0 == _strnicmp( QueryStr(), pszPrefix, cchPrefix ) ); + } + else + { + fMatch = ( 0 == strncmp( QueryStr(), pszPrefix, cchPrefix ) ); + } + + +Finished: + + return fMatch; +} + +/*++ + +Routine Description: + + Compares the string to the provided suffix to check for equality + +Arguments: + + pStraSuffix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if suffix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::EndsWith( + __in const STRA * pStraSuffix, + __in bool fIgnoreCase) const +{ + _ASSERTE( pStraSuffix != NULL ); + return EndsWith(pStraSuffix->QueryStr(), fIgnoreCase); +} + + +/*++ + +Routine Description: + + Compares the string to the provided suffix to check for equality + +Arguments: + + straSuffix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if suffix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::EndsWith( + __in const STRA & straSuffix, + __in bool fIgnoreCase) const +{ + return EndsWith(straSuffix.QueryStr(), fIgnoreCase); +} + + +/*++ + +Routine Description: + + Compares the string to the provided suffix to check for equality + +Arguments: + + pszSuffix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if suffix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::EndsWith( + __in PCSTR pszSuffix, + __in bool fIgnoreCase) const +{ + HRESULT hr = S_OK; + PSTR pszString = QueryStr(); + BOOL fMatch = FALSE; + size_t cchSuffix = 0; + ptrdiff_t ixOffset = 0; + + if (pszSuffix == NULL) + { + goto Finished; + } + + hr = StringCchLengthA( pszSuffix, + STRSAFE_MAX_CCH, + &cchSuffix ); + if (FAILED(hr)) + { + goto Finished; + } + + _ASSERTE( cchSuffix <= MAXDWORD ); + + if (cchSuffix > m_cchLen) + { + goto Finished; + } + + ixOffset = m_cchLen - cchSuffix; + _ASSERTE(ixOffset >= 0 && ixOffset <= MAXDWORD); + + if( fIgnoreCase ) + { + fMatch = ( 0 == _strnicmp( pszString + ixOffset, pszSuffix, cchSuffix ) ); + } + else + { + fMatch = ( 0 == strncmp( pszString + ixOffset, pszSuffix, cchSuffix ) ); + } + +Finished: + + return fMatch; +} + + +/*++ + +Routine Description: + + Searches the string for the first occurrence of the specified character. + +Arguments: + + charValue - character to find + dwStartIndex - the initial index. + +Return Value: + + The index for the first character occurence in the string. + + -1 if not found. + +--*/ +INT +STRA::IndexOf( + __in CHAR charValue, + __in DWORD dwStartIndex + ) const +{ + INT nIndex = -1; + + // Make sure that there are no buffer overruns. + if( dwStartIndex >= QueryCCH() ) + { + goto Finished; + } + + const CHAR* pChar = strchr( QueryStr() + dwStartIndex, charValue ); + + // Determine the index if found + if( pChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + + +/*++ + +Routine Description: + + Searches the string for the first occurrence of the specified substring. + +Arguments: + + pszValue - substring to find + dwStartIndex - initial index. + +Return Value: + + The index for the first character occurence in the string. + + -1 if not found. + +--*/ +INT +STRA::IndexOf( + __in PCSTR pszValue, + __in DWORD dwStartIndex + ) const +{ + HRESULT hr = S_OK; + INT nIndex = -1; + SIZE_T cchValue = 0; + + // Validate input parameters + if( dwStartIndex >= QueryCCH() || !pszValue ) + { + goto Finished; + } + + const CHAR* pChar = strstr( QueryStr() + dwStartIndex, pszValue ); + + // Determine the index if found + if( pChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + + +/*++ + +Routine Description: + + Searches the string for the last occurrence of the specified character. + +Arguments: + + charValue - character to find + dwStartIndex - initial index. + +Return Value: + + The index for the last character occurence in the string. + + -1 if not found. + +--*/ +INT +STRA::LastIndexOf( + __in CHAR charValue, + __in DWORD dwStartIndex + ) const +{ + INT nIndex = -1; + + // Make sure that there are no buffer overruns. + if( dwStartIndex >= QueryCCH() ) + { + goto Finished; + } + + const CHAR* pChar = strrchr( QueryStr() + dwStartIndex, charValue ); + + // Determine the index if found + if( pChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp new file mode 100644 index 0000000000..4fd2a052f2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp @@ -0,0 +1,1289 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +STRU::STRU( + VOID +) : m_cchLen( 0 ) +{ + *(QueryStr()) = L'\0'; +} + +STRU::STRU( + __inout_ecount(cchInit) WCHAR* pbInit, + __in DWORD cchInit +) : m_Buff( pbInit, cchInit * sizeof( WCHAR ) ), + m_cchLen( 0 ) +/*++ + Description: + + Used by STACK_STRU. Initially populates underlying buffer with pbInit. + + pbInit is not freed. + + Arguments: + + pbInit - initial memory to use + cchInit - count, in characters, of pbInit + + Returns: + + None. + +--*/ +{ + _ASSERTE( cchInit <= (MAXDWORD / sizeof( WCHAR )) ); + _ASSERTE( NULL != pbInit ); + _ASSERTE(cchInit > 0 ); + _ASSERTE(pbInit[0] == L'\0'); +} + +BOOL +STRU::IsEmpty( + VOID +) const +{ + return ( m_cchLen == 0 ); +} + +DWORD +STRU::QueryCB( + VOID +) const +// +// Returns the number of bytes in the string excluding the terminating NULL +// +{ + return m_cchLen * sizeof( WCHAR ); +} + +DWORD +STRU::QueryCCH( + VOID +) const +// +// Returns the number of characters in the string excluding the terminating NULL +// +{ + return m_cchLen; +} + +DWORD +STRU::QuerySizeCCH( + VOID +) const +// +// Returns size of the underlying storage buffer, in characters +// +{ + return m_Buff.QuerySize() / sizeof( WCHAR ); +} + +__nullterminated +__ecount(this->m_cchLen) +WCHAR* +STRU::QueryStr( + VOID +) const +// +// Return the string buffer +// +{ + return m_Buff.QueryPtr(); +} + +VOID +STRU::Reset( + VOID +) +// +// Resets the internal string to be NULL string. Buffer remains cached. +// +{ + _ASSERTE( QueryStr() != NULL ); + *(QueryStr()) = L'\0'; + m_cchLen = 0; +} + +HRESULT +STRU::Resize( + DWORD cchSize +) +{ + SIZE_T cbSize = cchSize * sizeof( WCHAR ); + if ( cbSize > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + if( !m_Buff.Resize( cbSize ) ) + { + return E_OUTOFMEMORY; + } + + return S_OK; +} + +HRESULT +STRU::SyncWithBuffer( + VOID +) +// +// Recalculate the length of the string, etc. because we've modified +// the buffer directly. +// +{ + HRESULT hr; + size_t size; + hr = StringCchLengthW( QueryStr(), + QuerySizeCCH(), + &size ); + if ( SUCCEEDED( hr ) ) + { + m_cchLen = static_cast(size); + } + return hr; +} + +HRESULT +STRU::Copy( + __in PCWSTR pszCopy +) +{ + HRESULT hr; + size_t cbStr; + + hr = StringCchLengthW( pszCopy, + STRSAFE_MAX_CCH, + &cbStr ); + if ( FAILED( hr ) ) + { + return hr; + } + + _ASSERTE( cbStr <= MAXDWORD ); + return Copy( pszCopy, + cbStr ); +} + +HRESULT +STRU::Copy( + __in_ecount(cchLen) + PCWSTR pszCopy, + SIZE_T cchLen +) +// +// Copy the contents of another string to this one +// +{ + return AuxAppend( pszCopy, + cchLen * sizeof(WCHAR), + 0); +} + +HRESULT +STRU::Copy( + __in const STRU * pstrRhs +) +{ + _ASSERTE( NULL != pstrRhs ); + return Copy( pstrRhs->QueryStr(), pstrRhs->QueryCCH() ); +} + +HRESULT +STRU::Copy( + __in const STRU & str +) +{ + return Copy( str.QueryStr(), str.QueryCCH() ); +} + +HRESULT +STRU::CopyAndExpandEnvironmentStrings( + __in PCWSTR pszSource +) +{ + HRESULT hr = S_OK; + DWORD cchDestReqBuff = 0; + + Reset(); + + cchDestReqBuff = ExpandEnvironmentStringsW( pszSource, + QueryStr(), + QuerySizeCCH() ); + if ( cchDestReqBuff == 0 ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + else if ( cchDestReqBuff > QuerySizeCCH() ) + { + hr = Resize( cchDestReqBuff ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + cchDestReqBuff = ExpandEnvironmentStringsW( pszSource, + QueryStr(), + QuerySizeCCH() ); + + if ( cchDestReqBuff == 0 || cchDestReqBuff > QuerySizeCCH() ) + { + _ASSERTE( FALSE ); + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + } + + hr = SyncWithBuffer(); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + return hr; + +} + +HRESULT +STRU::CopyA( + __in PCSTR pszCopyA +) +{ + HRESULT hr; + size_t cbStr; + + hr = StringCbLengthA( pszCopyA, + STRSAFE_MAX_CCH, + &cbStr ); + if ( FAILED( hr ) ) + { + return hr; + } + + _ASSERTE( cbStr <= MAXDWORD ); + return CopyA( pszCopyA, + cbStr ); +} + +HRESULT +STRU::CopyA( + __in_bcount(cchLen) + PCSTR pszCopyA, + SIZE_T cchLen, + UINT CodePage /*= CP_UTF8*/ +) +{ + return AuxAppendA( + pszCopyA, + cchLen, + 0, + CodePage + ); +} + +HRESULT +STRU::Append( + __in PCWSTR pszAppend +) +{ + HRESULT hr; + size_t cbStr; + + hr = StringCchLengthW( pszAppend, + STRSAFE_MAX_CCH, + &cbStr ); + if ( FAILED( hr ) ) + { + return hr; + } + + _ASSERTE( cbStr <= MAXDWORD ); + return Append( pszAppend, + cbStr ); +} + +HRESULT +STRU::Append( + __in_ecount(cchLen) + PCWSTR pszAppend, + SIZE_T cchLen +) +// +// Append something to the end of the string +// +{ + if ( cchLen == 0 ) + { + return S_OK; + } + return AuxAppend( pszAppend, + cchLen * sizeof(WCHAR), + QueryCB() ); +} + +HRESULT +STRU::Append( + __in const STRU * pstrRhs +) +{ + _ASSERTE( NULL != pstrRhs ); + return Append( pstrRhs->QueryStr(), pstrRhs->QueryCCH() ); +} + +HRESULT +STRU::Append( + __in const STRU & strRhs +) +{ + return Append( strRhs.QueryStr(), strRhs.QueryCCH() ); +} + +HRESULT +STRU::AppendA( + __in PCSTR pszAppendA +) +{ + HRESULT hr; + size_t cbStr; + + hr = StringCbLengthA( pszAppendA, + STRSAFE_MAX_CCH, + &cbStr ); + if ( FAILED( hr ) ) + { + return hr; + } + + _ASSERTE( cbStr <= MAXDWORD ); + return AppendA( pszAppendA, + cbStr ); +} + +HRESULT +STRU::AppendA( + __in_bcount(cchLen) + PCSTR pszAppendA, + SIZE_T cchLen, + UINT CodePage /*= CP_UTF8*/ +) +{ + if ( cchLen == 0 ) + { + return S_OK; + } + return AuxAppendA( + pszAppendA, + cchLen, + QueryCB(), + CodePage + ); +} + +HRESULT +STRU::CopyToBuffer( + __out_bcount(*pcb) WCHAR* pszBuffer, + PDWORD pcb +) const +// +// Makes a copy of the stored string into the given buffer +// +{ + _ASSERTE( NULL != pszBuffer ); + _ASSERTE( NULL != pcb ); + + HRESULT hr = S_OK; + DWORD cbNeeded = QueryCB() + sizeof( WCHAR ); + + if( *pcb < cbNeeded ) + { + hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ); + goto Finished; + } + + // + // BUGBUG: StringCchCopy? + // + memcpy( pszBuffer, QueryStr(), cbNeeded ); + +Finished: + + *pcb = cbNeeded; + + return hr; +} + +HRESULT +STRU::CopyToBufferA( + __out_bcount(*pcb) CHAR* pszBuffer, + __inout PDWORD pcb +) const +{ + HRESULT hr = S_OK; + STACK_STRA( straBuffer, 256 ); + hr = straBuffer.CopyW( QueryStr() ); + if ( FAILED( hr ) ) + { + goto Finished; + } + hr = straBuffer.CopyToBuffer( pszBuffer, pcb ); + if ( FAILED( hr ) ) + { + goto Finished; + } +Finished: + return hr; +} + +HRESULT +STRU::SetLen( + __in DWORD cchLen +) +/*++ + * +Routine Description: + + Set the length of the string and null terminate, if there + is sufficient buffer already allocated. Will not reallocate. + +Arguments: + + cchLen - The number of characters in the new string. + +Return Value: + + HRESULT + +--*/ +{ + if( cchLen >= QuerySizeCCH() ) + { + return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + + *( QueryStr() + cchLen ) = L'\0'; + m_cchLen = cchLen; + + return S_OK; +} + +HRESULT +STRU::SafeSnwprintf( + __in PCWSTR pwszFormatString, + ... +) +/*++ + +Routine Description: + + Writes to a STRU, growing it as needed. It arbitrarily caps growth at 64k chars. + +Arguments: + + pwszFormatString - printf format + ... - printf args + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + va_list argsList; + va_start( argsList, pwszFormatString ); + + hr = SafeVsnwprintf(pwszFormatString, argsList); + + va_end( argsList ); + return hr; +} + +HRESULT +STRU::SafeVsnwprintf( + __in PCWSTR pwszFormatString, + va_list argsList +) +/*++ + +Routine Description: + + Writes to a STRU, growing it as needed. It arbitrarily caps growth at 64k chars. + +Arguments: + + pwszFormatString - printf format + argsList - printf va_list + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + int cchOutput; + int cchNeeded; + + // + // Format the incoming message using vsnprintf() + // so that the overflows are captured + // + cchOutput = _vsnwprintf_s( + QueryStr(), + QuerySizeCCH(), + QuerySizeCCH() - 1, + pwszFormatString, + argsList + ); + + if( cchOutput == -1 ) + { + // + // Couldn't fit this in the original STRU size. + // + cchNeeded = _vscwprintf( pwszFormatString, argsList ); + if( cchNeeded > 64 * 1024 ) + { + // + // If we're trying to produce a string > 64k chars, then + // there is probably a problem + // + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + + // + // _vscprintf doesn't include terminating null character + // + cchNeeded++; + + hr = Resize( cchNeeded ); + if( FAILED( hr ) ) + { + goto Finished; + } + + cchOutput = _vsnwprintf_s( + QueryStr(), + QuerySizeCCH(), + QuerySizeCCH() - 1, + pwszFormatString, + argsList + ); + if( -1 == cchOutput ) + { + // + // This should never happen, cause we should already have correctly sized memory + // + _ASSERTE( FALSE ); + + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + } + + // + // always null terminate at the last WCHAR + // + QueryStr()[ QuerySizeCCH() - 1 ] = L'\0'; + + // + // we directly touched the buffer - therefore: + // + hr = SyncWithBuffer(); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + if( FAILED( hr ) ) + { + Reset(); + } + + return hr; +} + +HRESULT +STRU::AuxAppend( + __in_ecount(cNumStrings) + PCWSTR const rgpszStrings[], + SIZE_T cNumStrings +) +/*++ + +Routine Description: + + Appends an array of strings of length cNumStrings + +Arguments: + + rgStrings - The array of strings to be appened + cNumStrings - The count of String + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + size_t cbStringsTotal = sizeof( WCHAR ); // Account for null-terminator + + // + // Compute total size of the string. + // Resize internal buffer + // Copy each array element one by one to backing buffer + // Update backing buffer string length + // + for ( SIZE_T i = 0; i < cNumStrings; i++ ) + { + _ASSERTE( rgpszStrings[ i ] != NULL ); + if ( NULL == rgpszStrings[ i ] ) + { + return E_INVALIDARG; + } + + size_t cbString = 0; + + hr = StringCbLengthW( rgpszStrings[ i ], + STRSAFE_MAX_CCH * sizeof( WCHAR ), + &cbString ); + if ( FAILED( hr ) ) + { + return hr; + } + + cbStringsTotal += cbString; + + if ( cbStringsTotal > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + } + + size_t cbBufSizeRequired = QueryCB() + cbStringsTotal; + if ( cbBufSizeRequired > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + + if( m_Buff.QuerySize() < cbBufSizeRequired ) + { + if( !m_Buff.Resize( cbBufSizeRequired ) ) + { + return E_OUTOFMEMORY; + } + } + + STRSAFE_LPWSTR pszStringEnd = QueryStr() + QueryCCH(); + size_t cchRemaining = QuerySizeCCH() - QueryCCH(); + for ( SIZE_T i = 0; i < cNumStrings; i++ ) + { + hr = StringCchCopyExW( pszStringEnd, // pszDest + cchRemaining, // cchDest + rgpszStrings[ i ], // pszSrc + &pszStringEnd, // ppszDestEnd + &cchRemaining, // pcchRemaining + 0 ); // dwFlags + if ( FAILED( hr ) ) + { + _ASSERTE( FALSE ); + HRESULT hr2 = SyncWithBuffer(); + if ( FAILED( hr2 ) ) + { + return hr2; + } + return hr; + } + } + + m_cchLen = static_cast< DWORD >( cbBufSizeRequired ) / sizeof( WCHAR ) - 1; + + return S_OK; +} + +HRESULT +STRU::AuxAppend( + __in_bcount(cbStr) + const WCHAR* pStr, + SIZE_T cbStr, + DWORD cbOffset +) +/*++ + +Routine Description: + + Appends to the string starting at the (byte) offset cbOffset. + +Arguments: + + pStr - A unicode string to be appended + cbStr - Length, in bytes, of pStr + cbOffset - Offset, in bytes, at which to begin the append + +Return Value: + + HRESULT + +--*/ +{ + _ASSERTE( NULL != pStr ); + _ASSERTE( 0 == cbStr % sizeof( WCHAR ) ); + _ASSERTE( cbOffset <= QueryCB() ); + _ASSERTE( 0 == cbOffset % sizeof( WCHAR ) ); + + ULONGLONG cb64NewSize = (ULONGLONG)cbOffset + cbStr + sizeof( WCHAR ); + if( cb64NewSize > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + + if( m_Buff.QuerySize() < cb64NewSize ) + { + if( !m_Buff.Resize( static_cast(cb64NewSize) ) ) + { + return E_OUTOFMEMORY; + } + } + + memcpy( reinterpret_cast(m_Buff.QueryPtr()) + cbOffset, pStr, cbStr ); + + m_cchLen = (static_cast(cbStr) + cbOffset) / sizeof(WCHAR); + + *( QueryStr() + m_cchLen ) = L'\0'; + + return S_OK; +} + +HRESULT +STRU::AuxAppendA( + __in_bcount(cbStr) + const CHAR* pStr, + SIZE_T cbStr, + DWORD cbOffset, + UINT CodePage +) +/*++ + +Routine Description: + + Convert and append an ANSI string to the string starting at + the (byte) offset cbOffset + +Arguments: + + pStr - An ANSI string to be appended + cbStr - Length, in bytes, of pStr + cbOffset - Offset, in bytes, at which to begin the append + CodePage - code page to use for conversion + +Return Value: + + HRESULT + +--*/ +{ + WCHAR* pszBuffer; + DWORD cchBuffer; + DWORD cchCharsCopied = 0; + + _ASSERTE( NULL != pStr ); + _ASSERTE( cbOffset <= QueryCB() ); + _ASSERTE( 0 == cbOffset % sizeof( WCHAR ) ); + + if ( NULL == pStr ) + { + return E_INVALIDARG; + } + + if( 0 == cbStr ) + { + return S_OK; + } + + // + // Only resize when we have to. When we do resize, we tack on + // some extra space to avoid extra reallocations. + // + if( m_Buff.QuerySize() < (ULONGLONG)cbOffset + (cbStr * sizeof( WCHAR )) + sizeof(WCHAR) ) + { + ULONGLONG cb64NewSize = (ULONGLONG)( cbOffset + cbStr * sizeof(WCHAR) + sizeof( WCHAR ) ); + + // + // Check for the arithmetic overflow + // + if( cb64NewSize > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + + if( !m_Buff.Resize( static_cast(cb64NewSize) ) ) + { + return E_OUTOFMEMORY; + } + } + + pszBuffer = reinterpret_cast(reinterpret_cast(m_Buff.QueryPtr()) + cbOffset); + cchBuffer = ( m_Buff.QuerySize() - cbOffset - sizeof( WCHAR ) ) / sizeof( WCHAR ); + + cchCharsCopied = MultiByteToWideChar( + CodePage, + MB_ERR_INVALID_CHARS, + pStr, + static_cast(cbStr), + pszBuffer, + cchBuffer + ); + if( 0 == cchCharsCopied ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + // + // set the new length + // + m_cchLen = cchCharsCopied + cbOffset/sizeof(WCHAR); + + // + // Must be less than, cause still need to add NULL + // + _ASSERTE( m_cchLen < QuerySizeCCH() ); + + // + // append NULL character + // + *(QueryStr() + m_cchLen) = L'\0'; + + return S_OK; +} + + +/*++ + +Routine Description: + + Removes leading and trailing whitespace + +--*/ + +VOID +STRU::Trim() +{ + PWSTR pwszString = QueryStr(); + DWORD cchNewLength = m_cchLen; + DWORD cchLeadingWhitespace = 0; + DWORD cchTempLength = 0; + + for (LONG ixString = m_cchLen - 1; ixString >= 0; ixString--) + { + if (iswspace(pwszString[ixString]) != 0) + { + pwszString[ixString] = L'\0'; + cchNewLength--; + } + else + { + break; + } + } + + cchTempLength = cchNewLength; + for (DWORD ixString = 0; ixString < cchTempLength; ixString++) + { + if (iswspace(pwszString[ixString]) != 0) + { + cchLeadingWhitespace++; + cchNewLength--; + } + else + { + break; + } + } + + if (cchNewLength == 0) + { + + Reset(); + } + else if (cchLeadingWhitespace > 0) + { + memmove(pwszString, pwszString + cchLeadingWhitespace, cchNewLength * sizeof(WCHAR)); + pwszString[cchNewLength] = L'\0'; + } + + SyncWithBuffer(); +} + +/*++ + +Routine Description: + + Compares the string to the provided prefix to check for equality + +Arguments: + + pwszPrefix - wide char string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if prefix string matches with internal string, FALSE otherwise + +--*/ + +BOOL +STRU::StartsWith( + __in PCWSTR pwszPrefix, + __in bool fIgnoreCase) const +{ + HRESULT hr = S_OK; + BOOL fMatch = FALSE; + size_t cchPrefix = 0; + + if (pwszPrefix == NULL) + { + goto Finished; + } + + hr = StringCchLengthW( pwszPrefix, + STRSAFE_MAX_CCH, + &cchPrefix ); + if (FAILED(hr)) + { + goto Finished; + } + + _ASSERTE( cchPrefix <= MAXLONG ); + + if (cchPrefix > m_cchLen) + { + goto Finished; + } + + #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + fMatch = ( CSTR_EQUAL == CompareStringOrdinal( QueryStr(), + (int)cchPrefix, + pwszPrefix, + (int)cchPrefix, + fIgnoreCase ) ); + #else + + if( fIgnoreCase ) + { + fMatch = ( 0 == _wcsnicmp( QueryStr(), pwszPrefix, cchPrefix ) ); + } + else + { + fMatch = ( 0 == wcsncmp( QueryStr(), pwszPrefix, cchPrefix ) ); + } + + #endif + +Finished: + + return fMatch; +} + +/*++ + +Routine Description: + + Compares the string to the provided suffix to check for equality + +Arguments: + + pwszSuffix - wide char string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if suffix string matches with internal string, FALSE otherwise + +--*/ + + +BOOL +STRU::EndsWith( + __in PCWSTR pwszSuffix, + __in bool fIgnoreCase) const +{ + HRESULT hr = S_OK; + PWSTR pwszString = QueryStr(); + BOOL fMatch = FALSE; + size_t cchSuffix = 0; + ptrdiff_t ixOffset = 0; + + if (pwszSuffix == NULL) + { + goto Finished; + } + + hr = StringCchLengthW( pwszSuffix, + STRSAFE_MAX_CCH, + &cchSuffix ); + if (FAILED(hr)) + { + goto Finished; + } + + _ASSERTE( cchSuffix <= MAXLONG ); + + if (cchSuffix > m_cchLen) + { + goto Finished; + } + + ixOffset = m_cchLen - cchSuffix; + _ASSERTE(ixOffset >= 0 && ixOffset <= MAXDWORD); + + #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + fMatch = ( CSTR_EQUAL == CompareStringOrdinal( pwszString + ixOffset, + (int)cchSuffix, + pwszSuffix, + (int)cchSuffix, + fIgnoreCase ) ); + #else + + if( fIgnoreCase ) + { + fMatch = ( 0 == _wcsnicmp( pwszString + ixOffset, pwszSuffix, cchSuffix ) ); + } + else + { + fMatch = ( 0 == wcsncmp( pwszString + ixOffset, pwszSuffix, cchSuffix ) ); + } + + #endif + +Finished: + + return fMatch; +} + +/*++ + +Routine Description: + + Searches the string for the first occurrence of the specified character. + +Arguments: + + charValue - character to find + dwStartIndex - the initial index. + +Return Value: + + The index for the first character occurence in the string. + + -1 if not found. + +--*/ +INT +STRU::IndexOf( + __in WCHAR charValue, + __in DWORD dwStartIndex + ) const +{ + INT nIndex = -1; + + // Make sure that there are no buffer overruns. + if( dwStartIndex >= QueryCCH() ) + { + goto Finished; + } + + const WCHAR* pwChar = wcschr( QueryStr() + dwStartIndex, charValue ); + + // Determine the index if found + if( pwChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pwChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + + +/*++ + +Routine Description: + + Searches the string for the first occurrence of the specified substring. + +Arguments: + + pwszValue - substring to find + dwStartIndex - initial index. + +Return Value: + + The index for the first character occurence in the string. + + -1 if not found. + +--*/ +INT +STRU::IndexOf( + __in PCWSTR pwszValue, + __in DWORD dwStartIndex + ) const +{ + HRESULT hr = S_OK; + INT nIndex = -1; + SIZE_T cchValue = 0; + + // Validate input parameters + if( dwStartIndex >= QueryCCH() || !pwszValue ) + { + goto Finished; + } + + const WCHAR* pwChar = wcsstr( QueryStr() + dwStartIndex, pwszValue ); + + // Determine the index if found + if( pwChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pwChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + + +/*++ + +Routine Description: + + Searches the string for the last occurrence of the specified character. + +Arguments: + + charValue - character to find + dwStartIndex - initial index. + +Return Value: + + The index for the last character occurence in the string. + + -1 if not found. + +--*/ +INT +STRU::LastIndexOf( + __in WCHAR charValue, + __in DWORD dwStartIndex + ) const +{ + INT nIndex = -1; + + // Make sure that there are no buffer overruns. + if( dwStartIndex >= QueryCCH() ) + { + goto Finished; + } + + const WCHAR* pwChar = wcsrchr( QueryStr() + dwStartIndex, charValue ); + + // Determine the index if found + if( pwChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pwChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + +//static +HRESULT +STRU::ExpandEnvironmentVariables( + __in PCWSTR pszString, + __out STRU * pstrExpandedString + ) +/*++ + +Routine Description: + + Expand the environment variables in a string + +Arguments: + + pszString - String with environment variables to expand + pstrExpandedString - Receives expanded string on success + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + DWORD cchNewSize = 0; + + if ( pszString == NULL || + pstrExpandedString == NULL ) + { + DBG_ASSERT( FALSE ); + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Exit; + } + + cchNewSize = ExpandEnvironmentStrings( pszString, + pstrExpandedString->QueryStr(), + pstrExpandedString->QuerySizeCCH() ); + if ( cchNewSize == 0 ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Exit; + } + + if ( cchNewSize > pstrExpandedString->QuerySizeCCH() ) + { + hr = pstrExpandedString->Resize( + ( cchNewSize + 1 ) * sizeof( WCHAR ) + ); + if ( FAILED( hr ) ) + { + goto Exit; + } + + cchNewSize = ExpandEnvironmentStrings( + pszString, + pstrExpandedString->QueryStr(), + pstrExpandedString->QuerySizeCCH() + ); + + if ( cchNewSize == 0 || + cchNewSize > pstrExpandedString->QuerySizeCCH() ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Exit; + } + } + + pstrExpandedString->SyncWithBuffer(); + + hr = S_OK; + +Exit: + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx new file mode 100644 index 0000000000..69b42e6250 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx @@ -0,0 +1,1416 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +// +// BUGBUG: Turn off optimization on ia64 builds due to a compiler bug +// +#if (defined(_M_IA64) && (_MSC_FULL_VER == 13009286)) +#pragma optimize("",off) +#endif + +#define LF 0x0A +#define SP 0x20 +#define HT 0x09 + +#define HTTP_CHAR 0x001 +#define HTTP_UPCASE 0x002 +#define HTTP_LOCASE 0x004 +#define HTTP_ALPHA (HTTP_UPCASE | HTTP_LOCASE) +#define HTTP_DIGIT 0x008 +#define HTTP_CTL 0x010 +#define HTTP_LWS 0x020 +#define HTTP_HEX 0x040 +#define HTTP_SEPERATOR 0x080 +#define HTTP_TOKEN 0x100 + +#define URL_LEGAL 0x200 +#define URL_TOKEN (HTTP_ALPHA | HTTP_DIGIT | URL_LEGAL) + +#define IS_HTTP_UPCASE(c) (HttpChars[(UCHAR)(c)] & HTTP_UPCASE) +#define IS_HTTP_LOCASE(c) (HttpChars[(UCHAR)(c)] & HTTP_UPCASE) +#define IS_HTTP_ALPHA(c) (HttpChars[(UCHAR)(c)] & HTTP_ALPHA) +#define IS_HTTP_DIGIT(c) (HttpChars[(UCHAR)(c)] & HTTP_DIGIT) +#define IS_HTTP_HEX(c) (HttpChars[(UCHAR)(c)] & HTTP_HEX) +#define IS_HTTP_CTL(c) (HttpChars[(UCHAR)(c)] & HTTP_CTL) +#define IS_HTTP_LWS(c) (HttpChars[(UCHAR)(c)] & HTTP_LWS) +#define IS_HTTP_SEPERATOR(c) (HttpChars[(UCHAR)(c)] & HTTP_SEPERATOR) +#define IS_HTTP_TOKEN(c) (HttpChars[(UCHAR)(c)] & HTTP_TOKEN) +#define IS_URL_TOKEN(c) (HttpChars[(UCHAR)(c)] & URL_TOKEN) + +// Some stuff not defined in VS SDK +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + +// Copied from ntstatus.h, otherwise we will have double definition for +// number of macros that are both in ntstatus.h and winnt.h +#ifndef STATUS_SUCCESS +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth +#endif +#ifndef STATUS_OBJECT_PATH_SYNTAX_BAD +#define STATUS_OBJECT_PATH_SYNTAX_BAD ((NTSTATUS)0xC000003BL) +#endif +#ifndef STATUS_OBJECT_PATH_INVALID +#define STATUS_OBJECT_PATH_INVALID ((NTSTATUS)0xC0000039L) +#endif +// +// Constant Declarations for UTF8 Encoding +// + +#define ASCII 0x007f + +#define UTF8_2_MAX 0x07ff // max UTF8 2-byte sequence (32 * 64 =2048) +#define UTF8_1ST_OF_2 0xc0 // 110x xxxx +#define UTF8_1ST_OF_3 0xe0 // 1110 xxxx +#define UTF8_1ST_OF_4 0xf0 // 1111 xxxx +#define UTF8_TRAIL 0x80 // 10xx xxxx + +#define HIGHER_6_BIT(u) ((u) >> 12) +#define MIDDLE_6_BIT(u) (((u) & 0x0fc0) >> 6) +#define LOWER_6_BIT(u) ((u) & 0x003f) + +#define BIT7(a) ((a) & 0x80) +#define BIT6(a) ((a) & 0x40) + +#define HIGH_SURROGATE_START 0xd800 +#define HIGH_SURROGATE_END 0xdbff +#define LOW_SURROGATE_START 0xdc00 +#define LOW_SURROGATE_END 0xdfff + +#define EMIT_CHAR(ch) \ + do { \ + pDest[0] = (ch); \ + pDest += 1; \ + BytesCopied += 2; \ + } while (0) + +typedef enum _URL_TYPE +{ + UrlTypeUtf8, + UrlTypeAnsi, + UrlTypeDbcs +} URL_TYPE; + +typedef enum _URL_PART +{ + Scheme, + HostName, + AbsPath, + QueryString + +} URL_PART; + +#define IS_UTF8_TRAILBYTE(ch) (((ch) & 0xc0) == 0x80) + +// +// These are copied from RTL NLS routines. +// + +#define DBCS_TABLE_SIZE 256 +extern PUSHORT NlsLeadByteInfo; + +#define LeadByteTable (*(PUSHORT *)NlsLeadByteInfo) +#define IS_LEAD_BYTE(c) (IsDBCSLeadByte(c)) + +ULONG HttpChars[256]; +USHORT FastPopChars[256]; +USHORT DummyPopChars[256]; +WCHAR FastUpcaseChars[256]; +BOOL g_UlEnableNonUTF8; +BOOL g_UlEnableDBCS; +BOOL g_UlFavorDBCS; + +// RtlNtStatusToDosError is nowhere defined, should be used through +// native code "reflection" +typedef ULONG (RTL_NT_STATUS_TO_DOS_ERROR_PROC)(NTSTATUS); +static RTL_NT_STATUS_TO_DOS_ERROR_PROC* rtlNtStatusToDosErrorProc = NULL; +static HMODULE lib = NULL; + +HRESULT +WIN32_FROM_NTSTATUS( + __in NTSTATUS status, + __out DWORD * pResult + ) +{ + HRESULT hr = S_OK; + if (pResult == NULL) + { + hr = E_INVALIDARG; + goto Finished; + } + if (lib == NULL) + { + lib = GetModuleHandle(L"Ntdll.dll"); + if (lib == NULL) + { + hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + goto Finished; + } + } + if (rtlNtStatusToDosErrorProc == NULL) + { + rtlNtStatusToDosErrorProc = + (RTL_NT_STATUS_TO_DOS_ERROR_PROC*)GetProcAddress( + lib, "RtlNtStatusToDosError"); + if (rtlNtStatusToDosErrorProc == NULL) + { + hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + goto Finished; + } + } + *pResult = rtlNtStatusToDosErrorProc(status); + +Finished: + return hr; +} + +NTSTATUS +Unescape( + IN PUCHAR pChar, + OUT PUCHAR pOutChar + ) + +{ + UCHAR Result, Digit; + + if (pChar[0] != '%' || + SAFEIsXDigit(pChar[1]) == FALSE || + SAFEIsXDigit(pChar[2]) == FALSE) + { + return STATUS_OBJECT_PATH_SYNTAX_BAD; + } + + // + // HexToChar() inlined + // + + // uppercase #1 + // + if (SAFEIsAlpha(pChar[1])) + Digit = (UCHAR) toupper(pChar[1]); + else + Digit = pChar[1]; + + Result = ((Digit >= 'A') ? (Digit - 'A' + 0xA) : (Digit - '0')) << 4; + + // uppercase #2 + // + if (SAFEIsAlpha(pChar[2])) + Digit = (UCHAR) toupper(pChar[2]); + else + Digit = pChar[2]; + + Result |= (Digit >= 'A') ? (Digit - 'A' + 0xA) : (Digit - '0'); + + *pOutChar = Result; + + return STATUS_SUCCESS; + +} // Unescape + +// +// PopChar is used only if the string is not UTF-8, or UrlPart != QueryString, +// or the current character is '%' or its high bit is set. In all other cases, +// the FastPopChars table is used for fast conversion. +// + +__inline +NTSTATUS +PopChar( + IN URL_TYPE UrlType, + IN URL_PART UrlPart, + __in LPSTR pChar, + __out WCHAR * pUnicodeChar, + __out WCHAR * pUnicodeChar2, + OUT PULONG pCharToSkip + ) +{ + NTSTATUS Status; + WCHAR UnicodeChar = L'\0'; + WCHAR UnicodeChar2 = L'\0'; + UCHAR Char; + UCHAR Trail1; + UCHAR Trail2; + UCHAR Trail3; + ULONG CharToSkip; + + // + // validate it as a valid url character + // + + if (UrlPart != QueryString) + { + if (IS_URL_TOKEN((UCHAR)pChar[0]) == FALSE) + { + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + } + else + { + // + // Allow anything but linefeed in the query string. + // + + if (pChar[0] == LF) + { + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + UnicodeChar = (USHORT) (UCHAR)pChar[0]; + CharToSkip = 1; + + // skip all the decoding stuff + goto slash; + } + + // + // need to unescape ? + // + // can't decode the query string. that would be lossy decodeing + // as '=' and '&' characters might be encoded, but have meaning + // to the usermode parser. + // + + if (pChar[0] == '%') + { + Status = Unescape((PUCHAR)pChar, &Char); + if (NT_SUCCESS(Status) == FALSE) + goto end; + CharToSkip = 3; + } + else + { + Char = pChar[0]; + CharToSkip = 1; + } + + if (UrlType == UrlTypeUtf8) + { + // + // convert to unicode, checking for utf8 . + // + // 3 byte runs are the largest we can have. 16 bits in UCS-2 = + // 3 bytes of (4+4,2+6,2+6) where it's code + char. + // for a total of 6+6+4 char bits = 16 bits. + // + + // + // NOTE: we'll only bother to decode utf if it was escaped + // thus the (CharToSkip == 3) + // + if ((CharToSkip == 3) && ((Char & 0xf8) == 0xf0)) + { + // 4 byte run + // + + // Unescape the next 3 trail bytes + // + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail1); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail2); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail3); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + if (IS_UTF8_TRAILBYTE(Trail1) == FALSE || + IS_UTF8_TRAILBYTE(Trail2) == FALSE || + IS_UTF8_TRAILBYTE(Trail3) == FALSE) + { + // bad utf! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + // handle four byte case - convert to utf-16 + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + UnicodeChar = ((USHORT) ((Char & 0x07) << 8) | + ((Trail1 & 0x3f) << 2) | + ((Trail2 & 0x30) >> 4)) + 0xD7C0; + UnicodeChar2 = ((USHORT) ((Trail2 & 0x0f) << 6) | + (Trail3 & 0x3f)) | 0xDC00; + } + else if ((CharToSkip == 3) && ((Char & 0xf0) == 0xe0)) + { + // 3 byte run + // + + // Unescape the next 2 trail bytes + // + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail1); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail2); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + if (IS_UTF8_TRAILBYTE(Trail1) == FALSE || + IS_UTF8_TRAILBYTE(Trail2) == FALSE) + { + // bad utf! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + // handle three byte case + // 1110xxxx 10xxxxxx 10xxxxxx + + UnicodeChar = (USHORT) (((Char & 0x0f) << 12) | + ((Trail1 & 0x3f) << 6) | + (Trail2 & 0x3f)); + + } + else if ((CharToSkip == 3) && ((Char & 0xe0) == 0xc0)) + { + // 2 byte run + // + + // Unescape the next 1 trail byte + // + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail1); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + if (IS_UTF8_TRAILBYTE(Trail1) == FALSE) + { + // bad utf! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + // handle two byte case + // 110xxxxx 10xxxxxx + + UnicodeChar = (USHORT) (((Char & 0x1f) << 6) | + (Trail1 & 0x3f)); + + } + + // now this can either be unescaped high-bit (bad) + // or escaped high-bit. (also bad) + // + // thus not checking CharToSkip + // + + else if ((Char & 0x80) == 0x80) + { + // high bit set ! bad utf! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + + } + // + // Normal character (again either escaped or unescaped) + // + else + { + // + // Simple conversion to unicode, it's 7-bit ascii. + // + + UnicodeChar = (USHORT)Char; + } + + } + else // UrlType != UrlTypeUtf8 + { + UCHAR AnsiChar[2]; + ULONG AnsiCharSize; + + // + // Convert ANSI character to Unicode. + // If the UrlType is UrlTypeDbcs, then we may have + // a DBCS lead/trail pair. + // + + if (UrlType == UrlTypeDbcs && IS_LEAD_BYTE(Char)) + { + UCHAR SecondByte; + + // + // This is a double-byte character. + // + + SecondByte = *(pChar+CharToSkip); + + AnsiCharSize = 2; + AnsiChar[0] = Char; + + if (SecondByte == '%') + { + Status = Unescape((PUCHAR)pChar+CharToSkip, &AnsiChar[1]); + if (!NT_SUCCESS(Status)) + { + goto end; + } + + CharToSkip += 3; // %xx + } + else + { + AnsiChar[1] = SecondByte; + CharToSkip += 1; + } + + } + else + { + // + // This is a single-byte character. + // + + AnsiCharSize = 1; + AnsiChar[0] = Char; + + } + /* + Status = RtlMultiByteToUnicodeN( + &UnicodeChar, + sizeof(WCHAR), + NULL, + (PCHAR) &AnsiChar[0], + AnsiCharSize + ); + */ + Status = MultiByteToWideChar( + CP_ACP, + 0, + (PCHAR) &AnsiChar[0], + AnsiCharSize, + &UnicodeChar, + sizeof(WCHAR) + ); + + if (!NT_SUCCESS(Status)) + { + goto end; + } + } + + +slash: + // + // turn backslashes into forward slashes + // + + if (UrlPart != QueryString && UnicodeChar == L'\\') + { + UnicodeChar = L'/'; + } + else if (UnicodeChar == UNICODE_NULL) + { + // + // we pop'd a NULL. bad! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + *pCharToSkip = CharToSkip; + *pUnicodeChar = UnicodeChar; + *pUnicodeChar2 = UnicodeChar2; + + Status = STATUS_SUCCESS; + +end: + return Status; + +} // PopChar + + +// +// Private constants. +// + +#define ACTION_NOTHING 0x00000000 +#define ACTION_EMIT_CH 0x00010000 +#define ACTION_EMIT_DOT_CH 0x00020000 +#define ACTION_EMIT_DOT_DOT_CH 0x00030000 +#define ACTION_BACKUP 0x00040000 +#define ACTION_MASK 0xFFFF0000 + +// +// Private globals +// + +// +// this table says what to do based on the current state and the current +// character +// +ULONG pActionTable[16] = +{ + // + // state 0 = fresh, seen nothing exciting yet + // + ACTION_EMIT_CH, // other = emit it state = 0 + ACTION_EMIT_CH, // "." = emit it state = 0 + ACTION_NOTHING, // EOS = normal finish state = 4 + ACTION_EMIT_CH, // "/" = we saw the "/", emit it state = 1 + + // + // state 1 = we saw a "/" ! + // + ACTION_EMIT_CH, // other = emit it, state = 0 + ACTION_NOTHING, // "." = eat it, state = 2 + ACTION_NOTHING, // EOS = normal finish state = 4 + ACTION_NOTHING, // "/" = extra slash, eat it, state = 1 + + // + // state 2 = we saw a "/" and ate a "." ! + // + ACTION_EMIT_DOT_CH, // other = emit the dot we ate. state = 0 + ACTION_NOTHING, // "." = eat it, a .. state = 3 + ACTION_NOTHING, // EOS = normal finish state = 4 + ACTION_NOTHING, // "/" = we ate a "/./", swallow it state = 1 + + // + // state 3 = we saw a "/" and ate a ".." ! + // + ACTION_EMIT_DOT_DOT_CH, // other = emit the "..". state = 0 + ACTION_EMIT_DOT_DOT_CH, // "." = 3 dots, emit the ".." state = 0 + ACTION_BACKUP, // EOS = we have a "/..\0", backup! state = 4 + ACTION_BACKUP // "/" = we have a "/../", backup! state = 1 +}; + +// +// this table says which newstate to be in given the current state and the +// character we saw +// +ULONG pNextStateTable[16] = +{ + // state 0 + 0 , // other + 0 , // "." + 4 , // EOS + 1 , // "\" + + // state 1 + 0 , // other + 2 , // "." + 4 , // EOS + 1 , // "\" + + // state 2 + 0 , // other + 3 , // "." + 4 , // EOS + 1 , // "\" + + // state 3 + 0 , // other + 0 , // "." + 4 , // EOS + 1 // "\" +}; + +// +// this says how to index into pNextStateTable given our current state. +// +// since max states = 4, we calculate the index by multiplying with 4. +// +#define IndexFromState( st) ( (st) * 4) + + +/***************************************************************************++ + +Routine Description: + + This function can be told to clean up UTF-8, ANSI, or DBCS URLs. + + Unescape + Convert backslash to forward slash + Remove double slashes (empty directiories names) - e.g. // or \\ + Handle /./ + Handle /../ + Convert to unicode + computes the case insensitive hash + +Arguments: + + +Return Value: + + NTSTATUS - Completion status. + + +--***************************************************************************/ +NTSTATUS +UlpCleanAndCopyUrlByType( + IN URL_TYPE UrlType, + IN URL_PART UrlPart, + __inout PWSTR pDestination, + __in_ecount(SourceLength) LPSTR pSource, + IN ULONG SourceLength, + OUT PULONG pBytesCopied, + __deref_opt_out_opt PWSTR * ppQueryString + ) +{ + NTSTATUS Status; + PWSTR pDest; + PUCHAR pChar; + ULONG CharToSkip; + ULONG BytesCopied; + PWSTR pQueryString; + ULONG StateIndex; + WCHAR UnicodeChar; + WCHAR UnicodeChar2 = L'\0'; + BOOLEAN MakeCanonical; + PUSHORT pFastPopChar; + + pDest = pDestination; + pQueryString = NULL; + BytesCopied = 0; + + pChar = (PUCHAR)pSource; + CharToSkip = 0; + + StateIndex = 0; + + MakeCanonical = (UrlPart == AbsPath) ? TRUE : FALSE; + + if (UrlType == UrlTypeUtf8 && UrlPart != QueryString) + { + pFastPopChar = FastPopChars; + } + else + { + pFastPopChar = DummyPopChars; + } + + while (SourceLength > 0) + { + // + // advance ! it's at the top of the loop to enable ANSI_NULL to + // come through ONCE + // + + pChar += CharToSkip; + SourceLength -= CharToSkip; + + // + // well? have we hit the end? + // + + if (SourceLength == 0) + { + UnicodeChar = UNICODE_NULL; + UnicodeChar2 = UNICODE_NULL; + } + else + { + // + // Nope. Peek briefly to see if we hit the query string + // + + if (UrlPart == AbsPath && pChar[0] == '?') + { + DBG_ASSERT(pQueryString == NULL); + + // + // remember it's location + // + + pQueryString = pDest; + + // + // let it fall through ONCE to the canonical + // in order to handle a trailing "/.." like + // "http://hostname:80/a/b/..?v=1&v2" + // + + UnicodeChar = L'?'; + UnicodeChar2 = UNICODE_NULL; + CharToSkip = 1; + + // + // now we are cleaning the query string + // + + UrlPart = QueryString; + + // + // cannot use fast path for PopChar anymore + // + + pFastPopChar = DummyPopChars; + } + else + { + USHORT NextUnicodeChar = pFastPopChar[*pChar]; + + // + // Grab the next character. Try to be fast for the + // normal character case. Otherwise call PopChar. + // + + if (NextUnicodeChar == 0) + { + Status = PopChar( + UrlType, + UrlPart, + (LPSTR)pChar, + &UnicodeChar, + &UnicodeChar2, + &CharToSkip + ); + + if (NT_SUCCESS(Status) == FALSE) + goto end; + } + else + { +#if DBG + Status = PopChar( + UrlType, + UrlPart, + (LPSTR)pChar, + &UnicodeChar, + &UnicodeChar2, + &CharToSkip + ); + + DBG_ASSERT(NT_SUCCESS(Status)); + DBG_ASSERT(UnicodeChar == NextUnicodeChar); + DBG_ASSERT(CharToSkip == 1); +#endif + UnicodeChar = NextUnicodeChar; + UnicodeChar2 = UNICODE_NULL; + CharToSkip = 1; + } + } + } + + if (MakeCanonical) + { + // + // now use the state machine to make it canonical . + // + + // + // from the old value of StateIndex, figure out our new base StateIndex + // + StateIndex = IndexFromState(pNextStateTable[StateIndex]); + + // + // did we just hit the query string? this will only happen once + // that we take this branch after hitting it, as we stop + // processing after hitting it. + // + + if (UrlPart == QueryString) + { + // + // treat this just like we hit a NULL, EOS. + // + + StateIndex += 2; + } + else + { + // + // otherwise based the new state off of the char we + // just popped. + // + + switch (UnicodeChar) + { + case UNICODE_NULL: StateIndex += 2; break; + case L'.': StateIndex += 1; break; + case L'/': StateIndex += 3; break; + default: StateIndex += 0; break; + } + } + + } + else + { + StateIndex = (UnicodeChar == UNICODE_NULL) ? 2 : 0; + } + + // + // Perform the action associated with the state. + // + + switch (pActionTable[StateIndex]) + { + case ACTION_EMIT_DOT_DOT_CH: + + EMIT_CHAR(L'.'); + + // fall through + + case ACTION_EMIT_DOT_CH: + + EMIT_CHAR(L'.'); + + // fall through + + case ACTION_EMIT_CH: + + EMIT_CHAR(UnicodeChar); + if (UnicodeChar2 != UNICODE_NULL) + { + EMIT_CHAR(UnicodeChar2); + } + + // fall through + + case ACTION_NOTHING: + break; + + case ACTION_BACKUP: + + // + // pDest currently points 1 past the last '/'. backup over it and + // find the preceding '/', set pDest to 1 past that one. + // + + // + // backup to the '/' + // + + pDest -= 1; + BytesCopied -= 2; + + DBG_ASSERT(pDest[0] == L'/'); + + // + // are we at the start of the string? that's bad, can't go back! + // + + if (pDest == pDestination) + { + DBG_ASSERT(BytesCopied == 0); + Status = STATUS_OBJECT_PATH_INVALID; + goto end; + } + + // + // back up over the '/' + // + + pDest -= 1; + BytesCopied -= 2; + + DBG_ASSERT(pDest > pDestination); + + // + // now find the previous slash + // + + while (pDest > pDestination && pDest[0] != L'/') + { + pDest -= 1; + BytesCopied -= 2; + } + + // + // we already have a slash, so don't have to store 1. + // + + DBG_ASSERT(pDest[0] == L'/'); + + // + // simply skip it, as if we had emitted it just now + // + + pDest += 1; + BytesCopied += 2; + + break; + + default: + DBG_ASSERT(!"http!UlpCleanAndCopyUrl: Invalid action code in state table!"); + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + // + // Just hit the query string ? + // + + if (MakeCanonical && UrlPart == QueryString) + { + // + // Stop canonical processing + // + + MakeCanonical = FALSE; + + // + // Need to emit the '?', it wasn't emitted above + // + + DBG_ASSERT(pActionTable[StateIndex] != ACTION_EMIT_CH); + + EMIT_CHAR(L'?'); + + } + + } + + // + // terminate the string, it hasn't been done in the loop + // + + DBG_ASSERT((pDest-1)[0] != UNICODE_NULL); + + pDest[0] = UNICODE_NULL; + *pBytesCopied = BytesCopied; + + if (ppQueryString != NULL) + { + *ppQueryString = pQueryString; + } + + Status = STATUS_SUCCESS; + + +end: + return Status; + +} // UlpCleanAndCopyUrlByType + + +/***************************************************************************++ + +Routine Description: + + + Unescape + Convert backslash to forward slash + Remove double slashes (empty directiories names) - e.g. // or \\ + Handle /./ + Handle /../ + Convert to unicode + +Arguments: + +Return Value: + + HRESULT + + +--***************************************************************************/ +HRESULT +UlCleanAndCopyUrl( + __in LPSTR pSource, + IN ULONG SourceLength, + OUT PULONG pBytesCopied, + __inout PWSTR pDestination, + __deref_opt_out_opt PWSTR * ppQueryString OPTIONAL + ) +{ + NTSTATUS Status; + URL_TYPE AnsiUrlType = g_UlEnableDBCS ? UrlTypeDbcs : UrlTypeAnsi; + + if (!g_UlEnableNonUTF8) + { + // + // Only accept UTF-8 URLs. + // + + Status = UlpCleanAndCopyUrlByType( + UrlTypeUtf8, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + } + else if (!g_UlFavorDBCS) + { + // + // The URL may be either UTF-8 or ANSI. First + // try UTF-8, and if that fails go for ANSI. + // + + Status = UlpCleanAndCopyUrlByType( + UrlTypeUtf8, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + if (!NT_SUCCESS(Status)) + { + Status = UlpCleanAndCopyUrlByType( + AnsiUrlType, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + } + + } + else + { + // + // The URL may be either ANSI or UTF-8. First + // try the ANSI interpretation, and if that fails + // go for UTF-8. + // + Status = UlpCleanAndCopyUrlByType( + AnsiUrlType, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + if (!NT_SUCCESS(Status)) + { + Status = UlpCleanAndCopyUrlByType( + UrlTypeUtf8, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + } + } + + // + // Convert NTSTATUS to HRESULT + // + + if ( Status == STATUS_SUCCESS ) + { + return S_OK; + } + else + { + DWORD dwErr = 0; + if (SUCCEEDED(WIN32_FROM_NTSTATUS( Status, &dwErr ))) + { + return HRESULT_FROM_WIN32( dwErr ); + } + else + { + return Status; + } + } +} + +HRESULT +UlInitializeParsing( + VOID +) +{ + ULONG i; + UCHAR c; + HKEY hKey; + DWORD dwType; + DWORD dwData; + DWORD cbData; + + // + // First read the HTTP registry settings on how to handle URLs + // + + g_UlEnableNonUTF8 = TRUE; + g_UlEnableDBCS = FALSE; + g_UlFavorDBCS = FALSE; + + if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, + L"System\\CurrentControlSet\\Services\\http\\Parameters", + 0, + KEY_READ, + &hKey ) == ERROR_SUCCESS ) + { + cbData = sizeof( dwData ); + + if ( RegQueryValueEx( hKey, + L"EnableNonUTF8", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_UlEnableNonUTF8 = !!dwData; + } + + cbData = sizeof( dwData ); + + if ( g_UlEnableNonUTF8 ) + { + if ( RegQueryValueEx( hKey, + L"EnableDBCS", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_UlEnableDBCS = !!dwData; + } + } + else + { + g_UlEnableDBCS = FALSE; + } + + cbData = sizeof( dwData ); + + if ( g_UlEnableDBCS ) + { + if ( RegQueryValueEx( hKey, + L"FavorDBCS", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_UlFavorDBCS = !!dwData; + } + } + else + { + g_UlFavorDBCS = FALSE; + } + + RegCloseKey( hKey ); + } + + + // Initialize the HttpChars array appropriately. + + for (i = 0; i < 128; i++) + { + HttpChars[i] = HTTP_CHAR; + } + + for (i = 'A'; i <= 'Z'; i++) + { + HttpChars[i] |= HTTP_UPCASE; + } + + for (i = 'a'; i <= 'z'; i++) + { + HttpChars[i] |= HTTP_LOCASE; + } + + for (i = '0'; i <= '9'; i++) + { + HttpChars[i] |= (HTTP_DIGIT | HTTP_HEX); + } + + + for (i = 0; i <= 31; i++) + { + HttpChars[i] |= HTTP_CTL; + } + + HttpChars[127] |= HTTP_CTL; + + HttpChars[SP] |= HTTP_LWS; + HttpChars[HT] |= HTTP_LWS; + + + for (i = 'A'; i <= 'F'; i++) + { + HttpChars[i] |= HTTP_HEX; + } + + for (i = 'a'; i <= 'f'; i++) + { + HttpChars[i] |= HTTP_HEX; + } + + HttpChars['('] |= HTTP_SEPERATOR; + HttpChars[')'] |= HTTP_SEPERATOR; + HttpChars['<'] |= HTTP_SEPERATOR; + HttpChars['>'] |= HTTP_SEPERATOR; + HttpChars['@'] |= HTTP_SEPERATOR; + HttpChars[','] |= HTTP_SEPERATOR; + HttpChars[';'] |= HTTP_SEPERATOR; + HttpChars[':'] |= HTTP_SEPERATOR; + HttpChars['\\'] |= HTTP_SEPERATOR; + HttpChars['"'] |= HTTP_SEPERATOR; + HttpChars['/'] |= HTTP_SEPERATOR; + HttpChars['['] |= HTTP_SEPERATOR; + HttpChars[']'] |= HTTP_SEPERATOR; + HttpChars['?'] |= HTTP_SEPERATOR; + HttpChars['='] |= HTTP_SEPERATOR; + HttpChars['{'] |= HTTP_SEPERATOR; + HttpChars['}'] |= HTTP_SEPERATOR; + HttpChars[SP] |= HTTP_SEPERATOR; + HttpChars[HT] |= HTTP_SEPERATOR; + + + // + // URL "reserved" characters (rfc2396) + // + + HttpChars[';'] |= URL_LEGAL; + HttpChars['/'] |= URL_LEGAL; + HttpChars['\\'] |= URL_LEGAL; + HttpChars['?'] |= URL_LEGAL; + HttpChars[':'] |= URL_LEGAL; + HttpChars['@'] |= URL_LEGAL; + HttpChars['&'] |= URL_LEGAL; + HttpChars['='] |= URL_LEGAL; + HttpChars['+'] |= URL_LEGAL; + HttpChars['$'] |= URL_LEGAL; + HttpChars[','] |= URL_LEGAL; + + + // + // URL escape character + // + + HttpChars['%'] |= URL_LEGAL; + + // + // URL "mark" characters (rfc2396) + // + + HttpChars['-'] |= URL_LEGAL; + HttpChars['_'] |= URL_LEGAL; + HttpChars['.'] |= URL_LEGAL; + HttpChars['!'] |= URL_LEGAL; + HttpChars['~'] |= URL_LEGAL; + HttpChars['*'] |= URL_LEGAL; + HttpChars['\''] |= URL_LEGAL; + HttpChars['('] |= URL_LEGAL; + HttpChars[')'] |= URL_LEGAL; + + + // + // RFC2396 describes these characters as `unwise' "because gateways and + // other transport agents are known to sometimes modify such characters, + // or they are used as delimiters". However, for compatibility with + // IIS 5.0 and DAV, we must allow these unwise characters in URLs. + // + + HttpChars['{'] |= URL_LEGAL; + HttpChars['}'] |= URL_LEGAL; + HttpChars['|'] |= URL_LEGAL; + HttpChars['^'] |= URL_LEGAL; + HttpChars['['] |= URL_LEGAL; + HttpChars[']'] |= URL_LEGAL; + HttpChars['`'] |= URL_LEGAL; + + // + // '#', '%', and '"' are not considered URL_LEGAL, according to the RFC. + // However, IIS 5.0 allowed them, so we should too. + // + + HttpChars['#'] |= URL_LEGAL; + HttpChars['%'] |= URL_LEGAL; + HttpChars['"'] |= URL_LEGAL; + + // + // In DBCS locales we need to explicitly accept lead bytes which + // we would normally reject. + // + + if (0) // BUGBUG + { + for (i = 0; i < DBCS_TABLE_SIZE; i++) + { + if (IS_LEAD_BYTE((BYTE)i)) + { + HttpChars[i] |= URL_LEGAL; + } + } + } + + // + // These US-ASCII characters are "excluded"; i.e. not URL_LEGAL (see RFC): + // '<' | '>' | ' ' (0x20) + // In addition, control characters (0x00-0x1F and 0x7F) and + // non US-ASCII characters (0x80-0xFF) are not URL_LEGAL. + // + + for (i = 0; i < 128; i++) + { + if (!IS_HTTP_SEPERATOR(i) && !IS_HTTP_CTL(i)) + { + HttpChars[i] |= HTTP_TOKEN; + } + } + + + // + // Fast path for PopChar + // + + RtlZeroMemory(FastPopChars, 256 * sizeof(USHORT)); + RtlZeroMemory(DummyPopChars, 256 * sizeof(USHORT)); + + for (i = 0; i < 256; i++) + { + c = (UCHAR)i; + + if (IS_URL_TOKEN(c) && c != '%' && (c & 0x80) != 0x80) + { + FastPopChars[i] = (USHORT)c; + } + } + + // + // Turn backslashes into forward slashes + // + + FastPopChars['\\'] = L'/'; + + + // + // Fast path for UpcaseUnicodeChar + // + + for (i = 0; i < 256; i++) + { + FastUpcaseChars[i] = towupper((WCHAR)i); + } + + + return S_OK; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx new file mode 100644 index 0000000000..22c31a0ed2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +MakePathCanonicalizationProof( + IN PCWSTR pszName, + OUT STRU * pstrPath +) +/*++ + +Routine Description: + + This functions adds a prefix + to the string, which is "\\?\UNC\" for a UNC path, and "\\?\" for + other paths. This prefix tells Windows not to parse the path. + +Arguments: + + IN pszName - The path to be converted + OUT pstrPath - Output path created + +Return Values: + + HRESULT + +--*/ +{ + HRESULT hr; + + if (pszName[0] == L'\\' && pszName[1] == L'\\') + { + // + // If the path is already canonicalized, just return + // + + if ((pszName[2] == '?' || pszName[2] == '.') && + pszName[3] == '\\') + { + hr = pstrPath->Copy(pszName); + + if (SUCCEEDED(hr)) + { + // + // If the path was in DOS form ("\\.\"), + // we need to change it to Win32 from ("\\?\") + // + + pstrPath->QueryStr()[2] = L'?'; + } + + return hr; + } + + pszName += 2; + + + if (FAILED(hr = pstrPath->Copy(L"\\\\?\\UNC\\"))) + { + return hr; + } + } + else + { + if (FAILED(hr = pstrPath->Copy(L"\\\\?\\"))) + { + return hr; + } + } + + return pstrPath->Append(pszName); +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h new file mode 100644 index 0000000000..04e13789f0 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h @@ -0,0 +1,1013 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STBUFF_H +#define _STBUFF_H + +#include +#include + +#define STB_INLINE_SIZE 64 +#define STB_MAX_ALLOC 16*1024 + +#define TO_UPPER(ch) (isupper(ch) ? ch : toupper(ch)) + +class STBUFF +{ +public: + + STBUFF( + BOOL fZeroInit = TRUE + ) : _pData( _Inline ), + _cbData( 0 ), + _cbBuffer( STB_INLINE_SIZE ), + _cbMaxAlloc( STB_MAX_ALLOC ) + { + if ( fZeroInit ) + { + ZeroInit(); + } + + _Inline[STB_INLINE_SIZE] = 0; + _Inline[STB_INLINE_SIZE+1] = 0; + } + + virtual + ~STBUFF() + { + Reset( TRUE ); + } + + VOID + Reset( + BOOL fFreeAlloc = FALSE + ) + { + // + // If we are supposed to free any heap + // allocations, do so now. + // + + if ( fFreeAlloc && + _pData != _Inline ) + { + LocalFree( _pData ); + _pData = _Inline; + _cbBuffer = STB_INLINE_SIZE; + } + + // + // Reset the data size + // + + _cbData = 0; + } + + HRESULT + Resize( + DWORD cbSize + ) + { + HRESULT hr = S_OK; + BYTE * pTemp; + + // + // If the buffer is large enough, just return + // + + if ( cbSize < _cbBuffer ) + { + goto Finished; + } + + // + // If the requested size exceeds our maximum + // allocation, then fail this call. + // + + if ( cbSize > _cbMaxAlloc ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + // + // Adjust the allocation size so that we allocate + // in chunks of MINITOOLS_INLINE_SIZE. Don't + // exeed _cbMaxAlloc. + // + + if ( cbSize % STB_INLINE_SIZE ) + { + cbSize = ( cbSize / STB_INLINE_SIZE + 1 ) * + STB_INLINE_SIZE; + } + + if ( cbSize > _cbMaxAlloc ) + { + cbSize = _cbMaxAlloc; + } + + // + // Allocate the new storage and copy any existing + // data into it. + // + // Allocate two extra bytes so that we can guarantee + // NULL termination when someone queries the data + // pointer as a string. + // + + pTemp = (BYTE*)LocalAlloc( LPTR, cbSize + 2 ); + + if ( !pTemp ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + if ( _cbData ) + { + CopyMemory( pTemp, _pData, _cbData ); + } + + // + // If the original buffer is not the inline + // storage, then free it. + // + + if ( _pData != _Inline ) + { + LocalFree( _pData ); + } + + // + // Save the new storage pointer + // + + _pData = pTemp; + _cbBuffer = cbSize; + + // + // Set the extra two bytes as 0 + // + + _pData[_cbBuffer] = 0; + _pData[_cbBuffer+1] = 0; + +Finished: + return hr; + } + + HRESULT + AppendData( + VOID * pData, + DWORD cbData, + DWORD Offset = 0xffffffff + ) + { + DWORD cbNeeded; + HRESULT hr = S_OK; + + // + // Resize the buffer if necessary + // + + cbNeeded = Offset + cbData; + + hr = Resize( cbNeeded ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + // + // Copy the new data + // + + if ( cbData ) + { + CopyMemory( _pData + Offset, pData, cbData ); + } + + _cbData = cbNeeded; + + // + // NULL terminate the data + // + + GuaranteeNullTermination(); + +Finished: + + return hr; + } + + + HRESULT + AppendData( + LPCSTR szData, + DWORD cchData = 0xffffffff, + DWORD Offset = 0xffffffff + ) + { + // + // If cchData is 0xffffffff, then calculate size + // + + if ( cchData == 0xffffffff ) + { + cchData = (DWORD)strlen( szData ); + } + + // + // If offset is 0xffffffff, then assume + // that we are appending to the end of the + // string. + // + + if ( Offset == 0xffffffff ) + { + Offset = _cbData; + } + + return AppendData( (VOID*)szData, + cchData, + Offset ); + } + + HRESULT + AppendData( + LPCWSTR szData, + DWORD cchData = 0xffffffff, + DWORD cchOffset = 0xffffffff + ) + { + DWORD cbData; + DWORD cbOffset; + // + // If cchData is 0xffffffff, then calculate size + // + + if ( cchData == 0xffffffff ) + { + cchData = (DWORD)wcslen( szData ); + } + + cbData = cchData * sizeof(WCHAR); + + // + // If offset is 0xffffffff, then assume + // that we are appending to the end of the + // string. + // + + if ( cchOffset == 0xffffffff ) + { + cchOffset = _cbData; + } + + cbOffset = cchOffset * sizeof(WCHAR); + + return AppendData( (VOID*)szData, + cbData, + cbOffset ); + } + + HRESULT + AppendData( + STBUFF *pbuff + ) + { + return AppendData( pbuff->QueryPtr(), + pbuff->QueryDataSize() ); + } + + HRESULT + SetData( + VOID * pData, + DWORD cbData + ) + { + // + // Set data is just an append to offset zero + // + + return AppendData( pData, + cbData, + 0 ); + } + + HRESULT + SetData( + LPCSTR pData, + DWORD cchData = 0xffffffff + ) + { + // + // If cbData is 0xffffffff, then assume that + // pData is a NULL terminated string. + // + + if ( cchData == 0xffffffff ) + { + cchData = (DWORD)strlen( (LPSTR)pData ); + } + + return SetData( (VOID*)pData, cchData ); + } + + HRESULT + SetData( + LPCWSTR pData, + DWORD cchData = 0xffffffff + ) + { + // + // If cbData is 0xffffffff, then assume that + // pData is a NULL terminated string. + // + + if ( cchData == 0xffffffff ) + { + cchData = (DWORD)wcslen( (LPWSTR)pData ); + } + + return SetData( (VOID*)pData, cchData * sizeof(WCHAR) ); + } + + + HRESULT + SetData( + STBUFF *pbuff + ) + { + return AppendData( pbuff->QueryPtr(), + pbuff->QueryDataSize(), + 0 ); + } + + HRESULT + AnsiToUnicode( + LPCSTR szString, + UINT codepage = CP_UTF8 + ) + { + DWORD cchString = (DWORD)strlen( szString ); + HRESULT hr = S_OK; + + hr = Resize( cchString * sizeof(WCHAR) ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + if ( !MultiByteToWideChar( codepage, + MB_ERR_INVALID_CHARS, + szString, + cchString, + (LPWSTR)_pData, + cchString ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + + _cbData = cchString * sizeof(WCHAR); + +Finished: + + return hr; + } + + HRESULT + UnicodeToAnsi( + LPCWSTR szStringW, + UINT codepage = CP_UTF8 + ) + { + DWORD cchString = (DWORD)wcslen( szStringW ); + HRESULT hr = S_OK; + + hr = Resize( cchString ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + if ( !WideCharToMultiByte( codepage, + 0, + szStringW, + cchString, + (LPSTR)_pData, + cchString, + NULL, + NULL ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + + _cbData = cchString; + +Finished: + + return hr; + } + + HRESULT + ExpandEnvironmentStrings( + VOID + ) + { + STBUFF Temp; + DWORD cbNeeded; + HRESULT hr = S_OK; + + cbNeeded = ::ExpandEnvironmentStringsA( QueryStr(), + Temp.QueryStr(), + Temp.QueryBufferSize() ); + + if ( cbNeeded > Temp.QueryBufferSize() ) + { + hr = Temp.Resize ( cbNeeded ); + if ( FAILED (hr) ) + { + goto Finished; + } + + cbNeeded = ::ExpandEnvironmentStringsA( QueryStr(), + Temp.QueryStr(), + Temp.QueryBufferSize() ); + + } + + Temp.CalcDataSize(); + + hr = SetData( &Temp ); + if ( FAILED (hr) ) + { + goto Finished; + } + + Finished: + + return hr; + } + + HRESULT + Vsprintf( + LPCSTR szFormat, + va_list args + ) + { + DWORD cchWritten; + HRESULT hr = S_OK; + + DWORD cbNeeded = _vscprintf( szFormat, args ); + + hr = Resize( cbNeeded + 1 ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + cchWritten = _vsnprintf_s( QueryStr(), + QueryBufferSize(), + QueryBufferSize(), + szFormat, + args ); + + _cbData = cchWritten; + +Finished: + + return hr; + } + + HRESULT + Vsprintf( + LPCWSTR szFormat, + va_list args + ) + { + DWORD cchWritten; + HRESULT hr = S_OK; + + DWORD cbNeeded = _vscwprintf( szFormat, args ) * sizeof(WCHAR); + + hr = Resize( cbNeeded + 1 ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + cchWritten = _vsnwprintf_s( QueryStrW(), + QueryBufferSize() / sizeof(WCHAR), + _TRUNCATE, + szFormat, + args ); + + _cbData = cchWritten * sizeof(WCHAR); + +Finished: + + return hr; + } + + HRESULT + Printf( + LPCSTR szFormat, + ... + ) + { + HRESULT hr; + + // + // Let Vsprintf do the work + // + + va_list args; + + va_start( args, szFormat ); + + hr = Vsprintf( szFormat, + args ); + + va_end( args ); + + return hr; + } + + HRESULT + Printf( + LPCWSTR szFormat, + ... + ) + { + HRESULT hr; + + // + // Let Vsprintf do the work + // + + va_list args; + + va_start( args, szFormat ); + + hr = Vsprintf( szFormat, + args ); + + va_end( args ); + + return hr; + } + + VOID * + QueryPtr() + { + return (VOID*)_pData; + } + + LPSTR + QueryStr() + { + GuaranteeNullTermination(); + + return (LPSTR)_pData; + } + + LPWSTR + QueryStrW() + { + GuaranteeNullTermination(); + + return (LPWSTR)_pData; + } + + DWORD + QueryDataSize() + { + return _cbData; + } + + HRESULT + SetDataSize( + DWORD cbData + ) + { + HRESULT hr = S_OK; + + if ( cbData > _cbBuffer ) + { + hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ); + goto Finished; + } + + _cbData = cbData; + + Finished: + return hr; + } + + VOID + CalcDataSize() + { + _cbData = (DWORD)strlen( (LPSTR)_pData ); + } + + VOID + CalcDataSizeW() + { + _cbData = (DWORD)wcslen( (LPWSTR)_pData ); + } + + DWORD + QueryBufferSize() + { + return _cbBuffer; + } + + DWORD + QueryMaxAlloc() + { + return _cbMaxAlloc; + } + + VOID + SetMaxAlloc( + DWORD cbMaxAlloc + ) + { + _cbMaxAlloc = cbMaxAlloc; + } + + VOID + ZeroInit( + VOID + ) + { + FillMemory( _Inline, STB_INLINE_SIZE, 0x00 ); + + if ( _pData != _Inline ) + { + FillMemory( _pData, _cbBuffer, 0x00 ); + } + } + + HRESULT + Escape( + BOOL fAllowDoubleEscaping = FALSE + ) + { + STBUFF Temp; + DWORD dwNumEscapes = 0; + CHAR szHex[3] = {0}; + BYTE * pRead; + BYTE * pWrite; + HRESULT hr = S_OK; + + // + // Walk through the string once. If there + // are no escapes, then we can just return. + // + + GuaranteeNullTermination(); + + pRead = (BYTE*)_pData; + + while ( *pRead != '\0' ) + { + if ( ( fAllowDoubleEscaping || + !IsEscapeSequence( (CHAR*)pRead ) ) && + ShouldEscape( *pRead ) ) + { + dwNumEscapes++; + } + + pRead++; + } + + if ( dwNumEscapes == 0 ) + { + goto Finished; + } + + // + // Make sure that our cooked string buffer is big enough, so + // we can manipulate its pointer directly. + // + + hr = Temp.Resize( _cbData + dwNumEscapes * 2 ); + if ( FAILED (hr) ) + { + goto Finished; + } + + pRead = (BYTE*)_pData; + pWrite = (BYTE*)Temp.QueryStr(); + + while ( *pRead != '\0' ) + { + if ( ( fAllowDoubleEscaping || + !IsEscapeSequence( (CHAR*)pRead ) ) && + ShouldEscape( *pRead ) ) + { + _snprintf_s( szHex, 3, 2, "%02x", *pRead ); + + *pWrite = '%'; + *(pWrite+1) = szHex[0]; + *(pWrite+2) = szHex[1]; + + pRead++; + pWrite += 3; + + continue; + } + + *pWrite = *pRead; + + pRead++; + pWrite++; + } + + *pWrite = '\0'; + + Temp.CalcDataSize(); + + hr = SetData( Temp.QueryStr() ); + if ( FAILED (hr) ) + { + goto Finished; + } + + Finished: + + return hr; + } + + VOID + Unescape( + VOID + ) + { + CHAR * pRead; + CHAR * pWrite; + CHAR szHex[3] = {0}; + BYTE c; + + pRead = (CHAR*)_pData; + pWrite = pRead; + + while ( *pRead ) + { + if ( IsEscapeSequence( pRead ) ) + { + szHex[0] = *(pRead+1); + szHex[1] = *(pRead+2); + + c = (BYTE)strtoul( szHex, NULL, 16 ); + + *pWrite = c; + + pRead += 3; + pWrite++; + + continue; + } + + *pWrite = *pRead; + + pRead++; + pWrite++; + } + + *pWrite = '\0'; + + CalcDataSize(); + + return; + } + + VOID + MoveToFront( + DWORD cbOffset + ) + { + if ( cbOffset >= _cbData ) + { + Reset(); + + return; + } + + MoveMemory( _pData, _pData + cbOffset, _cbData - cbOffset ); + + _cbData -= cbOffset; + } + + BOOL + IsWildcardMatch( + LPCSTR szExpr + ) + { + LPCSTR pExpr = szExpr; + LPCSTR pString = QueryStr(); + LPCSTR pSubMatch; + DWORD cchSubMatch; + + if ( !pExpr ) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + while ( *pExpr ) + { + switch ( *pExpr ) + { + case '*': + + // + // Eat '*' characters + // + + while ( *pExpr == '*' ) + { + pExpr++; + } + + // + // Find the next wildcard + // + + pSubMatch = strchr( pExpr, '*' ); + + cchSubMatch = (DWORD)(pSubMatch ? + pSubMatch - pExpr : + strlen( pExpr )); + + if ( cchSubMatch == 0 ) + { + // + // No submatch. The rest of + // pString automatically matches + // + + return TRUE; + } + + // + // Ensure that the current submatch exists + // + + while ( _strnicmp( pString, pExpr, cchSubMatch ) ) + { + pString++; + + if ( *pString == '\0' ) + { + // + // Not found + // + + return FALSE; + } + } + + pExpr += cchSubMatch; + pString += cchSubMatch; + + break; + + default: + + if ( TO_UPPER( *pExpr ) != TO_UPPER( *pString ) ) + { + return FALSE; + } + + pExpr++; + pString++; + } + } + + if ( *pString != '\0' ) + { + return FALSE; + } + + return TRUE; + } + +private: + + LPBYTE _pData; + DWORD _cbData; + DWORD _cbBuffer; + DWORD _cbMaxAlloc; + BYTE _Inline[STB_INLINE_SIZE+2]; + + VOID + GuaranteeNullTermination() + { + _pData[_cbData] = 0; + _pData[_cbData+1] = 0; + } + + BOOL + IsEscapeSequence( + CHAR * str + ) + { + if ( *str == '%' && + isxdigit( *(str+1) ) && + isxdigit( *(str+2) ) ) + { + return TRUE; + } + + return FALSE; + } + + BOOL + ShouldEscape( + BYTE c + ) + { + // + // If the character is listed in RFC2396, section + // 2.4.3 as control, space, delims or unwise, we + // should escape it. Also, we should escape characters + // with the high bit set. + // + + if ( c <= 0x1f || + c == 0x7f ) + { + // + // Control character + // + + goto ReturnTrue; + } + + if ( c >= 0x80 ) + { + // + // High bit set + // + + goto ReturnTrue; + } + + switch ( c ) + { + + // + // space + // + case ' ': + + // + // delims + // + case '<': + case '>': + case '#': + case '%': + case '\"': + + // + // unwise + // + case '{': + case '}': + case '|': + case '\\': + case '^': + case '[': + case ']': + case '`': + + goto ReturnTrue; + } + + // + // If we get here, then the character should not be + // escaped + // + + return FALSE; + + ReturnTrue: + + return TRUE; + } +}; + +#endif // _STBUFF_H diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h new file mode 100644 index 0000000000..916c8576a8 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STLIST_H +#define _STLIST_H + +#ifndef IsListEmpty + +#include + +#define IsListEmpty(ListHead) ((ListHead)->Flink == (ListHead)) + +VOID +inline +InitializeListHead( + LIST_ENTRY * ListHead + ) +{ + ListHead->Flink = ListHead->Blink = ListHead; +} + +BOOL +inline +RemoveEntryList( + LIST_ENTRY * Entry + ) +{ + LIST_ENTRY * Blink; + LIST_ENTRY * Flink; + + Flink = Entry->Flink; + Blink = Entry->Blink; + Blink->Flink = Flink; + Flink->Blink = Blink; + return (Flink == Blink); +} + +PLIST_ENTRY +inline +RemoveHeadList( + LIST_ENTRY * ListHead + ) +{ + LIST_ENTRY * Flink; + LIST_ENTRY * Entry; + + Entry = ListHead->Flink; + Flink = Entry->Flink; + ListHead->Flink = Flink; + Flink->Blink = ListHead; + return Entry; +} + +VOID +inline +InsertHeadList( + LIST_ENTRY * ListHead, + LIST_ENTRY * Entry + ) +{ + LIST_ENTRY * Flink; + + Flink = ListHead->Flink; + Entry->Flink = Flink; + Entry->Blink = ListHead; + Flink->Blink = Entry; + ListHead->Flink = Entry; +} + +VOID +inline +InsertTailList( + LIST_ENTRY * ListHead, + LIST_ENTRY * Entry + ) +{ + LIST_ENTRY * Blink; + + Blink = ListHead->Blink; + Entry->Flink = ListHead; + Entry->Blink = Blink; + Blink->Flink = Entry; + ListHead->Blink = Entry; +} + +#endif // IsListEmpty +#endif // _STLIST_H diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h new file mode 100644 index 0000000000..6571489187 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STLOCK_H +#define _STLOCK_H + +class STLOCK +{ +public: + + STLOCK() + : _fInitialized( FALSE ) + { + } + + ~STLOCK() + { + if ( _fInitialized ) + { + DeleteCriticalSection( &_cs ); + CloseHandle( _hReadersDone ); + } + } + + HRESULT + Initialize( + VOID + ) + { + HRESULT hr = S_OK; + BOOL fResult = FALSE; + + if ( !_fInitialized ) + { + _fWriterWaiting = FALSE; + _cReaders = 0; + + fResult = InitializeCriticalSectionAndSpinCount( &_cs, 100 ); + + if ( !fResult ) + { + hr = E_FAIL; + goto Finished; + } + + _hReadersDone = CreateEvent( NULL, + FALSE, + FALSE, + NULL ); + + if ( !_hReadersDone ) + { + DeleteCriticalSection( &_cs ); + hr = E_FAIL; + goto Finished; + } + + _fInitialized = TRUE; + } + +Finished: + return hr; + } + + BOOL + QueryInitialized() const + { + return _fInitialized; + } + + void SharedAcquire() + { + EnterCriticalSection( &_cs ); + InterlockedIncrement( &_cReaders ); + LeaveCriticalSection( &_cs ); + } + + void SharedRelease() + { + ReleaseInternal(); + } + + void ExclusiveAcquire() + { + EnterCriticalSection( &_cs ); + + _fWriterWaiting = TRUE; + + // + // If there are any readers, wait for them + // to release + // + + if ( InterlockedExchangeAdd( &_cReaders, 0 ) > 0 ) + { + WaitForSingleObject( _hReadersDone, INFINITE ); + } + + // + // Reader count -1 indicates that a writer has the lock + // + + _cReaders = -1; + } + + void ExclusiveRelease() + { + ReleaseInternal(); + } + +private: + + BOOL _fInitialized; + BOOL _fWriterWaiting; + LONG _cReaders; + CRITICAL_SECTION _cs; + HANDLE _hReadersDone; + + void ReleaseInternal() + { + LONG cReaders = InterlockedDecrement( &_cReaders ); + + if ( cReaders >= 0 ) + { + // + // Released a read lock. If this was the last + // reader and writers are waiting, set the + // readers done event + // + + if ( ( _fWriterWaiting ) && ( cReaders == 0 ) ) + { + SetEvent( _hReadersDone ); + } + } + else + { + // + // Released a write lock + // + + _cReaders = 0; + _fWriterWaiting = FALSE; + LeaveCriticalSection( &_cs ); + } + } +}; + +#endif // _STLOCK_H \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h new file mode 100644 index 0000000000..0fd629af3d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h @@ -0,0 +1,599 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STTABLE_H +#define _STTABLE_H + +#include +#include +#include "stbuff.h" +#include "stlock.h" +#include "stlist.h" + +#define DEFAULT_BUCKETS 97 // largest prime under 100 + +class ITEM; +class STTABLE_ITEM; + +typedef DWORD (WINAPI * PFN_HASH)(STBUFF*); +typedef BOOL (WINAPI * PFN_COMPARE_KEYS)(STBUFF*,STBUFF*); +typedef VOID (WINAPI * PFN_ITER)(STTABLE_ITEM*, BOOL*); + +class STTABLE_ITEM +{ +public: + + STTABLE_ITEM() + : _cRefs( 1 ) + { + InitializeListHead( &le ); + } + + VOID + Reference() + { + InterlockedIncrement( &_cRefs ); + } + + VOID + Dereference() + { + LONG cRefs = InterlockedDecrement( &_cRefs ); + + if ( cRefs == 0 ) + { + delete this; + } + } + + HRESULT + Initialize( + STBUFF * pKey + ) + { + return _buffKey.SetData( pKey->QueryPtr(), + pKey->QueryDataSize() ); + } + + STBUFF * + QueryKey() + { + return &_buffKey; + } + + virtual + ~STTABLE_ITEM() + {} + + LIST_ENTRY le; + +private: + + LONG _cRefs; + STBUFF _buffKey; +}; + +class STTABLE_BUCKET +{ +public: + + STTABLE_BUCKET() + : _pfnCompareKeys( NULL ) + {} + + virtual + ~STTABLE_BUCKET() + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + + while ( !IsListEmpty( &_Head ) ) + { + pEntry = RemoveHeadList( &_Head ); + + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + pItem->Dereference(); + pItem = NULL; + } + } + + HRESULT + Initialize( + PFN_COMPARE_KEYS pfnCompareKeys = NULL + ) + { + InitializeListHead( &_Head ); + + _pfnCompareKeys = pfnCompareKeys; + + return _BucketLock.Initialize(); + } + + HRESULT + Insert( + STTABLE_ITEM * pNewItem + ) + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + HRESULT hr = S_OK; + + _BucketLock.ExclusiveAcquire(); + + // + // Check to see if the item is already in the list + // + + pEntry = _Head.Flink; + + while ( pEntry != &_Head ) + { + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + if ( CompareKeys( pNewItem->QueryKey(), + pItem->QueryKey() ) ) + { + hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); + goto Finished; + } + + pEntry = pEntry->Flink; + } + + // + // It's not in the list. Add it now + // + + pNewItem->Reference(); + InsertTailList( &_Head, &pNewItem->le ); + +Finished: + + _BucketLock.ExclusiveRelease(); + + return hr; + } + + HRESULT + Remove( + STTABLE_ITEM * pItemToRemove + ) + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + + _BucketLock.ExclusiveAcquire(); + + // + // Find the item in the list + // + + pEntry = _Head.Flink; + + while ( pEntry != &_Head ) + { + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + if ( CompareKeys( pItemToRemove->QueryKey(), + pItem->QueryKey() ) ) + { + RemoveEntryList( &pItemToRemove->le ); + pItemToRemove->Dereference(); + pItemToRemove = NULL; + + goto Finished; + } + + pEntry = pEntry->Flink; + } + + // + // Item was not found. Set error code, but + // don't fail function. + // + + SetLastError (ERROR_FILE_NOT_FOUND); + +Finished: + + _BucketLock.ExclusiveRelease(); + + return S_OK; + } + + HRESULT + GetItem( + STBUFF * pKey, + STTABLE_ITEM **ppItem + ) + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + HRESULT hr = S_OK; + + _BucketLock.SharedAcquire(); + + // + // Find the item in the list + // + + pEntry = _Head.Flink; + + while ( pEntry != &_Head ) + { + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + if ( CompareKeys( pKey, + pItem->QueryKey() ) ) + { + pItem->Reference(); + goto Finished; + } + + pEntry = pEntry->Flink; + } + + // + // Item was not found. + // + + pItem = NULL; + + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + +Finished: + + _BucketLock.SharedRelease(); + + *ppItem = pItem; + + return hr; + } + + VOID + Iterate( + PFN_ITER pIterFunction + ) + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + BOOL fRemoveItem; + + //////////////////////////////////////// + // + // It is assumed that this function will + // be called under a write lock + // + //////////////////////////////////////// + + // + // Walk the list and call the provided + // function on each item + // + + pEntry = _Head.Flink; + + while ( pEntry != &_Head ) + { + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + // + // The iterator function might remove + // the item from the list, so we need + // to get the next link first + // + + pEntry = pEntry->Flink; + + pItem->Reference(); + pIterFunction( pItem, &fRemoveItem ); + + if ( fRemoveItem ) + { + RemoveEntryList( &pItem->le ); + pItem->Dereference(); + pItem = NULL; + } + } + + } + +private: + + LIST_ENTRY _Head; + STLOCK _BucketLock; + PFN_COMPARE_KEYS _pfnCompareKeys; + + BOOL + CompareKeys( + STBUFF * pKey1, + STBUFF * pKey2 + ) + { + if ( _pfnCompareKeys ) + { + return _pfnCompareKeys( pKey1, + pKey2 ); + } + + return ( strcmp( pKey1->QueryStr(), + pKey2->QueryStr() ) == 0 ); + } +}; + + +class STTABLE +{ +public: + + STTABLE() + : _cBuckets( 0 ), + _pfnHash( NULL ) + {} + + virtual + ~STTABLE() + { + STTABLE_BUCKET ** rgBuckets; + STTABLE_BUCKET * pBucket; + DWORD n; + + rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr(); + + for( n = 0; n < _cBuckets; n++ ) + { + pBucket = rgBuckets[n]; + + delete pBucket; + pBucket = NULL; + } + } + + HRESULT + Initialize( + DWORD cBuckets = DEFAULT_BUCKETS, + PFN_HASH pfnHash = NULL, + PFN_COMPARE_KEYS pfnCompareKeys = NULL + ) + { + STTABLE_BUCKET ** rgBuckets; + DWORD n; + HRESULT hr = S_OK; + + // + // Create a buffer for the bucket array + // + + hr = _buffBucketPtrs.Resize( cBuckets * sizeof(STTABLE_BUCKET*) ); + + if ( FAILED (hr) ) + { + goto Finished; + } + + rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr(); + + // + // Create the buckets + // + + for ( n = 0; n < cBuckets; n++ ) + { + STTABLE_BUCKET * pNewBucket = new STTABLE_BUCKET; + + if ( !pNewBucket ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + hr = pNewBucket->Initialize( pfnCompareKeys ); + + if ( FAILED (hr) ) + { + delete pNewBucket; + pNewBucket = NULL; + + goto Finished; + } + + rgBuckets[n] = pNewBucket; + pNewBucket = NULL; + + _cBuckets++; + } + + // + // Initialize the table lock + // + + _TableLock.Initialize(); + + // + // Set the hash function + // + + _pfnHash = pfnHash; + +Finished: + return hr; + } + + HRESULT + Insert( + STTABLE_ITEM * pNewItem + ) + { + + DWORD dwHash; + STTABLE_BUCKET * pBucket; + HRESULT hr = S_OK; + + dwHash = ComputeHash( pNewItem->QueryKey() ); + + pBucket = GetBucket( dwHash ); + + _TableLock.SharedAcquire(); + + hr = pBucket->Insert( pNewItem ); + + _TableLock.SharedRelease(); + + return hr; + } + + HRESULT + Remove( + STTABLE_ITEM * pItemToRemove + ) + { + DWORD dwHash; + STTABLE_BUCKET * pBucket; + HRESULT hr = S_OK; + + dwHash = ComputeHash( pItemToRemove->QueryKey() ); + + pBucket = GetBucket( dwHash ); + + _TableLock.SharedAcquire(); + + hr = pBucket->Remove( pItemToRemove ); + + _TableLock.SharedRelease(); + + return hr; + } + + HRESULT + GetItem( + STBUFF * pKey, + STTABLE_ITEM **ppItem + ) + { + DWORD dwHash; + STTABLE_BUCKET * pBucket; + STTABLE_ITEM * pRet; + HRESULT hr = S_OK; + + dwHash = ComputeHash( pKey ); + + pBucket = GetBucket( dwHash ); + + _TableLock.SharedAcquire(); + + hr = pBucket->GetItem( pKey, &pRet ); + if(FAILED( hr)) + { + pRet = NULL; + goto Finished; + } + + Finished: + + _TableLock.SharedRelease(); + + *ppItem = pRet; + + return hr; + } + + VOID + Iterate( + PFN_ITER pIterFunction + ) + { + STTABLE_BUCKET ** rgBuckets; + DWORD n; + + _TableLock.ExclusiveAcquire(); + + rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr(); + + // + // Iterate each bucket + // + + for ( n = 0; n < _cBuckets; n++ ) + { + STTABLE_BUCKET * pBucket; + + pBucket = rgBuckets[n]; + + pBucket->Iterate( pIterFunction ); + + pBucket = NULL; + } + + _TableLock.ExclusiveRelease(); + } + +private: + + STBUFF _buffBucketPtrs; + DWORD _cBuckets; + STLOCK _TableLock; + PFN_HASH _pfnHash; + + DWORD + ComputeHash( + STBUFF * pKey + ) + { + if ( _pfnHash ) + { + return _pfnHash( pKey ); + } + + return HashString( pKey->QueryStr() ); + } + + STTABLE_BUCKET * + GetBucket( + DWORD dwHash + ) + { + STTABLE_BUCKET ** rgBuckets; + + rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr(); + + return rgBuckets[dwHash % _cBuckets]; + } + + DWORD + WINAPI + HashString( + LPCSTR szString + ) + { + DWORD dwRet = 0; + + // + // Create a hash by adding up the ascii values + // of each character in a case-insensitive manner + // + + if ( szString ) + { + while ( *szString ) + { + dwRet += ( (*szString) | 0x20 ); + szString++; + } + } + + return dwRet; + } +}; + +#endif // _STTABLE_H diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h new file mode 100644 index 0000000000..f5a10817a5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STTIMER_H +#define _STTIMER_H + +class STTIMER +{ +public: + + STTIMER() + : _pTimer( NULL ) + { + } + + virtual + ~STTIMER() + { + if ( _pTimer ) + { + CancelTimer(); + + CloseThreadpoolTimer( _pTimer ); + + _pTimer = NULL; + } + } + + HRESULT + InitializeTimer( + PTP_TIMER_CALLBACK pfnCallback, + VOID * pContext, + DWORD dwInitialWait = 0, + DWORD dwPeriod = 0 + ) + { + _pTimer = CreateThreadpoolTimer( pfnCallback, + pContext, + NULL ); + + if ( !_pTimer ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + if ( dwInitialWait ) + { + SetTimer( dwInitialWait, + dwPeriod ); + } + + return S_OK; + } + + VOID + SetTimer( + DWORD dwInitialWait, + DWORD dwPeriod = 0 + ) + { + FILETIME ftInitialWait; + + if ( dwInitialWait == 0 && dwPeriod == 0 ) + { + // + // Special case. We are preventing new callbacks + // from being queued. Any existing callbacks in the + // queue will still run. + // + // This effectively disables the timer. It can be + // re-enabled by setting non-zero initial wait or + // period values. + // + + SetThreadpoolTimer( _pTimer, NULL, 0, 0 ); + return; + } + + InitializeRelativeFileTime( &ftInitialWait, dwInitialWait ); + + SetThreadpoolTimer( _pTimer, + &ftInitialWait, + dwPeriod, + 0 ); + } + + VOID + CancelTimer() + { + // + // Disable the timer + // + + SetTimer( 0 ); + + // + // Wait until any callbacks queued prior to disabling + // have completed. + // + + WaitForThreadpoolTimerCallbacks( _pTimer, TRUE ); + } + +private: + + VOID + InitializeRelativeFileTime( + FILETIME * pft, + DWORD dwMilliseconds + ) + { + LARGE_INTEGER li; + + // + // The pftDueTime parameter expects the time to be + // expressed as the number of 100 nanosecond intervals + // times -1. + // + // To convert from milliseconds, we'll multiply by + // -10000 + // + + li.QuadPart = (LONGLONG)dwMilliseconds * -10000; + + pft->dwHighDateTime = li.HighPart; + pft->dwLowDateTime = li.LowPart; + }; + + TP_TIMER * _pTimer; +}; + +class STELAPSED +{ +public: + + STELAPSED() + : _dwInitTime( 0 ), + _dwInitTickCount( 0 ), + _dwPerfCountsPerMillisecond( 0 ), + _fUsingHighResolution( FALSE ) + { + LARGE_INTEGER li; + BOOL fResult; + + _dwInitTickCount = GetTickCount64(); + + fResult = QueryPerformanceFrequency( &li ); + + if ( !fResult ) + { + goto Finished; + } + + _dwPerfCountsPerMillisecond = li.QuadPart / 1000; + + fResult = QueryPerformanceCounter( &li ); + + if ( !fResult ) + { + goto Finished; + } + + _dwInitTime = li.QuadPart / _dwPerfCountsPerMillisecond; + + _fUsingHighResolution = TRUE; + +Finished: + + return; + } + + virtual + ~STELAPSED() + { + } + + LONGLONG + QueryElapsedTime() + { + LARGE_INTEGER li; + + if ( _fUsingHighResolution && QueryPerformanceCounter( &li ) ) + { + DWORD64 dwCurrentTime = li.QuadPart / _dwPerfCountsPerMillisecond; + + if ( dwCurrentTime < _dwInitTime ) + { + // + // It's theoretically possible that QueryPerformanceCounter + // may return slightly different values on different CPUs. + // In this case, we don't want to return an unexpected value + // so we'll return zero. This is acceptable because + // presumably such a case would only happen for a very short + // time window. + // + // It would be possible to prevent this by ensuring processor + // affinity for all calls to QueryPerformanceCounter, but that + // would be undesirable in the general case because it could + // introduce unnecessary context switches and potentially a + // CPU bottleneck. + // + // Note that this issue also applies to callers doing rapid + // calls to this function. If a caller wants to mitigate + // that, they could enforce the affinitization, or they + // could implement a similar sanity check when comparing + // returned values from this function. + // + + return 0; + } + + return dwCurrentTime - _dwInitTime; + } + + return GetTickCount64() - _dwInitTickCount; + } + + BOOL + QueryUsingHighResolution() + { + return _fUsingHighResolution; + } + +private: + + DWORD64 _dwInitTime; + DWORD64 _dwInitTickCount; + DWORD64 _dwPerfCountsPerMillisecond; + BOOL _fUsingHighResolution; +}; + +#endif // _STTIMER_H \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h new file mode 100644 index 0000000000..1c4d2d4381 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +# ifndef _DBGUTIL_H_ +# define _DBGUTIL_H_ + + +// begin_user_modifiable + +// +// define DEBUG_FLAGS_VAR to assure that DebugFlags will stay private to +// iisutil. This is important in the case when iisutil is linked as static library +// +#define DEBUG_FLAGS_VAR g_dwDebugFlagsIISUtil + +// +// Modify the following flags if necessary +// + +# define DEFAULT_OUTPUT_FLAGS ( DbgOutputKdb ) + + +// end_user_modifiable +// begin_user_unmodifiable + + + +/************************************************************ + * Include Headers + ************************************************************/ + +# include + + +// +// Define the debugging constants +// + +# define DEBUG_ALLOC_CACHE 0x01000000 +# define DEBUG_SCHED 0x02000000 +# define DEBUG_RESOURCE 0x04000000 +# define DEBUG_INET_MONITOR 0x08000000 +# define DEBUG_PIPEDATA 0x10000000 + +// Use the default constants from pudebug.h + +# endif /* _DBGUTIL_H_ */ + +/************************ End of File ***********************/ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h new file mode 100644 index 0000000000..3c6c48e7b1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h @@ -0,0 +1,154 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __IRTLDBG_H__ +#define __IRTLDBG_H__ + +#ifndef __IRTLMISC_H__ +# include +#endif + +/* Ensure that MessageBoxes can popup */ +# define RUNNING_AS_SERVICE 1 + + +#ifdef _AFX + /* Assure compatiblity with MFC */ + +# define IRTLASSERT(x) ASSERT(x) +# define IRTLVERIFY(x) VERIFY(x) + +#else /* !_AFX */ + +# if DBG || defined(_DEBUG) +# define IRTLDEBUG +# endif + +# if defined(IRTLDEBUG) +# ifndef USE_DEBUG_CRTS + /* IIS (and NT) do not ship msvcrtD.dll, per the VC license, + * so we can't use the assertion code from . Use similar + * macros from instead. */ +# include + + /* workaround for /W4 warnings about 'constant expressions' */ +# define IRTLASSERT(f) \ + ((void) ((f) || (PuDbgAssertFailed(DBG_CONTEXT, #f, ""), 0) )) + +# elif defined(_MSC_VER) && (_MSC_VER >= 1000) + /* Use the new debugging tools in Visual C++ 4.x */ +# include + /* _ASSERTE will give a more meaningful message, but the string takes + * space. Use _ASSERT if this is an issue. */ +# define IRTLASSERT(f) _ASSERTE(f) +# else +# include +# define IRTLASSERT(f) assert(f) +# endif + +# ifdef _PREFAST_ +# undef IRTLASSERT +# define IRTLASSERT(f) ((void)0) +# endif + +# define IRTLVERIFY(f) IRTLASSERT(f) +# define DEBUG_ONLY(f) (f) +# define TRACE IrtlTrace +# define TRACE0(psz) IrtlTrace(_T("%s"), _T(psz)) +# define TRACE1(psz, p1) IrtlTrace(_T(psz), p1) +# define TRACE2(psz, p1, p2) IrtlTrace(_T(psz), p1, p2) +# define TRACE3(psz, p1, p2, p3) IrtlTrace(_T(psz), p1, p2, p3) +# define ASSERT_VALID(pObj) \ + do {IRTLASSERT((pObj) != NULL); (pObj)->AssertValid();} while (0) +# define DUMP(pObj) \ + do {IRTLASSERT((pObj) != NULL); (pObj)->Dump();} while (0) + +# else /* !_DEBUG */ + + /* These macros should all compile away to nothing */ +# define IRTLASSERT(f) ((void)0) +# define IRTLVERIFY(f) ((void)(f)) +# define DEBUG_ONLY(f) ((void)0) +# define TRACE 1 ? (void)0 : IrtlTrace +# define TRACE0(psz) +# define TRACE1(psz, p1) +# define TRACE2(psz, p1, p2) +# define TRACE3(psz, p1, p2, p3) +# define ASSERT_VALID(pObj) ((void)0) +# define DUMP(pObj) ((void)0) + +# endif /* !_DEBUG */ + + +# define ASSERT_POINTER(p, type) \ + IRTLASSERT((p) != NULL) + +#define ASSERT_STRING(s) \ + IRTLASSERT(((s) != NULL)) + +/* Declarations for non-Windows apps */ + +# ifndef _WINDEF_ +typedef void* LPVOID; +typedef const void* LPCVOID; +typedef unsigned int UINT; +typedef int BOOL; +typedef const char* LPCTSTR; +# endif /* _WINDEF_ */ + +# ifndef TRUE +# define FALSE 0 +# define TRUE 1 +# endif + +#endif /* !_AFX */ + + +#ifdef __cplusplus + +// Compile-time (not run-time) assertion. Code will not compile if +// expr is false. Note: there is no non-debug version of this; we +// want this for all builds. The compiler optimizes the code away. +template struct static_checker; +template <> struct static_checker {}; // specialize only for `true' +#define STATIC_ASSERT(expr) static_checker< (expr) >() + +#endif /* !__cplusplus */ + +/* Writes trace messages to debug stream */ +extern +#ifdef __cplusplus +"C" +#endif /* !__cplusplus */ +IRTL_DLLEXP +void __cdecl +IrtlTrace( + LPCTSTR pszFormat, + ...); + + +#ifdef _DEBUG +# define IRTL_DEBUG_INIT() IrtlDebugInit() +# define IRTL_DEBUG_TERM() IrtlDebugTerm() +#else /* !_DEBUG */ +# define IRTL_DEBUG_INIT() ((void)0) +# define IRTL_DEBUG_TERM() ((void)0) +#endif /* !_DEBUG */ + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* should be called from main(), WinMain(), or DllMain() */ +IRTL_DLLEXP void +IrtlDebugInit(); + +IRTL_DLLEXP void +IrtlDebugTerm(); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __IRTLDBG_H__ */ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h new file mode 100644 index 0000000000..02bfa2d065 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __IRTLMISC_H__ +#define __IRTLMISC_H__ + +#include + +//-------------------------------------------------------------------- +// These declarations are needed to export the template classes from +// IisRtl.DLL and import them into other modules. + +// DEBGUDEBUG +/** +#ifndef IRTL_DLLEXP +# ifdef DLL_IMPLEMENTATION +# define IRTL_DLLEXP __declspec(dllexport) +# ifdef IMPLEMENTATION_EXPORT +# define IRTL_EXPIMP +# else +# undef IRTL_EXPIMP +# endif +# elif defined LIB_IMPLEMENTATION +# define IRTL_DLLEXP +# define IRTL_EXPIMP extern +# else +# define IRTL_DLLEXP __declspec(dllimport) +# define IRTL_EXPIMP extern +# endif // !DLL_IMPLEMENTATION +#endif // !IRTL_DLLEXP +*/ + +#define IRTL_DLLEXP +#define IRTL_EXPIMP + + + + + +//-------------------------------------------------------------------- +// Miscellaneous functions + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +// Heap routines + +// Private IIS heap +HANDLE +WINAPI +IisHeap(); + +// Allocate dwBytes +LPVOID +WINAPI +IisMalloc( + IN SIZE_T dwBytes); + +// Allocate dwBytes. Memory is zeroed +LPVOID +WINAPI +IisCalloc( + IN SIZE_T dwBytes); + +// Reallocate lpMem to dwBytes +LPVOID +WINAPI +IisReAlloc( + IN LPVOID lpMem, + IN SIZE_T dwBytes); + +// Free lpMem +BOOL +WINAPI +IisFree( + IN LPVOID lpMem); + +// additional IISRTL initialization +BOOL +WINAPI +InitializeIISRTL(); + +// call before unloading IISRTL +void +WINAPI +TerminateIISRTL(); + +// case-insensitive strstr +IRTL_DLLEXP const char* stristr(const char* pszString, const char* pszSubString); + +// how many CPUs on this machine? +inline int NumProcessors() +{ + static int s_nCPUs = 0; + + if (s_nCPUs == 0) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + s_nCPUs = si.dwNumberOfProcessors; + } + return s_nCPUs; +} + + +// how many CPUs on this machine? +inline int ProcessorType() +{ + static int s_nProcessorType = 0; + + if (s_nProcessorType == 0) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + s_nProcessorType = si.dwProcessorType; + } + return s_nProcessorType; +} + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#define HRESULT_FROM_GLE() ( GetLastError() != NO_ERROR ) \ + ? HRESULT_FROM_WIN32( GetLastError() ) \ + : E_FAIL + +#endif // __IRTLMISC_H__ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx new file mode 100644 index 0000000000..effa543259 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _MEMORYLOG_HXX_ +#define _MEMORYLOG_HXX_ + +//#include "buffer.hxx" + +class CMemoryLog +{ +public: + CMemoryLog(DWORD dwMaxByteSize); + ~CMemoryLog(); + + // + // Override the new and delete operator to make them + // use LocalAlloc so that CMemoryLog + // can be safely constructed and deleted + // in the DllMain() + // + + VOID * + operator new( + size_t size + ) + { + return LocalAlloc( LPTR, size ); + } + + VOID + operator delete( + VOID * pMemoryLog + ) + { + DBG_ASSERT( pMemoryLog != NULL ); + LocalFree( pMemoryLog ); + } + + // appends to memory log + DWORD Append(LPCSTR pszOutput, + DWORD cchLen + ); +private: + CMemoryLog(); + + // pointer to the beginning of the memory buffer + CHAR *m_pBufferBegin; + // pointer to the byte 1 beyond the end of the last message + CHAR *m_pLastMessageEnd; + // pointer to the end of the memory buffer + CHAR *m_pBufferEnd; + + // Used for storage + BUFFER m_buf; + + // TRUE if storage could be allocated, otherwise FALSE + BOOL m_fValid; + + CRITICAL_SECTION m_cs; + + // to be able to tell if the critsec was initialized successfully + BOOL m_fCritSecInitialized; + +}; + +#endif // _MEMORYLOG_HXX_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx new file mode 100644 index 0000000000..d012c7ee29 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx @@ -0,0 +1,9 @@ +#include +#include "tchar.h" +#include "dbgutil.h" +#include "ntassert.h" +#include "buffer.h" +#include "stringa.h" +#include "stringu.h" +#include "stdlib.h" +#include "stdio.h" diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h new file mode 100644 index 0000000000..d42153d457 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h @@ -0,0 +1,748 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#if !defined(BUILD_PUDEBUG) +// +// if we are not using this header for building the pudebug library +// then better this be used with dbgutil.h +// + # ifndef _DBGUTIL_H_ + // error Please make sure you included dbgutil.h! + // error Do not include pudebug.h directly + #include + # endif // _DBGUTIL_H_ +#endif + +# ifndef _PUDEBUG_H_ +# define _PUDEBUG_H_ + +#ifndef _NO_TRACING_ +# define _NO_TRACING_ +#endif // _NO_TRACING_ + +/************************************************************ + * Include Headers + ************************************************************/ + +# ifdef __cplusplus +extern "C" { +# endif // __cplusplus + +# include + +# ifndef dllexp +# define dllexp __declspec( dllexport) +# endif // dllexp + +#include + +#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 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 ***********************/ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj new file mode 100644 index 0000000000..257df53c47 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj @@ -0,0 +1,78 @@ + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + 15.0 + {A2599642-CBE5-4230-8511-3DC2D81874BE} + Win32Proj + reftrace + + + + StaticLibrary + v141 + + + true + + + + $(ProjectDir)include;$(IIS-Common)Include;$(IncludePath) + + + + true + precomp.hxx + _LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + This project is trying to import a missing file: {0}. + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters new file mode 100644 index 0000000000..b77ab9c7c1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters @@ -0,0 +1,54 @@ + + + + + {aaa5bb99-ba5c-4b8d-9ef9-a406282e05a6} + + + {85a83b74-9536-44d0-a7f7-96e1475f21e9} + + + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + + + include + + + include + + + include + + + include + + + include + + + include + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp new file mode 100644 index 0000000000..06ce025bbe --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" + +#include +#include +#include +#include +#include + +#define IMPLEMENTATION_EXPORT +#include + + +void __cdecl +IrtlTrace( + LPCTSTR ptszFormat, + ...) +{ + TCHAR tszBuff[2048]; + va_list args; + + va_start(args, ptszFormat); + _vsntprintf_s(tszBuff, sizeof(tszBuff) / sizeof(tszBuff[0]), _TRUNCATE, ptszFormat, args); + va_end(args); + + DBGPRINTF(( DBG_CONTEXT, "%ls", tszBuff )); +} + + + +#ifdef IRTLDEBUG + +# if defined(USE_DEBUG_CRTS) && defined(_MSC_VER) && (_MSC_VER >= 1000) + + +# ifdef IRTLDBG_RUNNING_AS_SERVICE + +// The default assertion mechanism set up by Visual C++ 4 will not +// work with Active Server Pages because it's running inside a service +// and there is no desktop to interact with. + +// Note: for this to work properly, #define _WIN32_WINNT 0x400 before +// including or MB_SERVICE_NOTIFICATION won't be #define'd. + +int __cdecl +AspAssertHandler( + int nReportType, + char* pszErrorText, + int* pnReturn) +{ + const char szInfo[] = " (Press ABORT to terminate IIS," + " RETRY to debug this failure," + " or IGNORE to continue.)"; + char* pszMessageTitle = NULL; + int nResult = FALSE; + + *pnReturn = 0; // nothing for _CrtDbgReport to do + + // These flags enable message boxes to show up on the user's console + switch (nReportType) + { + case _CRT_WARN: + // If using MFC's TRACE macro (AfxTrace), the report hook + // (AspAssertHandler) will get called with _CRT_WARN. Ignore. + pszMessageTitle = "Warning"; + *pnReturn = 0; + return FALSE; + + case _CRT_ERROR: + pszMessageTitle = "Fatal Error"; + break; + + case _CRT_ASSERT: + pszMessageTitle = "Assertion Failed"; + break; + } + + char* pszMessageText = + static_cast(malloc(strlen(pszErrorText) + strlen(szInfo) + 1)); + + if (NULL == pszMessageText) + return FALSE; + + strcpy(pszMessageText, pszErrorText); + strcat(pszMessageText, szInfo); + + const int n = MessageBoxA(NULL, pszMessageText, pszMessageTitle, + (MB_SERVICE_NOTIFICATION | MB_TOPMOST + | MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION)); + + if (n == IDABORT) + { + exit(1); + } + else if (n == IDRETRY) + { + *pnReturn = 1; // tell _CrtDbgReport to start the debugger + nResult = TRUE; // tell _CrtDbgReport to run + } + + free(pszMessageText); + + return nResult; +} +# endif // IRTLDBG_RUNNING_AS_SERVICE +# endif // _MSC_VER >= 1000 + + + +void +IrtlDebugInit() +{ +# if defined(USE_DEBUG_CRTS) && defined(_MSC_VER) && (_MSC_VER >= 1000) +# ifdef IRTLDBG_RUNNING_AS_SERVICE + // If we end up in _CrtDbgReport, don't put up a message box + // _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); + + // Use AspAssertHandler to put up a message box instead + _CrtSetReportHook(AspAssertHandler); +# endif // IRTLDBG_RUNNING_AS_SERVICE + + + // Enable debug heap allocations & check for memory leaks at program exit + // The memory leak check will not be performed if inetinfo.exe is + // run directly under a debugger, only if it is run as a service. + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF + | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); +# endif // _MSC_VER >= 1000 +} + + + +void +IrtlDebugTerm() +{ +# if defined(USE_DEBUG_CRTS) && defined(_MSC_VER) && (_MSC_VER >= 1000) +# ifdef IRTLDBG_RUNNING_AS_SERVICE + // Turn off AspAssertHandler, so that we don't get numerous message boxes + // if there are memory leaks on shutdown + _CrtSetReportHook(NULL); +# endif // IRTLDBG_RUNNING_AS_SERVICE +# endif // _MSC_VER >= 1000 +} + +#endif //IRTLDEBUG + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx new file mode 100644 index 0000000000..eb13b3edde --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "pudebug.h" + +#define IMPLEMENTATION_EXPORT + +extern "C" +PLATFORM_TYPE +IISGetPlatformType( + VOID +) +/*++ + + This function consults the registry and determines the platform type + for this machine. + + Arguments: + + None + + Returns: + Platform type + +--*/ +{ + OSVERSIONINFOEX osVersionInfoEx = { 0 }; + DWORDLONG dwlConditionMask = 0; + BOOL fReturn = FALSE; + + osVersionInfoEx.dwOSVersionInfoSize = sizeof( osVersionInfoEx ); + + // + // If we are not workstation (Client) + // that means that we are a server or domain controller (Server) + // + osVersionInfoEx.wProductType = VER_NT_WORKSTATION; + VER_SET_CONDITION( dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL ); + + fReturn = VerifyVersionInfo( + &osVersionInfoEx, + VER_PRODUCT_TYPE, + dwlConditionMask ); + + // + // VerifyVersionInfo fails if the return value is zero + // and GetLastError returns an error code other than ERROR_OLD_WIN_VERSION + // + if ( !fReturn && GetLastError() != ERROR_OLD_WIN_VERSION ) + { + DPERROR(( DBG_CONTEXT, + HRESULT_FROM_WIN32 ( GetLastError() ), + "VerifyVersionInfo failed\n" )); + + return PtInvalid; + } + + return ( fReturn ) ? PtNtWorkstation : PtNtServer; +} + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx new file mode 100644 index 0000000000..6f303f94e0 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx @@ -0,0 +1,123 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "memorylog.hxx" +#include "pudebug.h" + +CMemoryLog::CMemoryLog(DWORD dwMaxByteSize) : + m_fValid(FALSE), + m_fCritSecInitialized(FALSE) +{ + BOOL fRet; + + fRet = m_buf.Resize(dwMaxByteSize); + if (fRet) + { + m_fValid = TRUE; + } + + m_pBufferBegin = (CHAR*) m_buf.QueryPtr(); + m_pLastMessageEnd = (CHAR*) m_buf.QueryPtr(); + m_pBufferEnd = ((CHAR*) m_buf.QueryPtr()) + m_buf.QuerySize(); + + fRet = InitializeCriticalSectionAndSpinCount(&m_cs, + 0x80000000 /* precreate event */ | + IIS_DEFAULT_CS_SPIN_COUNT ); + if (FALSE != fRet) + { + m_fCritSecInitialized = TRUE; + } + +} + +CMemoryLog::~CMemoryLog() +{ + m_pBufferBegin = NULL; + m_pLastMessageEnd = NULL; + m_pBufferEnd = NULL; + m_fValid = FALSE; + + if (m_fCritSecInitialized) + { + DeleteCriticalSection(&m_cs); + m_fCritSecInitialized = FALSE; + } +} + +// +// Appends to end of the circular memory log. +// +DWORD +CMemoryLog::Append(LPCSTR pszOutput, + DWORD cchLen + ) +{ + // make sure internal state can accept this request + if (FALSE == m_fValid || + FALSE == m_fCritSecInitialized ) + { + return ERROR_NOT_ENOUGH_MEMORY; + } + + // make sure that we won't think we need less + // memory than we do. We are going to add 1 to + // this value next, so if it is MAX_UINT then + // we will wrap on the add. Don't allow strings + // that are that long. + if ( (ULONGLONG)cchLen + 1 > MAXDWORD ) + { + return ERROR_ARITHMETIC_OVERFLOW; + } + + // make sure the string length will fit inside the buffer + if ( cchLen + 1 > m_buf.QuerySize()) + { + return ERROR_NOT_ENOUGH_MEMORY; + } + + CHAR * pWhereToWriteMessage = NULL; + + // need to synchronize access to m_pLastMessageEnd + EnterCriticalSection(&m_cs); + + // check if the new message will fit into the remaining space in the buffer + // previous end (+1) + new length + 1 for NULL + if (m_pLastMessageEnd + cchLen + 1 < m_pBufferEnd) + { + // it will fit in remaining space + pWhereToWriteMessage = m_pLastMessageEnd; + } + else + { + // start over at the beginning + pWhereToWriteMessage = (CHAR*)m_buf.QueryPtr(); + + // don't leave extra old goo sitting around in the buffer + ZeroMemory(m_pLastMessageEnd, m_pBufferEnd - m_pLastMessageEnd); + } + + // set end of message to pWhere + length + 1 for NULL + m_pLastMessageEnd = pWhereToWriteMessage + cchLen + 1; + + LeaveCriticalSection(&m_cs); + + // the following memcpy is outside of the criticalsection - + // this introduces a race between leaving the criticalsection and + // looping back through the buffer before we finish writing. + // how likely is this? Not very. + // + // In addition - moving the memcpy inside of the critsec makes the time spent + // quite a bit larger than some simple load/stores that are currently there. + // + // Plus this is a debugging aid - life isn't fair. + + // actually do the copy + memcpy(pWhereToWriteMessage, pszOutput, cchLen); + + // write out a NULL to indicate end of message + *(pWhereToWriteMessage + cchLen) = NULL; + + return NO_ERROR; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx new file mode 100644 index 0000000000..44e42a21b1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx @@ -0,0 +1,1164 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +/************************************************************ + * Include Headers + ************************************************************/ +# include "precomp.hxx" + + +# include +# include +# include +# include +# include + + +# include "pudebug.h" +# include "memorylog.hxx" + + +/************************************************************* + * Global Variables and Default Values + *************************************************************/ + +// +// TRUE if we're in a test process. +// There are a few noisy assertions that fire frequently cause of test code issues. These noisy asserts are masking +// real ones, drastically reducing the value of CHK bits. +// +BOOL g_fTestProcess = FALSE; + +// +// HACK HACK +// suppress shutdown asserts under some hosts +// +BOOL g_fAvoidShutdownAsserts = FALSE; + +# define MAX_PRINTF_OUTPUT ( 10240) + +# define DEFAULT_DEBUG_FLAGS_VALUE ( 0) +# define DEBUG_FLAGS_REGISTRY_LOCATION_A "DebugFlags" +# define DEBUG_BREAK_ENABLED_REGKEYNAME_A "BreakOnAssert" + +/************************************************************* + * Functions + *************************************************************/ + +/********************************************************************++ + +Routine Description: + This function creates a new DEBUG_PRINTS object for the required + program. + +Arguments: + pszPrintLabel pointer to null-terminated string containing + the label for program's debugging output + dwOutputFlags DWORD containing the output flags to be used. + +Returns: + pointer to a new DEBUG_PRINTS object on success. + Returns NULL on failure. +--*********************************************************************/ +LPDEBUG_PRINTS +PuCreateDebugPrintsObject( + IN const char * pszPrintLabel, + IN DWORD dwOutputFlags) +{ + + LPDEBUG_PRINTS pDebugPrints; + + pDebugPrints = (LPDEBUG_PRINTS ) GlobalAlloc( GPTR, sizeof( DEBUG_PRINTS)); + + if ( pDebugPrints != NULL) { + + if ( strlen( pszPrintLabel) < MAX_LABEL_LENGTH) { + + strcpy_s( pDebugPrints->m_rgchLabel, + sizeof( pDebugPrints->m_rgchLabel ) / sizeof( pDebugPrints->m_rgchLabel[0]), + pszPrintLabel); + } else { + strncpy_s( pDebugPrints->m_rgchLabel, + sizeof( pDebugPrints->m_rgchLabel ) / sizeof( pDebugPrints->m_rgchLabel[0]), + pszPrintLabel, + MAX_LABEL_LENGTH - 1); + } + + memset( pDebugPrints->m_rgchLogFilePath, 0, MAX_PATH); + memset( pDebugPrints->m_rgchLogFileName, 0, MAX_PATH); + + pDebugPrints->m_LogFileHandle = INVALID_HANDLE_VALUE; + + pDebugPrints->m_dwOutputFlags = dwOutputFlags; + pDebugPrints->m_StdErrHandle = GetStdHandle( STD_ERROR_HANDLE); + + if ( pDebugPrints->m_StdErrHandle == NULL ) + { + pDebugPrints->m_StdErrHandle = INVALID_HANDLE_VALUE; + } + + pDebugPrints->m_fInitialized = TRUE; + pDebugPrints->m_fBreakOnAssert= TRUE; + pDebugPrints->m_pMemoryLog = NULL; + } + + + return ( pDebugPrints); +} // PuCreateDebugPrintsObject() + + + + +/********************************************************************++ + +Routine Description: + This function cleans up the pDebugPrints object and + frees the allocated memory. + + Arguments: + pDebugPrints poitner to the DEBUG_PRINTS object. + + Returns: + NULL on success. + pDebugPrints() if the deallocation failed. + +--*********************************************************************/ +LPDEBUG_PRINTS +PuDeleteDebugPrintsObject( + IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + if ( pDebugPrints != NULL) { + + PuCloseDbgMemoryLog(pDebugPrints); + DWORD dwError = PuCloseDbgPrintFile( pDebugPrints); + + if ( dwError != NO_ERROR) { + + SetLastError( dwError); + } else { + + // returns NULL on success + pDebugPrints = + (LPDEBUG_PRINTS ) GlobalFree( pDebugPrints); + } + } + + return ( pDebugPrints); + +} // PuDeleteDebugPrintsObject() + + + + +VOID +PuSetDbgOutputFlags( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN DWORD dwFlags) +{ + + if ( pDebugPrints == NULL) { + + SetLastError( ERROR_INVALID_PARAMETER); + } else { + + pDebugPrints->m_dwOutputFlags = dwFlags; + } + + return; +} // PuSetDbgOutputFlags() + + + +DWORD +PuGetDbgOutputFlags( + IN const LPDEBUG_PRINTS pDebugPrints) +{ + return ( pDebugPrints != NULL) ? pDebugPrints->m_dwOutputFlags : 0; + +} // PuGetDbgOutputFlags() + + +static DWORD +PuOpenDbgFileLocal( + IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + if ( pDebugPrints == NULL) + return ERROR_INVALID_PARAMETER; + + if ( pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) { + + // + // Silently return as a file handle exists. + // + return ( NO_ERROR); + } + + pDebugPrints->m_LogFileHandle = + CreateFileA( pDebugPrints->m_rgchLogFileName, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if ( pDebugPrints->m_LogFileHandle == INVALID_HANDLE_VALUE) { + + CHAR pchBuffer[1024]; + DWORD dwError = GetLastError(); + + sprintf_s( pchBuffer, + sizeof( pchBuffer ) / sizeof( pchBuffer[0] ), + " Critical Error: Unable to Open File %s. Error = %d\n", + pDebugPrints->m_rgchLogFileName, dwError); + OutputDebugStringA( pchBuffer); + + return ( dwError); + } + + return ( NO_ERROR); +} // PuOpenDbgFileLocal() + + + + + +DWORD +PuOpenDbgPrintFile( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFileName, + IN const char * pszPathForFile) +/********************************************************************++ + + Opens a Debugging log file. This function can be called to set path + and name of the debugging file. + + Arguments: + pszFileName pointer to null-terminated string containing + the name of the file. + + pszPathForFile pointer to null-terminated string containing the + path for the given file. + If NULL, then the old place where dbg files were + stored is used or if none, + default windows directory will be used. + + Returns: + Win32 error codes. NO_ERROR on success. + +--*********************************************************************/ + +{ + if ( pszFileName == NULL || pDebugPrints == NULL) { + + return ( ERROR_INVALID_PARAMETER); + } + + // + // Setup the Path information. if necessary. + // + + if ( pszPathForFile != NULL) { + + // Path is being changed. + + if ( strlen( pszPathForFile) < MAX_PATH) { + + strcpy_s( pDebugPrints->m_rgchLogFilePath, + sizeof( pDebugPrints->m_rgchLogFilePath ) / sizeof( pDebugPrints->m_rgchLogFilePath[0] ), + pszPathForFile); + } else { + + return ( ERROR_INVALID_PARAMETER); + } + } else { + + if ( pDebugPrints->m_rgchLogFilePath[0] == '\0' && // no old path + !GetWindowsDirectoryA( pDebugPrints->m_rgchLogFilePath, MAX_PATH)) { + + // + // Unable to get the windows default directory. Use current dir + // + + strcpy_s( pDebugPrints->m_rgchLogFilePath, + sizeof( pDebugPrints->m_rgchLogFilePath ) / sizeof( pDebugPrints->m_rgchLogFilePath[0] ), + "."); + } + } + + // + // Should need be, we need to create this directory for storing file + // + + + // + // Form the complete Log File name and open the file. + // + if ( (strlen( pszFileName) + strlen( pDebugPrints->m_rgchLogFilePath)) + >= MAX_PATH) { + + return ( ERROR_NOT_ENOUGH_MEMORY); + } + + // form the complete path + strcpy_s( pDebugPrints->m_rgchLogFileName, + sizeof( pDebugPrints->m_rgchLogFileName ) / sizeof( pDebugPrints->m_rgchLogFileName[0] ), + pDebugPrints->m_rgchLogFilePath); + + if ( pDebugPrints->m_rgchLogFileName[ strlen(pDebugPrints->m_rgchLogFileName) - 1] + != '\\') { + // Append a \ if necessary + strcat_s( pDebugPrints->m_rgchLogFileName, + sizeof( pDebugPrints->m_rgchLogFileName ) / sizeof( pDebugPrints->m_rgchLogFileName[0] ), + "\\"); + }; + strcat_s( pDebugPrints->m_rgchLogFileName, + sizeof( pDebugPrints->m_rgchLogFileName ) / sizeof( pDebugPrints->m_rgchLogFileName[0] ), + pszFileName); + + return PuOpenDbgFileLocal( pDebugPrints); + +} // PuOpenDbgPrintFile() + + + + +DWORD +PuReOpenDbgPrintFile( + IN OUT LPDEBUG_PRINTS pDebugPrints) +/********************************************************************++ + + This function closes any open log file and reopens a new copy. + If necessary. It makes a backup copy of the file. + +--*********************************************************************/ + +{ + if ( pDebugPrints == NULL) { + return ( ERROR_INVALID_PARAMETER); + } + + PuCloseDbgPrintFile( pDebugPrints); // close any existing file. + + if ( pDebugPrints->m_dwOutputFlags & DbgOutputBackup) { + + // MakeBkupCopy(); + + OutputDebugStringA( " Error: MakeBkupCopy() Not Yet Implemented\n"); + } + + return PuOpenDbgFileLocal( pDebugPrints); + +} // PuReOpenDbgPrintFile() + + + + +DWORD +PuCloseDbgPrintFile( + IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + DWORD dwError = NO_ERROR; + + if ( pDebugPrints == NULL ) { + dwError = ERROR_INVALID_PARAMETER; + } else { + + if ( pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) { + + FlushFileBuffers( pDebugPrints->m_LogFileHandle); + + if ( !CloseHandle( pDebugPrints->m_LogFileHandle)) { + + CHAR pchBuffer[1024]; + + dwError = GetLastError(); + + sprintf_s( pchBuffer, + sizeof( pchBuffer ) / sizeof( pchBuffer[0] ), + "CloseDbgPrintFile() : CloseHandle( %p) failed." + " Error = %d\n", + pDebugPrints->m_LogFileHandle, + dwError); + OutputDebugStringA( pchBuffer); + } + + pDebugPrints->m_LogFileHandle = INVALID_HANDLE_VALUE; + } + } + + return ( dwError); +} // DEBUG_PRINTS::CloseDbgPrintFile() + +DWORD +PuOpenDbgMemoryLog(IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + DWORD dwError; + CMemoryLog * pLog = NULL; + + if (NULL == pDebugPrints) + { + dwError = ERROR_INVALID_PARAMETER; + goto done; + } + + if (NULL != pDebugPrints->m_pMemoryLog) + { + dwError = ERROR_SUCCESS; + goto done; + } + + pLog = new CMemoryLog(1024 * 512); // max size of 512 K + if (NULL == pLog) + { + dwError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + // save away the pointer + pDebugPrints->m_pMemoryLog = pLog; + + // make sure output gets to the log + pDebugPrints->m_dwOutputFlags |= DbgOutputMemory; + + dwError = NO_ERROR; +done: + return dwError; +} + +DWORD +PuCloseDbgMemoryLog(IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + DWORD dwError; + + if (NULL == pDebugPrints) + { + dwError = ERROR_INVALID_PARAMETER; + goto done; + } + if (NULL != pDebugPrints->m_pMemoryLog) + { + CMemoryLog * pLog = (CMemoryLog*) (pDebugPrints->m_pMemoryLog); + delete pLog; + pDebugPrints->m_pMemoryLog = NULL; + } + + dwError = NO_ERROR; +done: + return dwError; +} + +VOID +PupOutputMessage( + IN LPDEBUG_PRINTS pDebugPrints, + IN STRA *straOutput + ) +{ + if ( pDebugPrints != NULL) + { + if ( ( pDebugPrints->m_dwOutputFlags & DbgOutputStderr) && + ( pDebugPrints->m_StdErrHandle != INVALID_HANDLE_VALUE ) ) { + + DWORD nBytesWritten; + + ( VOID) WriteFile( pDebugPrints->m_StdErrHandle, + straOutput->QueryStr(), + straOutput->QueryCCH(), + &nBytesWritten, + NULL); + } + + if ( pDebugPrints->m_dwOutputFlags & DbgOutputLogFile && + pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) { + + DWORD nBytesWritten; + + // + // Truncation of log files. Not yet implemented. + + ( VOID) WriteFile( pDebugPrints->m_LogFileHandle, + straOutput->QueryStr(), + straOutput->QueryCCH(), + &nBytesWritten, + NULL); + + } + + if ( (pDebugPrints->m_dwOutputFlags & DbgOutputMemory) && + (NULL != pDebugPrints->m_pMemoryLog) ) + { + CMemoryLog* pLog = (CMemoryLog*) (pDebugPrints->m_pMemoryLog); + pLog->Append(straOutput->QueryStr(), straOutput->QueryCCH()); + } + + } + + + if ( pDebugPrints == NULL || + pDebugPrints->m_dwOutputFlags & DbgOutputKdb) + { + OutputDebugStringA( straOutput->QueryStr() ); + } + + return; +} + +void +FormatMsgToBuffer( IN OUT STRA * pSTRAOutput, + IN LPDEBUG_PRINTS pDebugPrints, + IN LPCSTR pszFilePath, + IN DWORD nLineNum, + IN LPCSTR pszFunctionName, + IN LPCSTR pszFormat, + IN va_list * pargsList) +{ + LPCSTR pszFileName = strrchr( pszFilePath, '\\'); + int cchPrologue = 0; + HRESULT hr = S_OK; + DWORD cchOutput = 0; + + // + // Skip the complete path name and retain file name in pszName + // + + if ( pszFileName== NULL) { + + // if skipping \\ yields nothing use whole path. + pszFileName = pszFilePath; + } + else + { + // skip past the '\' + ++pszFileName; + } + + // Format the message header as: tid label!function [file @ line number]:message + cchPrologue = sprintf_s( pSTRAOutput->QueryStr(), + pSTRAOutput->QuerySize(), + "%lu %hs!%hs [%hs @ %d]:", + GetCurrentThreadId(), + pDebugPrints ? pDebugPrints->m_rgchLabel : "??", + pszFunctionName, + pszFileName, + nLineNum); + + // we directly touched the buffer - however, wait to SyncWithBuffer + // until the rest of the operations are done. Do NOT call QueryCCH() it will be WRONG. + + + // Format the incoming message using vsnprintf() so that the overflows are + // captured + + cchOutput = _vsnprintf_s( pSTRAOutput->QueryStr() + cchPrologue, + pSTRAOutput->QuerySize() - cchPrologue, + pSTRAOutput->QuerySize() - cchPrologue - 1, + pszFormat, *pargsList); + + if ( cchOutput == -1 ) + { + // couldn't fit this in the original STRA size. Try a heap allocation. + hr = pSTRAOutput->Resize(MAX_PRINTF_OUTPUT); + if (FAILED(hr)) + { + // Can't allocate, therefore don't give back half done results + pSTRAOutput->Reset(); + return; + } + + cchOutput = _vsnprintf_s( pSTRAOutput->QueryStr() + cchPrologue, + pSTRAOutput->QuerySize() - cchPrologue, + pSTRAOutput->QuerySize() - cchPrologue - 1, + pszFormat, *pargsList); + if (cchOutput == -1) + { + // we need to NULL terminate, as _vsnprintf failed to do that for us. + pSTRAOutput->QueryStr()[pSTRAOutput->QuerySize() - 1] = '\0'; + } + } + + // we directly touched the buffer - therefore: + pSTRAOutput->SyncWithBuffer(); + + return; +} // FormatMsgToBuffer() + + +/********************************************************************++ +Routine Description: + Main function that examines the incoming message and prints out a header + and the message. + +Arguments: + pDebugPrints - pointer to the debug print object + pszFilePaht - pointer to the file from where this function is called + nLineNum - Line number within the file + pszFormat - formatting string to use. + +Returns: + None +--*********************************************************************/ + +VOID +PuDbgPrint( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszFormat, + ...) +{ + STACK_STRA(straOutput, 256); + va_list argsList; + DWORD dwErr; + + // get a local copy of the error code so that it is not lost + dwErr = GetLastError(); + + va_start( argsList, pszFormat); + FormatMsgToBuffer( &straOutput, + pDebugPrints, + pszFilePath, + nLineNum, + pszFunctionName, + pszFormat, + &argsList); + + va_end( argsList); + + // + // Send the outputs to respective files. + // + PupOutputMessage( pDebugPrints, &straOutput); + + + SetLastError( dwErr ); + + return; +} // PuDbgPrint() + +void +FormatMsgToBufferW( IN OUT STRU * pSTRUOutput, + IN LPDEBUG_PRINTS pDebugPrints, + IN LPCSTR pszFilePath, + IN DWORD nLineNum, + IN LPCSTR pszFunctionName, + IN LPCWSTR pszFormat, + IN va_list * pargsList) +{ + LPCSTR pszFileName = strrchr( pszFilePath, '\\'); + int cchPrologue = 0; + HRESULT hr = S_OK; + DWORD cchOutput = 0; + + // + // Skip the complete path name and retain file name in pszName + // + + if ( pszFileName== NULL) { + + // if skipping \\ yields nothing use whole path. + pszFileName = pszFilePath; + } + else + { + // skip past the '\' + ++pszFileName; + } + + // Format the message header as: tid label!function [file @ line number]:message + cchPrologue = swprintf_s( pSTRUOutput->QueryStr(), + pSTRUOutput->QuerySizeCCH(), + L"%lu %hs!%hs [%hs @ %d]:", + GetCurrentThreadId(), + pDebugPrints ? pDebugPrints->m_rgchLabel : "??", + pszFunctionName, + pszFileName, + nLineNum); + + // we directly touched the buffer - however, wait to SyncWithBuffer + // until the rest of the operations are done. Do NOT call QueryCCH() it will be WRONG. + + // Format the incoming message using vsnprintf() so that the overflows are + // captured + + cchOutput = _vsnwprintf_s( pSTRUOutput->QueryStr() + cchPrologue, + pSTRUOutput->QuerySizeCCH() - cchPrologue, + // DEBUGDEBUG + //pSTRUOutput->QueryBuffer()->QuerySize() / sizeof(WCHAR) - cchPrologue - 1, // this is a count of characters + pSTRUOutput->QuerySizeCCH() - cchPrologue - 1, + pszFormat, *pargsList); + + if ( cchOutput == -1 ) + { + // couldn't fit this in the original STRA size. Try a heap allocation. + hr = pSTRUOutput->Resize(MAX_PRINTF_OUTPUT); + if (FAILED(hr)) + { + // Can't allocate, therefore don't give back half done results + pSTRUOutput->Reset(); + return; + } + + cchOutput = _vsnwprintf_s( pSTRUOutput->QueryStr() + cchPrologue, + pSTRUOutput->QuerySizeCCH() - cchPrologue, + //DEBUGDEBUG + //pSTRUOutput->QueryBuffer()->QuerySize() / sizeof(WCHAR) - cchPrologue - 1, // this is a count of characters + pSTRUOutput->QuerySizeCCH() - cchPrologue - 1, + pszFormat, *pargsList); + if (cchOutput == -1) + { + // we need to NULL terminate, as _vsnprintf failed to do that for us. + //DEBUGDEBUG + pSTRUOutput->QueryStr()[pSTRUOutput->QuerySizeCCH() - 1] = L'\0'; + + } + } + + // we directly touched the buffer - therefore: + pSTRUOutput->SyncWithBuffer(); + + return; +} // FormatMsgToBuffer() + +extern "C" +VOID +PuDbgPrintW( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const WCHAR * pszFormat, + ... +) +{ + STACK_STRU(struOutput, 256); + va_list argsList; + DWORD dwErr; + HRESULT hr; + // get a local copy of the error code so that it is not lost + dwErr = GetLastError(); + + va_start( argsList, pszFormat); + FormatMsgToBufferW( &struOutput, + pDebugPrints, + pszFilePath, + nLineNum, + pszFunctionName, + pszFormat, + &argsList); + + va_end( argsList); + + // + // Send the outputs to respective files. + // + STACK_STRA(straOutput, 256); + hr = straOutput.CopyWTruncate(struOutput.QueryStr(), struOutput.QueryCCH()); + if (FAILED(hr)) + { + goto done; + } + + PupOutputMessage( pDebugPrints, &straOutput); + +done: + + SetLastError( dwErr ); + + return; +} + +/********************************************************************++ +Routine Description: + This function behaves like PuDbgPrint() but also prints out formatted + Error message indicating what failed. + +Arguments: + pDebugPrints - pointer to the debug print object + pszFilePaht - pointer to the file from where this function is called + nLineNum - Line number within the file + dwError - Error code for which the formatted error message should + be printed + pszFormat - formatting string to use. + +Returns: + None +--*********************************************************************/ +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, + ...) // argsList +{ + STACK_STRA(straOutput, 256); + va_list argsList; + DWORD dwErr; + + // get a local copy of the error code so that it is not lost + dwErr = GetLastError(); + + va_start( argsList, pszFormat); + FormatMsgToBuffer( &straOutput, + pDebugPrints, + pszFilePath, + nLineNum, + pszFunctionName, + pszFormat, + &argsList); + + va_end( argsList); + + + // + // obtain the formatted error message for error code + // + + LPSTR lpErrorBuffer = NULL; + DWORD nRet; +#pragma prefast(suppress: __WARNING_ANSI_APICALL,"debug spew is ansi") + nRet = + FormatMessageA((FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM), + NULL, // lpSource + dwError, + LANG_NEUTRAL, + (LPSTR ) &lpErrorBuffer, // pointer to store buffer allocated + 0, // size of buffer + NULL // lpArguments + ); + + if (lpErrorBuffer) + { + CHAR pszErrorOut[64]; // 64 from: (/t=)4 + (Error(=)7 + (%x=)18 (0x + 16hex on 64 bit systems) + (): =)3 == 32 + some more slop + _snprintf_s( pszErrorOut, + sizeof( pszErrorOut ) / sizeof( pszErrorOut[0] ), + sizeof(pszErrorOut) / sizeof(CHAR) - 1, // leave space for NULL. + "\tError(%x): ", + dwError); + pszErrorOut[63] = '\0'; + + // if these appends fail, nothing to be done about it therefore just ignore the return values + straOutput.Append(pszErrorOut); + + straOutput.Append(lpErrorBuffer); + straOutput.Append("\n"); + } + + // + // Send the outputs to respective files. + // + PupOutputMessage( pDebugPrints, &straOutput); + + // free the buffer if any was allocated + if ( lpErrorBuffer != NULL) { + LocalFree (lpErrorBuffer); + } + + SetLastError( dwErr ); + + return; +} // PuDbgPrintError() + + + +VOID +PuDbgDump( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszDump + ) +{ + UNREFERENCED_PARAMETER( pszFunctionName ); + UNREFERENCED_PARAMETER( nLineNum ); + + LPCSTR pszFileName = strrchr( pszFilePath, '\\'); + DWORD dwErr; + DWORD cbDump; + + + // + // Skip the complete path name and retain file name in pszName + // + + if ( pszFileName== NULL) { + + pszFileName = pszFilePath; + } + + dwErr = GetLastError(); + + // No message header for this dump + cbDump = (DWORD)strlen( pszDump); + + // + // Send the outputs to respective files. + // + + if ( pDebugPrints != NULL) + { + if ( ( pDebugPrints->m_dwOutputFlags & DbgOutputStderr) && + ( pDebugPrints->m_StdErrHandle != INVALID_HANDLE_VALUE ) ) { + + DWORD nBytesWritten; + + ( VOID) WriteFile( pDebugPrints->m_StdErrHandle, + pszDump, + cbDump, + &nBytesWritten, + NULL); + } + + if ( pDebugPrints->m_dwOutputFlags & DbgOutputLogFile && + pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) { + + DWORD nBytesWritten; + + // + // Truncation of log files. Not yet implemented. + + ( VOID) WriteFile( pDebugPrints->m_LogFileHandle, + pszDump, + cbDump, + &nBytesWritten, + NULL); + + } + + if ( (pDebugPrints->m_dwOutputFlags & DbgOutputMemory) && + (NULL != pDebugPrints->m_pMemoryLog) ) + { + CMemoryLog * pLog = (CMemoryLog*)(pDebugPrints->m_pMemoryLog); + pLog->Append(pszDump, cbDump); + } + } + + if ( pDebugPrints == NULL + || pDebugPrints->m_dwOutputFlags & DbgOutputKdb) + { + OutputDebugStringA( pszDump); + } + + SetLastError( dwErr ); + + return; +} // PuDbgDump() + +// +// N.B. For PuDbgCaptureContext() to work properly, the calling function +// *must* be __cdecl, and must have a "normal" stack frame. So, we decorate +// PuDbgAssertFailed() with the __cdecl modifier and disable the frame pointer +// omission (FPO) optimization. +// + +// DEBUGDEBUG +//#pragma optimize( "y", off ) // disable frame pointer omission (FPO) +#pragma optimize( "", off ) + +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) +/********************************************************************++ + This function calls assertion failure and records assertion failure + in log file. + +--*********************************************************************/ + +{ + PuDbgPrintAssertFailed( pDebugPrints, pszFilePath, nLineNum, pszFunctionName, + pszExpression, + pszMessage ); + if ( !g_fAvoidShutdownAsserts ) + { + DebugBreak(); + } + + return 0; +} // PuDbgAssertFailed() + +#pragma optimize( "", on ) // restore frame pointer omission (FPO) + +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) +/********************************************************************++ + This function calls assertion failure and records assertion failure + in log file. + +--*********************************************************************/ + +{ + PuDbgPrint( pDebugPrints, pszFilePath, nLineNum, pszFunctionName, + " Assertion (%s) Failed: %s\n", + pszExpression, + pszMessage ); + return 0; +} // PuDbgPrintAssertFailed() + + + +VOID +PuDbgPrintCurrentTime( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName + ) +/********************************************************************++ + This function generates the current time and prints it out to debugger + for tracing out the path traversed, if need be. + + Arguments: + pszFile pointer to string containing the name of the file + lineNum line number within the file where this function is called. + + Returns: + NO_ERROR always. +--*********************************************************************/ + +{ + PuDbgPrint( pDebugPrints, pszFilePath, nLineNum, pszFunctionName, + " TickCount = %u\n", + GetTickCount() + ); + + return; +} // PrintOutCurrentTime() + + + + +DWORD +PuLoadDebugFlagsFromReg(IN HKEY hkey, IN DWORD dwDefault) +/********************************************************************++ + This function reads the debug flags assumed to be stored in + the location "DebugFlags" under given key. + If there is any error the default value is returned. +--*********************************************************************/ + +{ + DWORD err; + DWORD dwDebug = dwDefault; + DWORD dwBuffer; + DWORD cbBuffer = sizeof(dwBuffer); + DWORD dwType; + + if( hkey != NULL ) + { + err = RegQueryValueExA( hkey, + DEBUG_FLAGS_REGISTRY_LOCATION_A, + NULL, + &dwType, + (LPBYTE)&dwBuffer, + &cbBuffer ); + + if( ( err == NO_ERROR ) && ( dwType == REG_DWORD ) ) + { + dwDebug = dwBuffer; + } + } + + return dwDebug; +} // PuLoadDebugFlagsFromReg() + + + + +DWORD +PuLoadDebugFlagsFromRegStr(IN LPCSTR pszRegKey, IN DWORD dwDefault) +/********************************************************************++ +Description: + This function reads the debug flags assumed to be stored in + the location "DebugFlags" under given key location in registry. + If there is any error the default value is returned. + +Arguments: + pszRegKey - pointer to registry key location from where to read the key from + dwDefault - default values in case the read from registry fails + +Returns: + Newly read value on success + If there is any error the dwDefault is returned. +--*********************************************************************/ + +{ + HKEY hkey = NULL; + + DWORD dwVal = dwDefault; + + DWORD dwError = RegOpenKeyExA(HKEY_LOCAL_MACHINE, + pszRegKey, + 0, + KEY_READ, + &hkey); + if ( dwError == NO_ERROR) { + dwVal = PuLoadDebugFlagsFromReg( hkey, dwDefault); + RegCloseKey( hkey); + hkey = NULL; + } + + return ( dwVal); +} // PuLoadDebugFlagsFromRegStr() + + + + + +DWORD +PuSaveDebugFlagsInReg(IN HKEY hkey, IN DWORD dwDbg) +/********************************************************************++ + Saves the debug flags in registry. On failure returns the error code for + the operation that failed. + +--*********************************************************************/ +{ + DWORD err; + + if( hkey == NULL ) { + + err = ERROR_INVALID_PARAMETER; + } else { + + err = RegSetValueExA(hkey, + DEBUG_FLAGS_REGISTRY_LOCATION_A, + 0, + REG_DWORD, + (LPBYTE)&dwDbg, + sizeof(dwDbg) ); + } + + return (err); +} // PuSaveDebugFlagsInReg() + + +VOID +PuDbgCaptureContext ( + OUT PCONTEXT ContextRecord + ) +{ + // + // This space intentionally left blank. + // + UNREFERENCED_PARAMETER( ContextRecord ); +} // PuDbgCaptureContext + + +/****************************** End of File ******************************/ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c new file mode 100644 index 0000000000..bfb78aa717 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//#include +//#include +//#include +#include +#include +#include +#include + + +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) + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c new file mode 100644 index 0000000000..58eeb4863f --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//#include +//#include +//#include +#include +#include +#include +#include +#include + + +#define ALLOC_MEM(cb) (PVOID)LocalAlloc( LPTR, (cb) ) +#define FREE_MEM(ptr) (VOID)LocalFree( (HLOCAL)(ptr) ) + + + +PTRACE_LOG +CreateTraceLog( + IN LONG LogSize, + IN LONG ExtraBytesInHeader, + IN LONG EntrySize + ) +/*++ + +Routine Description: + + Creates a new (empty) 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. + + EntrySize - The size (in bytes) of each entry. + +Return Value: + + PTRACE_LOG - Pointer to the newly created log if successful, + NULL otherwise. + +--*/ +{ + + ULONG ulTotalSize = 0; + ULONG ulLogSize = 0; + ULONG ulEntrySize = 0; + ULONG ulTmpResult = 0; + ULONG ulExtraBytesInHeader = 0; + PTRACE_LOG log = NULL; + HRESULT hr = S_OK; + + // + // Sanity check the parameters. + // + + //DBG_ASSERT( LogSize > 0 ); + //DBG_ASSERT( EntrySize > 0 ); + //DBG_ASSERT( ExtraBytesInHeader >= 0 ); + //DBG_ASSERT( ( EntrySize & 3 ) == 0 ); + + // + // converting to unsigned long. Since all these values are positive + // so its safe to cast them to their unsigned equivalent directly. + // + ulLogSize = (ULONG) LogSize; + ulEntrySize = (ULONG) EntrySize; + ulExtraBytesInHeader = (ULONG) ExtraBytesInHeader; + + // + // Check if the multiplication operation will overflow a LONG + // ulTotalSize = LogSize * EntrySize; + // + hr = ULongMult( ulLogSize, ulEntrySize, &ulTotalSize ); + if ( FAILED(hr) ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return NULL; + } + + // + // check for overflow in addition operation. + // ulTmpResult = sizeof(TRACE_LOG) + ulExtraBytesInHeader + // + hr = ULongAdd( (ULONG) sizeof(TRACE_LOG), ulExtraBytesInHeader, &ulTmpResult ); + if ( FAILED(hr) ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return NULL; + } + + // + // check for overflow in addition operation. + // ulTotalSize = ulTotalSize + ulTmpResult; + // + hr = ULongAdd( ulTmpResult, ulTotalSize, &ulTotalSize ); + if ( FAILED(hr) ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return NULL; + } + + if ( ulTotalSize > (ULONG) 0x7FFFFFFF ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return NULL; + } + + // + // Allocate & initialize the log structure. + // + + log = (PTRACE_LOG)ALLOC_MEM( ulTotalSize ); + + // + // Initialize it. + // + + if( log != NULL ) { + + RtlZeroMemory( log, ulTotalSize ); + + log->Signature = TRACE_LOG_SIGNATURE; + log->LogSize = LogSize; + log->NextEntry = -1; + log->EntrySize = EntrySize; + log->LogBuffer = (PUCHAR)( log + 1 ) + ExtraBytesInHeader; + } + + return log; + +} // CreateTraceLog + + +VOID +DestroyTraceLog( + IN PTRACE_LOG Log + ) +/*++ + +Routine Description: + + Destroys a trace log buffer created with CreateTraceLog(). + +Arguments: + + Log - The trace log buffer to destroy. + +Return Value: + + None. + +--*/ +{ + if ( Log != NULL ) { + //DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE ); + + Log->Signature = TRACE_LOG_SIGNATURE_X; + FREE_MEM( Log ); + } + +} // DestroyTraceLog + + +LONG +WriteTraceLog( + IN PTRACE_LOG Log, + IN PVOID Entry + ) +/*++ + +Routine Description: + + Writes a new entry to the specified trace log. + +Arguments: + + Log - The log to write to. + + Entry - Pointer to the data to write. This buffer is assumed to be + Log->EntrySize bytes long. + +Return Value: + + Index of entry in log. This is useful for correlating the output + of !inetdbg.ref to a particular point in the output debug stream + +--*/ +{ + + PUCHAR target; + ULONG index; + + //DBG_ASSERT( Log != NULL ); + //DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE ); + //DBG_ASSERT( Entry != NULL ); + + // + // Find the next slot, copy the entry to the slot. + // + + index = ( (ULONG) InterlockedIncrement( &Log->NextEntry ) ) % (ULONG) Log->LogSize; + + //DBG_ASSERT( index < (ULONG) Log->LogSize ); + + target = Log->LogBuffer + ( index * Log->EntrySize ); + + RtlCopyMemory( + target, + Entry, + Log->EntrySize + ); + + return index; +} // WriteTraceLog + + +VOID +ResetTraceLog( + IN PTRACE_LOG Log + ) +{ + + //DBG_ASSERT( Log != NULL ); + //DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE ); + + RtlZeroMemory( + ( Log + 1 ), + Log->LogSize * Log->EntrySize + ); + + Log->NextEntry = -1; + +} // ResetTraceLog + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx new file mode 100644 index 0000000000..cd6987d860 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx @@ -0,0 +1,348 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "pudebug.h" + +#define MAX_OBJECT_NAME 256 // chars + + +LONG g_PuDbgEventsCreated = 0; +LONG g_PuDbgSemaphoresCreated = 0; +LONG g_PuDbgMutexesCreated = 0; + + + +LPSTR +PuDbgpBuildObjectName( + __in LPSTR ObjectNameBuffer, + IN ULONG ObjectNameBufferCch, + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address + ) + +/*++ + +Routine Description: + + Internal routine that builds an appropriate object name based on + the file name, line number, member name, address, and process ID. + +Arguments: + + ObjectNameBuffer - Pointer to the target buffer for the name. + + FileName - The filename of the source creating the object. This + is __FILE__ of the caller. + + LineNumber - The line number within the source. This is __LINE__ + of the caller. + + MemberName - The member/global variable name where the object handle + is to be stored. + + Address - The address of the containing structure/class or of the + global itself. + +Return Value: + + LPSTR - Pointer to ObjectNameBuffer if successful, NULL otherwise. + + N.B. This routine always returns NULL when running under Win9x. + +--*/ + +{ + + PLATFORM_TYPE platformType; + LPSTR fileNamePart; + LPSTR result; + + // + // We have no convenient way to dump objects w/ names from + // Win9x, so we'll only enable this functionality under NT. + // + + // platformType = IISGetPlatformType(); + + // + // By default IIS-Duct-tape will only run on NT platforms. So + // do not worry about getting the platform types yet. + // + platformType = PtNtServer; + result = NULL; + + if( platformType == PtNtServer || + platformType == PtNtWorkstation ) { + + // + // Find the filename part of the incoming source file name. + // + + fileNamePart = strrchr( FileName, '\\' ); + + if( fileNamePart == NULL ) { + fileNamePart = strrchr( FileName, '/' ); + } + + if( fileNamePart == NULL ) { + fileNamePart = strrchr( FileName, ':' ); + } + + if( fileNamePart == NULL ) { + fileNamePart = FileName; + } else { + fileNamePart++; + } + + // + // Ensure we don't overwrite our object name buffer. + // + + if( ( sizeof(":1234567890 :12345678 PID:1234567890") + + strlen( fileNamePart ) + + strlen( MemberName ) ) < MAX_OBJECT_NAME ) { + + sprintf_s( + ObjectNameBuffer, + ObjectNameBufferCch, + "%s:%lu %s:%08p PID:%lu", + fileNamePart, + LineNumber, + MemberName, + Address, + GetCurrentProcessId() + ); + + result = ObjectNameBuffer; + + } + + } + + return result; + +} // PuDbgpBuildObjectName + + +HANDLE +PuDbgCreateEvent( + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address, + IN BOOL ManualReset, + IN BOOL InitialState + ) + +/*++ + +Routine Description: + + Creates a new event object. + +Arguments: + + FileName - The filename of the source creating the object. This + is __FILE__ of the caller. + + LineNumber - The line number within the source. This is __LINE__ + of the caller. + + MemberName - The member/global variable name where the object handle + is to be stored. + + Address - The address of the containing structure/class or of the + global itself. + + ManualReset - TRUE to create a manual reset event, FALSE to create + an automatic reset event. + + InitialState - The intitial state of the event object. + +Return Value: + + HANDLE - Handle to the object if successful, NULL otherwise. + +--*/ + +{ + UNREFERENCED_PARAMETER( Address ); + UNREFERENCED_PARAMETER( MemberName ); + UNREFERENCED_PARAMETER( LineNumber ); + UNREFERENCED_PARAMETER( FileName ); + + LPSTR objName = NULL; + HANDLE objHandle; + //CHAR objNameBuffer[MAX_OBJECT_NAME]; + +/* + disable passing names to event creation + Longhorn forces some security checks that + prevent hostable webcore to work on checked builds + (at least ASP requests are failing when + trying to create event) + + objName = PuDbgpBuildObjectName( + objNameBuffer, + FileName, + LineNumber, + MemberName, + Address + ); +*/ + objHandle = CreateEventA( + NULL, // lpEventAttributes + ManualReset, // bManualReset + InitialState, // bInitialState + objName // lpName + ); + + if( objHandle != NULL ) { + InterlockedIncrement( &g_PuDbgEventsCreated ); + } + + return objHandle; + +} // PuDbgCreateEvent + + +HANDLE +PuDbgCreateSemaphore( + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address, + IN LONG InitialCount, + IN LONG MaximumCount + ) + +/*++ + +Routine Description: + + Creates a new semaphore object. + +Arguments: + + FileName - The filename of the source creating the object. This + is __FILE__ of the caller. + + LineNumber - The line number within the source. This is __LINE__ + of the caller. + + MemberName - The member/global variable name where the object handle + is to be stored. + + Address - The address of the containing structure/class or of the + global itself. + + InitialCount - The initial count of the semaphore. + + MaximumCount - The maximum count of the semaphore. + +Return Value: + + HANDLE - Handle to the object if successful, NULL otherwise. + +--*/ + +{ + + LPSTR objName; + HANDLE objHandle; + CHAR objNameBuffer[MAX_OBJECT_NAME]; + + objName = PuDbgpBuildObjectName( + objNameBuffer, + sizeof( objNameBuffer) / sizeof( objNameBuffer[0] ), + FileName, + LineNumber, + MemberName, + Address + ); + + objHandle = CreateSemaphoreA( + NULL, // lpSemaphoreAttributes + InitialCount, // lInitialCount + MaximumCount, // lMaximumCount + objName // lpName + ); + + if( objHandle != NULL ) { + InterlockedIncrement( &g_PuDbgSemaphoresCreated ); + } + + return objHandle; + +} // PuDbgCreateSemaphore + + +HANDLE +PuDbgCreateMutex( + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address, + IN BOOL InitialOwner + ) + +/*++ + +Routine Description: + + Creates a new mutex object. + +Arguments: + + FileName - The filename of the source creating the object. This + is __FILE__ of the caller. + + LineNumber - The line number within the source. This is __LINE__ + of the caller. + + MemberName - The member/global variable name where the object handle + is to be stored. + + Address - The address of the containing structure/class or of the + global itself. + + InitialOwner - TRUE if the mutex should be created "owned". + +Return Value: + + HANDLE - Handle to the object if successful, NULL otherwise. + +--*/ + +{ + + LPSTR objName; + HANDLE objHandle; + CHAR objNameBuffer[MAX_OBJECT_NAME]; + + objName = PuDbgpBuildObjectName( + objNameBuffer, + sizeof( objNameBuffer) / sizeof( objNameBuffer[0] ), + FileName, + LineNumber, + MemberName, + Address + ); + + objHandle = CreateMutexA( + NULL, // lpMutexAttributes + InitialOwner, // bInitialOwner, + objName // lpName + ); + + if( objHandle != NULL ) { + InterlockedIncrement( &g_PuDbgMutexesCreated ); + } + + return objHandle; + +} // PuDbgCreateMutex + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h new file mode 100644 index 0000000000..63a67d68f4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _BLDVER_H_ +#define _BLDVER_H_ + +#define STR_HELPER(x) #x +#define WSTR_HELPER(x) L#x +#define NUM_TO_STR(x) STR_HELPER(x) +#define NUM_TO_WSTR(x) WSTR_HELPER(x) + +// +// Build versions are properties of the build system but can be overwritten below +// +// #define PRODUCT_MAJOR 7 +// #define PRODUCT_MINOR 1 +// #define BUILD_MAJOR 1972 +// #define BUILD_MINOR 0 + +#define PRODUCT_MAJOR_STRING NUM_TO_STR(PRODUCT_MAJOR) +#define PRODUCT_MAJOR_STRING_L NUM_TO_WSTR(PRODUCT_MAJOR) +#define PRODUCT_MAJOR_NUMBER PRODUCT_MAJOR + +#define PRODUCT_MINOR_STRING NUM_TO_STR(PRODUCT_MINOR) +#define PRODUCT_MINOR_STRING_L NUM_TO_WSTR(PRODUCT_MINOR) +#define PRODUCT_MINOR_NUMBER PRODUCT_MINOR + +#define BUILD_MAJOR_STRING NUM_TO_STR(BUILD_MAJOR) +#define BUILD_MAJOR_STRING_L NUM_TO_WSTR(BUILD_MAJOR) +#define BUILD_MAJOR_NUMBER BUILD_MAJOR + +#define BUILD_MINOR_STRING NUM_TO_STR(BUILD_MINOR) +#define BUILD_MINOR_STRING_L NUM_TO_WSTR(BUILD_MINOR) +#define BUILD_MINOR_NUMBER BUILD_MINOR + +#define BUILD_NUMBER BUILD_MAJOR_STRING "." BUILD_MINOR_STRING +#define BUILD_NUM BUILD_MAJOR , BUILD_MINOR +#define PRODUCT_NUMBER PRODUCT_MAJOR_STRING "." PRODUCT_MINOR_STRING +#define PRODUCT_NUM PRODUCT_MAJOR , PRODUCT_MINOR +#define INET_VERSION PRODUCT_MAJOR_STRING "." PRODUCT_MINOR_STRING "." BUILD_MAJOR_STRING "." BUILD_MINOR_STRING +#define INET_VERSION_L PRODUCT_MAJOR_STRING_L L"." PRODUCT_MINOR_STRING_L L"." BUILD_MAJOR_STRING_L L"." BUILD_MINOR_STRING_L +#define INET_VER PRODUCT_MAJOR , PRODUCT_MINOR , BUILD_MAJOR , BUILD_MINOR + +#define BUILD_PRIVATE "Built by IISBLD on IISBLD.\0" + +#undef VER_PRODUCTVERSION +#undef VER_PRODUCTVERSION_STR +#undef VER_PRODUCTMAJORVERSION +#undef VER_PRODUCTMINORVERSION +#undef VER_PRODUCTBUILD +#undef VER_PRODUCTBUILD_QFE +#undef VER_PRODUCTNAME_STR +#undef VER_COMPANYNAME_STR + +#define VER_PRODUCTVERSION PRODUCT_MAJOR,PRODUCT_MINOR,BUILD_MAJOR,BUILD_MINOR +#define VER_PRODUCTVERSION_STR PRODUCT_MAJOR_STRING "." PRODUCT_MINOR_STRING "." BUILD_MAJOR_STRING "." BUILD_MINOR_STRING +#define VER_PRODUCTMAJORVERSION PRODUCT_MAJOR +#define VER_PRODUCTMINORVERSION PRODUCT_MINOR +#define VER_PRODUCTBUILD BUILD_MAJOR +#define VER_PRODUCTBUILD_QFE BUILD_MINOR +#define VER_PRODUCTNAME_STR "Microsoft Web Platform Extensions" +#define VER_COMPANYNAME_STR "Microsoft Corporation" + +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc new file mode 100644 index 0000000000..30a96499ec --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// BLDVER.RC - Standard version resource for CoreXT applications. + +// Before including this file into your .rc, define the following +// macros for your application (don't forget the \0's): +// #define RC_VERSION_FILE_DESCRIPTION "Test DLL\0" +// #define RC_VERSION_INTERNAL_NAME "Test\0" +// #define RC_VERSION_ORIGINAL_FILE_NAME "Test.DLL\0" + +#include +#include + +VS_VERSION_INFO VERSIONINFO + +FILEVERSION INET_VER +PRODUCTVERSION INET_VER + +FILEFLAGSMASK 0x3fL +#ifdef DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + +// +// Global definitions +// +#ifndef RC_VERSION_COMPANY_NAME + #define RC_VERSION_COMPANY_NAME "Microsoft Corporation\0" +#endif + +#ifndef RC_VERSION_PRODUCT_NAME + #define RC_VERSION_PRODUCT_NAME "Microsoft\256 Web Platform Extensions\0" +#endif + +#ifndef RC_VERSION_LEGAL_COPYRIGHT + #define RC_VERSION_LEGAL_COPYRIGHT "Copyright \251 Microsoft Corporation\0" +#endif + +#ifndef RC_VERSION_LEGAL_TRADEMARKS + #define RC_VERSION_LEGAL_TRADEMARKS "Microsoft\256 is a registered trademark of Microsoft Corporation.\0" +#endif + +FILEOS 0x4L +FILETYPE 0x1L +FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RC_VERSION_COMPANY_NAME + VALUE "FileDescription", RC_VERSION_FILE_DESCRIPTION + VALUE "InternalName", RC_VERSION_INTERNAL_NAME + VALUE "LegalCopyright", RC_VERSION_LEGAL_COPYRIGHT + VALUE "LegalTrademarks", RC_VERSION_LEGAL_TRADEMARKS + VALUE "OriginalFilename", RC_VERSION_ORIGINAL_FILE_NAME + VALUE "ProductName", RC_VERSION_PRODUCT_NAME + VALUE "FileVersion", INET_VERSION + VALUE "ProductVersion", INET_VERSION + VALUE "PrivateBuild", BUILD_PRIVATE +#ifdef OLEREGISTER + VALUE "OLESelfRegister","\0" +#endif + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln new file mode 100644 index 0000000000..4ec3c19636 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iisca", "iisca\lib\iisca.vcxproj", "{7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLib", "IIS-Common\lib\CommonLib.vcxproj", "{B54A8F61-60DE-4AD9-87CA-D102F230678E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x64.ActiveCfg = Debug|x64 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x64.Build.0 = Debug|x64 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x86.ActiveCfg = Debug|Win32 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x86.Build.0 = Debug|Win32 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x64.ActiveCfg = Release|x64 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x64.Build.0 = Release|x64 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x86.ActiveCfg = Release|Win32 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x86.Build.0 = Release|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.ActiveCfg = Debug|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.Build.0 = Debug|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.ActiveCfg = Debug|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.Build.0 = Debug|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.ActiveCfg = Release|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.Build.0 = Release|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.ActiveCfg = Release|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3DC22D38-F38B-420A-9AD1-77F2512B35FF} + EndGlobalSection +EndGlobal diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE new file mode 100644 index 0000000000..21071075c2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md new file mode 100644 index 0000000000..22e594aa6c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md @@ -0,0 +1,18 @@ +Microsoft IIS Setup +-------------------------------- + +The repository contains setup resources shared by IIS Out-Of-Band (OOB) products. + +### Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi new file mode 100644 index 0000000000..820cc86f4e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp new file mode 100644 index 0000000000..883a228a33 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +HRESULT +CheckInstallToSharedConfig( + IN MSIHANDLE hInstall, + BOOL * pbShouldInstall + ) +{ + HRESULT hr = S_OK; + STRU strShared; + STRU strWriteToShared; + + *pbShouldInstall = FALSE; + + //Check if config is shared + hr = MsiUtilGetProperty( hInstall, L"IISCONFIGISSHARED", &strShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if( 0 != wcscmp( strShared.QueryStr(), L"1" ) ) + { + //config is not shared, tell caller to schedule executeCA for config + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration is NOT shared. Setup will schedule the deferred custom action."); + *pbShouldInstall = TRUE; + goto exit; + } + + // + //config is shared lets check IIUSESHAREDCONFIG Property + // + hr = MsiUtilGetProperty( hInstall, L"IIUSESHAREDCONFIG", &strWriteToShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if( 0 == wcscmp( strWriteToShared.QueryStr(), L"1" ) ) + { + //Config is shared but property is set + //tell caller to schedule executeCA for config + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration IS shared. IIUSESHAREDCONFIG property indicated that setup SHOULD schedule the deferred custom action.."); + *pbShouldInstall = TRUE; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration IS shared. IIUSESHAREDCONFIG property indicated that setup should NOT schedule the deferred custom action."); + } + +exit: + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h new file mode 100644 index 0000000000..0ac0ea9852 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +HRESULT +CheckInstallToSharedConfig( + IN MSIHANDLE hInstall, + BOOL * pbShouldInstall + ); diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def new file mode 100644 index 0000000000..8ba47da929 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def @@ -0,0 +1,15 @@ +; Copyright (c) Microsoft Corporation. All rights reserved. +; Licensed under the MIT license. + +LIBRARY iisca + +EXPORTS + + ; IIS Common Config custom actions + + IISScheduleInstallCA + IISScheduleUninstallCA + IISExecuteCA + IISBeginTransactionCA + IISRollbackTransactionCA + IISCommitTransactionCA diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp new file mode 100644 index 0000000000..b57a5d3037 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp @@ -0,0 +1,271 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +// +// Public functions +// + +HRESULT +RegisterCgiRestriction( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szPath, + IN BOOL fAllowed, + IN OPTIONAL CONST WCHAR * szGroupId, + IN OPTIONAL CONST WCHAR * szDescription + ) +{ + HRESULT hr = NOERROR; + + CComPtr pCgiRestrictionSection; + CComPtr pCgiRestrictionCollection; + CComPtr pNewCgiRestrictionElement; + + BSTR bstrAppHostConfigPath = SysAllocString(szConfigPath); + BSTR bstrCgiRestriction = SysAllocString( L"system.webServer/security/isapiCgiRestriction" ); + BSTR bstrAdd = SysAllocString( L"add" ); + + if( !bstrAppHostConfigPath || + !bstrCgiRestriction || + !bstrAdd ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + // + // Remove any existing web service first, + // ignore any resulting errors. + // + + hr = UnRegisterCgiRestriction( + pAdminMgr, + szConfigPath, + szPath, + FALSE // do NOT expand environment strings + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + // press on regardless + } + + hr = UnRegisterCgiRestriction( + pAdminMgr, + szConfigPath, + szPath, + TRUE // DO expand environment strings + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + // press on regardless + } + + // + // Get the ISAPI CGI Restriction collection + // + + hr = pAdminMgr->GetAdminSection( bstrCgiRestriction, + bstrAppHostConfigPath, + &pCgiRestrictionSection ); + + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pCgiRestrictionSection->get_Collection( &pCgiRestrictionCollection ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + // + // Create a new element + // + + hr = pCgiRestrictionCollection->CreateNewElement( bstrAdd, + &pNewCgiRestrictionElement ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementStringProperty( + pNewCgiRestrictionElement, + L"path", + szPath + ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementStringProperty( + pNewCgiRestrictionElement, + L"allowed", + fAllowed ? L"true" : L"false" + ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + if( szGroupId && *szGroupId ) + { + hr = SetElementStringProperty( + pNewCgiRestrictionElement, + L"groupId", + szGroupId + ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + if( szDescription && *szDescription ) + { + hr = SetElementStringProperty( + pNewCgiRestrictionElement, + L"description", + szDescription + ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + // + // Add the new element + // + + hr = pCgiRestrictionCollection->AddElement( pNewCgiRestrictionElement ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrCgiRestriction ); + SysFreeString( bstrAdd ); + + return hr; +} + +HRESULT +UnRegisterCgiRestriction( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szPath, + IN BOOL fExpandPath + ) +{ + HRESULT hr = NOERROR; + + CComPtr pCgiRestrictionSection; + CComPtr pCgiRestrictionCollection; + + BSTR bstrAppHostConfigPath = SysAllocString(szConfigPath); + BSTR bstrCgiRestriction = SysAllocString( L"system.webServer/security/isapiCgiRestriction" ); + + UINT numDeleted; + + STRU expandedPath; + + if( !bstrAppHostConfigPath || + !bstrCgiRestriction ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + if (fExpandPath) + { + hr = expandedPath.CopyAndExpandEnvironmentStrings(szPath); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + szPath = expandedPath.QueryStr(); + } + + // + // Remove from the ISAPI CGI Restriction collection + // + + hr = pAdminMgr->GetAdminSection( bstrCgiRestriction, + bstrAppHostConfigPath, + &pCgiRestrictionSection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pCgiRestrictionSection->get_Collection( &pCgiRestrictionCollection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = DeleteAllElementsFromCollection( pCgiRestrictionCollection, + L"path", + szPath, + FIND_ELEMENT_CASE_INSENSITIVE, + &numDeleted + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( numDeleted == 0 ) + { + DBGWARN(( DBG_CONTEXT, + "Expected to find %S in ISAPI CGI Restriction collection\n", + szPath )); + } + +exit: + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrCgiRestriction ); + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h new file mode 100644 index 0000000000..68ae838d07 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + + +#ifndef _CGI_RESTRICTIONS_H_ +#define _CGI_RESTRICTIONS_H_ + + +HRESULT +RegisterCgiRestriction( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szPath, + IN BOOL fAllowed, + IN OPTIONAL CONST WCHAR * szGroupId, + IN OPTIONAL CONST WCHAR * szDescription + ); + + +HRESULT +UnRegisterCgiRestriction( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szPath, + IN BOOL fExpandPath = FALSE + ); + + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp new file mode 100644 index 0000000000..8d44a69506 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +UINT +__stdcall +CheckForSharedConfigurationCA( + MSIHANDLE hInstall +) +{ + HRESULT hr = S_OK; + UINT status = ERROR_SUCCESS; + BOOL fIsSharedConfig = FALSE; + STRU strWriteToShared; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hr = GetSharedConfigEnabled( &fIsSharedConfig ); + if ( FAILED( hr ) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Unable to detect whether shared configuration is in use."); + status = LogMsiCustomActionError( hInstall, 30001 ); + goto exit; + } + if ( fIsSharedConfig ) + { + //set config shared property. + //will be used by other CAs via CheckInstallToSharedConfig + hr = MsiSetProperty( hInstall, L"IISCONFIGISSHARED", L"1" ); + if ( FAILED( hr ) ) + { + goto exit; + } + // + //config is shared lets check if user + //set public property IIUSESHAREDCONFIG + // + hr = MsiUtilGetProperty( hInstall, L"IIUSESHAREDCONFIG", &strWriteToShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if( 0 == wcscmp( strWriteToShared.QueryStr(), L"1" ) ) + { + //Config is shared but property is set + //tell caller to schedule executeCA for config + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration IS shared. IIUSESHAREDCONFIG property indicated that setup SHOULD schedule the deferred custom action.."); + } + else + { + // + //public property not set error-out install + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Shared Configuration detected."); + status = LogMsiCustomActionError( hInstall, 30002 ); + goto exit; + } + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No Shared Configuration detected."); + } + +exit: + + IISLogClose(); + return status; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h new file mode 100644 index 0000000000..f69b0101c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + + +#ifndef _CONFIG_CUSTOM_H_ +#define _CONFIG_CUSTOM_H_ + + +UINT +__stdcall +CheckForSharedConfigurationCA( + MSIHANDLE hInstall +); + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp new file mode 100644 index 0000000000..ed39ca6af6 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp @@ -0,0 +1,594 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +#define CheckAndGoToExit(hr,sev,msg,prop) if (FAILED(hr)) { DBGERROR_HR(hr); IISLogWrite(sev, msg, prop, hr);goto exit;} +#define CheckAndReturnHr(hr,sev,msg,prop) if (FAILED(hr)) { DBGERROR_HR(hr); IISLogWrite(sev, msg, prop, hr);return hr;} + + +HRESULT +GetConsoleIntProperty( + IN MSIHANDLE hRecord, + IN UINT field, + __inout CA_DATA_WRITER * cadata) +{ + HRESULT hr = S_OK; + + UINT dwValue = 0; + hr = MsiUtilRecordGetInteger( hRecord, + field, + &dwValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", field, hr); + return hr; + } + + hr = cadata->Write(dwValue); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + return hr; + } + + return hr; +} + +HRESULT +GetConsoleProperties( + IN MSIHANDLE hRecord, + __inout CA_DATA_WRITER * cadata) +{ + HRESULT hr = S_OK; + + /*STACK_STRU( strTextColour, 128 ); + STACK_STRU( strBackgroundColour, 128 );*/ + + enum { + CA_CONSOLEPROPS_QUCIKEDIT = 5, + CA_CONSOLEPROPS_INSERTMODE, + CA_CONSOLEPROPS_WINDOWWIDTH, + CA_CONSOLEPROPS_WINDOWHEIGHT, + CA_CONSOLEPROPS_BUFFERWIDTH, + CA_CONSOLEPROPS_BUFFERHEIGHT, + /* CA_CONSOLEPROPS_TEXTCOLOUR, + CA_CONSOLEPROPS_BACKGROUNDCOLOUR*/ + }; + + // GET QuickEdit int + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_QUCIKEDIT, + cadata ); + if ( FAILED(hr) ) { return hr;} + + // GET InsertMode + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_INSERTMODE, + cadata ); + if ( FAILED(hr) ) { return hr;} + + + // GET WindowWidth + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_WINDOWWIDTH, + cadata ); + if ( FAILED(hr) ) { return hr;} + + + // GET WindowHeight + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_WINDOWHEIGHT, + cadata ); + if ( FAILED(hr) ) { return hr;} + + + // GET BufferWidth + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_BUFFERWIDTH, + cadata ); + if ( FAILED(hr) ) { return hr;} + + + // GET BufferHeight + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_BUFFERHEIGHT, + cadata ); + if ( FAILED(hr) ) { return hr;} + + //// Get Text colours + //hr = MsiUtilRecordGetString( hRecord, + // CA_CONSOLEPROPS_TEXTCOLOUR, + // &strTextColour ); + + //CheckAndReturnHr(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_TEXTCOLOUR); + + //hr = cadata->Write( strTextColour.QueryStr(), strTextColour.QueryCCH() ); + //if ( FAILED(hr) ) + //{ + // DBGERROR_HR(hr); + // IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + // return hr; + //} + + //// Get Background colours + //hr = MsiUtilRecordGetString( hRecord, + // CA_CONSOLEPROPS_BACKGROUNDCOLOUR, + // &strBackgroundColour ); + + //CheckAndReturnHr(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_TEXTCOLOUR); + + //hr = cadata->Write( strBackgroundColour.QueryStr(), strBackgroundColour.QueryCCH() ); + //if ( FAILED(hr) ) + //{ + // DBGERROR_HR(hr); + // IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + // return hr; + //} + + return hr; +} + +UINT +WINAPI +ScheduleSetConsolePropertiesCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strShortcut, 128 ); + STACK_STRU( strDirectoryId, 256 ); // Directory Identifier + STACK_STRU( strDirectoryName, 256 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strShortcutName, 256 ); + STACK_STRU( strData, 256); + + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISShortcutConsoleProperties`.`Shortcut_`, " + L"`Shortcut`.`Component_`, " + L"`Shortcut`.`Name`, " + L"`Directory`.`Directory`, " + L"`IISShortcutConsoleProperties`.`QuickEdit`, " + L"`IISShortcutConsoleProperties`.`InsertMode`, " + L"`IISShortcutConsoleProperties`.`WindowWidth`, " + L"`IISShortcutConsoleProperties`.`WindowHeight`, " + L"`IISShortcutConsoleProperties`.`BufferWidth`, " + L"`IISShortcutConsoleProperties`.`BufferHeight` " + /*L"`IISShortcutConsoleProperties`.`TextColor`, " + L"`IISShortcutConsoleProperties`.`BackgroundColor` "*/ + L"FROM `IISShortcutConsoleProperties`, `Shortcut`, `Directory` " + L"WHERE `IISShortcutConsoleProperties`.`Shortcut_`=`Shortcut`.`Shortcut` " + L"AND `Shortcut`.`Directory_`=`Directory`.`Directory`"; + + + CA_DATA_WRITER cadata; + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + BOOL scheduleDefferedCA = FALSE; + + enum { + CA_CONSOLEPROPS_SHORTCUT = 1, + CA_CONSOLEPROPS_COMPONENT, + CA_CONSOLEPROPS_SHORTCUTNAME, + CA_CONSOLEPROPS_DIRECTORY, + }; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting MSI database, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening View, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error executing view, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_CONSOLEPROPS_COMPONENT, + &strComponent ); + CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_COMPONENT); + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting state for component %s, hr=0x%x", strComponent.QueryStr(), hr); + goto exit; + } + + // Only run if the comonent is installing or reinstalling + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + // Get Shortcut location + { + // GET: directory where shortcut is + // Get the directory id for the shortcut + hr = MsiUtilRecordGetString( hRecord, + CA_CONSOLEPROPS_DIRECTORY, + &strDirectoryId ); + + CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_DIRECTORY); + + // Get directory path + hr = MsiUtilGetProperty(hInstall, strDirectoryId.QueryStr(), &strDirectoryName ); + + CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting value for directory record %s, hr=0x%x", strDirectoryId.QueryStr()); + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Shortcut Directory: '%s'.", + strDirectoryName.QueryStr()); + // ENDGET: directory where shortcut is + + + // GET: Short and Long names of shortcuts + hr = MsiUtilRecordGetString( hRecord, + CA_CONSOLEPROPS_SHORTCUTNAME, + &strShortcutName ); + + CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_SHORTCUTNAME); + + + // strShortcutName contains the short and long file names of the shortcut + PCWSTR pszPrevious = strShortcutName.QueryStr(); + // Append the shortcut name to the directory and write to cadata + // Write the short and long shortcut paths + for ( DWORD i = 0; i < strShortcutName.QueryCCH() + 1; i++ ) + { + if ( strShortcutName.QueryStr()[ i ] == L'|' || + strShortcutName.QueryStr()[ i ] == L'\0' ) + { + strShortcutName.QueryStr()[ i ] = L'\0'; + + strData.Copy( strDirectoryName ); + strData.Append(L"\\"); + strData.Append(pszPrevious); + strData.Append(L".lnk"); + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Potential shortcut path: %s", + strData.QueryStr()); + + hr = cadata.Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + + pszPrevious = strShortcutName.QueryStr() + i + 1; + + // Get the console properties + hr = GetConsoleProperties(hRecord, &cadata); + if( FAILED(hr)) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting console properties, hr=0x%x", hr); + goto exit; + } + + // Only schedule custom action if needed + scheduleDefferedCA = TRUE; + } + } + // ENDGET: Short and Long names of shortcuts + } + // End OF getting shortcut location + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + if ( scheduleDefferedCA ) + { + hr = MsiUtilScheduleDeferredAction( hInstall, + L"ExecuteSetConsoleProperties", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action ExecuteSetConsoleProperties scheduled"); + } + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogClose(); + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} + +void IntializeConsoleProps( + IN NT_CONSOLE_PROPS* pConsoleProps + ) +{ + if (!pConsoleProps) + { + return; + } + + pConsoleProps->dbh.cbSize = sizeof(NT_CONSOLE_PROPS); + pConsoleProps->dbh.dwSignature = NT_CONSOLE_PROPS_SIG; + pConsoleProps->bFullScreen = false; + pConsoleProps->uHistoryBufferSize = 50; + pConsoleProps->uNumberOfHistoryBuffers = 4; + pConsoleProps->uCursorSize = 25; + + pConsoleProps->ColorTable[0] = RGB(0,0,0); + pConsoleProps->ColorTable[1] = RGB(0,0,128); + pConsoleProps->ColorTable[2] = RGB(0,128,0); + pConsoleProps->ColorTable[3] = RGB(0,128,128); + pConsoleProps->ColorTable[4] = RGB(128,0,0); + pConsoleProps->ColorTable[5] = RGB(128,0,128); + pConsoleProps->ColorTable[6] = RGB(128,128,0); + pConsoleProps->ColorTable[7] = RGB(192,192,192); + pConsoleProps->ColorTable[8] = RGB(128,128,128); + pConsoleProps->ColorTable[9] = RGB(0,0,255); + pConsoleProps->ColorTable[10] = RGB(0,255,0); + pConsoleProps->ColorTable[11] = RGB(0,255,255); + pConsoleProps->ColorTable[12] = RGB(255,0,0); + pConsoleProps->ColorTable[13] = RGB(255,0,255); + pConsoleProps->ColorTable[14] = RGB(255,255,0); + pConsoleProps->ColorTable[15] = RGB(255,255,255); + + pConsoleProps->wPopupFillAttribute = ((15 << 4) | 3); +} + + +UINT +WINAPI +ExecuteSetConsolePropertiesCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + + BOOL fCoInit = FALSE; + + WCHAR * szShortcutFile = NULL; + /*WCHAR * szTextColour = NULL; + WCHAR * szBackgroundColour = NULL;*/ + INT dwQuickEdit = 0; + INT dwInsertMode = 0; + INT dwWindowWidth = 120; + INT dwWindowHeight = 50; + INT dwBufferWidth = 120; + INT dwBufferHeight = 3000; + + + CA_DATA_READER cadata; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + // + // Retrieve parameters from ca data + // + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error retrieving custom action data, hr=0x%x", hr); + goto exit; + } + + if ( SUCCEEDED( hr = CoInitialize(NULL) ) ) + { + fCoInit = TRUE; + } + + while ( SUCCEEDED(hr = cadata.Read( &szShortcutFile )) ) + { + hr = cadata.Read( &dwQuickEdit); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwInsertMode); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwWindowWidth); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwWindowHeight); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwBufferWidth); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwBufferHeight); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + /*hr = cadata.Read( &szTextColour); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &szBackgroundColour); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + }*/ + + // Check to see if file exists + if(GetFileAttributes(szShortcutFile) != 0xFFFFFFFF) + { + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Shortcut %s exists", szShortcutFile); + + // Get shell + CComPtr sppf; + + if (FAILED(hr = sppf.CoCreateInstance(L"lnkfile")) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error get ShellLink com object, hr=0x%x", hr); + goto exit; + } + + // Load shortcut file + if (FAILED(hr = sppf->Load(szShortcutFile, STGM_READWRITE))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error loading shortcut file %s, hr=0x%x", szShortcutFile, hr); + goto exit; + } + + CComQIPtr spdl(sppf); + if (!spdl) + { + DBGERROR_HR(hr); + goto exit; + } + + NT_CONSOLE_PROPS* pConsoleProps = NULL; + + hr = spdl->CopyDataBlock(NT_CONSOLE_PROPS_SIG, (LPVOID*) &pConsoleProps); + if ( FAILED(hr) || (NULL == pConsoleProps) ) + { + // Create new console properties and set defaults + pConsoleProps = (NT_CONSOLE_PROPS *)malloc(sizeof(NT_CONSOLE_PROPS)); + memset(pConsoleProps,0,sizeof(NT_CONSOLE_PROPS)); + IntializeConsoleProps(pConsoleProps); + } + + pConsoleProps->bQuickEdit = dwQuickEdit > 0; + pConsoleProps->bInsertMode = dwInsertMode > 0; + pConsoleProps->dwWindowSize.X = (short) dwWindowWidth; + pConsoleProps->dwWindowSize.Y = (short) dwWindowHeight; + pConsoleProps->dwScreenBufferSize.X = (short) dwBufferWidth; + pConsoleProps->dwScreenBufferSize.Y = (short) dwBufferHeight; + + pConsoleProps->ColorTable[6] = RGB(238, 237, 240); // text color + pConsoleProps->ColorTable[5] = RGB(1, 36, 86); // backgroud color + pConsoleProps->wFillAttribute = ((5 << 4) | 6 ); + + + spdl->RemoveDataBlock(NT_CONSOLE_PROPS_SIG); + if (FAILED(hr = spdl->AddDataBlock((void *)pConsoleProps))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error setting NT_CONSOLE_PROPS on shortcut file %s, hr=0x%x", szShortcutFile, hr); + goto exit; + } + + if (FAILED(hr = sppf->Save(NULL, TRUE))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error saving changes to shortcut, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Successfully added properties to shortcut %s", + szShortcutFile); + + } + } + + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogClose(); + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.h new file mode 100644 index 0000000000..11692e14b3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +UINT +WINAPI +ScheduleSetConsolePropertiesCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +ExecuteSetConsolePropertiesCA( + IN MSIHANDLE hInstall + ); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.cpp new file mode 100644 index 0000000000..51a9831cf7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.cpp @@ -0,0 +1,716 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +HRESULT +SetElementMetadata( + IAppHostElement * pElement, + CONST WCHAR * szMetaType, + CONST VARIANT * pVarValue + ) +{ + HRESULT hr = NOERROR; + + BSTR bstrMetaType = SysAllocString( szMetaType ); + if( !bstrMetaType ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pElement->SetMetadata( bstrMetaType, + *pVarValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrMetaType ); + + return hr; +} + +HRESULT +ProcessAttributes( + IAppHostElement * pElement, + IXmlReader * pReader + ) +{ + HRESULT hr = NOERROR; + + VARIANT varPropValue; + VariantInit( &varPropValue ); + + CONST WCHAR * pszName; + CONST WCHAR * pszValue; + + for( hr = pReader->MoveToFirstAttribute(); + ; + hr = pReader->MoveToNextAttribute() ) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pReader->GetLocalName( &pszName, NULL ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pReader->GetValue( &pszValue, NULL ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varPropValue, pszValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty( pElement, pszName, &varPropValue ); + + if( HRESULT_FROM_WIN32( ERROR_INVALID_INDEX ) == hr ) + { + // + // Possibly this is a metadata attribute not a property + // + + hr = SetElementMetadata( pElement, pszName, &varPropValue ); + } + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + VariantClear( &varPropValue ); + } + +exit: + + VariantClear( &varPropValue ); + + return hr; +} + +HRESULT +ProcessSection( + IAppHostWritableAdminManager * pAdminMgr, + CONST WCHAR * szSectionName, + IXmlReader * pReader, + IAppHostElement * pParent, + BOOL fClearSection + ) +{ + HRESULT hr = NOERROR; + + CComPtr pChildElement; + CComPtr pParentElement = pParent; + + CONST WCHAR * pwszLocalName; + + BSTR bstrName = NULL; + BSTR bstrSectionName = NULL; + BSTR bstrRoot = NULL; + BSTR bstrAddElementName = NULL; + + BOOL isEmpty = FALSE; + + bstrSectionName = SysAllocString( szSectionName ); + bstrRoot = SysAllocString( L"MACHINE/WEBROOT/APPHOST" ); + + if( !bstrSectionName || !bstrRoot ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + XmlNodeType nodeType; + + for (;;) + { + hr = pReader->Read(&nodeType); + + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + if (FAILED(hr)) + { + break; + } + + if( nodeType == XmlNodeType_Element ) + { + hr = pReader->GetLocalName( &pwszLocalName, NULL ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + SysFreeString( bstrName ); + bstrName = NULL; + + bstrName = SysAllocString( pwszLocalName ); + if( !bstrName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + isEmpty = pReader->IsEmptyElement(); + + if( !pParent ) + { + // + // This is the entry point to resetting the section. Begin by + // clearing. + // + + hr = pAdminMgr->GetAdminSection( bstrSectionName, + bstrRoot, + &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if (fClearSection) + { + hr = pChildElement->Clear(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // Need to commit change after clear + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // Need to reload after commit + + pChildElement.Release(); + + hr = pAdminMgr->GetAdminSection( bstrSectionName, + bstrRoot, + &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + } + else + { + // Test the parent of this node for a collection + + CComPtr pCollection; + hr = pParentElement->get_Collection( &pCollection ); + + if ( SUCCEEDED ( hr ) && ( pCollection != NULL ) ) + { + // Get the schema for the collection + CComPtr pCollectionSchema; + hr = pCollection->get_Schema( &pCollectionSchema ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + SysFreeString( bstrAddElementName ); + bstrAddElementName = NULL; + + // Parent element has a collection. Get the addElement token. + pCollectionSchema->get_AddElementNames(&bstrAddElementName); + + if( 0 == wcscmp( pwszLocalName, bstrAddElementName ) ) + { + hr = pCollection->CreateNewElement( bstrName, &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = ProcessAttributes( pChildElement, pReader ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pCollection->AddElement( pChildElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pCollection.Release(); + } + else + { + // Parent has collection, but this isn't an 'addElement' + hr = pParentElement->GetElementByName( bstrName, + &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Failed to get child element %S, %08x\n", bstrName, hr )); + goto exit; + } + } + + pCollectionSchema.Release(); + } + else + { + // Parent is not a collection. + hr = pParentElement->GetElementByName( bstrName, + &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Failed to get child element %S, %08x\n", bstrName, hr )); + goto exit; + } + } + } + + hr = ProcessAttributes( pChildElement, pReader ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( !isEmpty ) + { + hr = ProcessSection( pAdminMgr, + szSectionName, + pReader, + pChildElement, + fClearSection); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + pChildElement.Release(); + } + else if( nodeType == XmlNodeType_EndElement ) + { + break; + } + } + +exit: + + SysFreeString( bstrAddElementName ); + SysFreeString( bstrName ); + SysFreeString( bstrSectionName ); + SysFreeString( bstrRoot ); + + return hr; +} + +HRESULT +ResetConfigSection( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN OUT IStream * pStreamDefaults + ) +{ + HRESULT hr = NOERROR; + + CComPtr pReader; + + + hr = CreateXmlReader(__uuidof(IXmlReader), (void**) &pReader, NULL); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error creating xml reader, error is %08.8lx", hr)); + goto exit; + } + + hr = pReader->SetProperty( XmlReaderProperty_DtdProcessing, + DtdProcessing_Prohibit ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error setting XmlReaderProperty_DtdProcessing, %08x", hr)); + goto exit; + } + + hr = pReader->SetInput( pStreamDefaults ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error setting input for reader, %08x", hr)); + goto exit; + } + + hr = ProcessSection( pAdminMgr, + szSectionName, + pReader, + NULL, + TRUE); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +CreateStreamFromTextResource( + IN HINSTANCE hInstance, + IN CONST WCHAR * szResourceName, + OUT IStream ** ppStream + ) +{ + HRESULT hr = NOERROR; + + HRSRC hResDefaults = NULL; + HGLOBAL hGlobDefaults = NULL; + LPCVOID pDefaults = NULL; + DWORD cbDefaults; + HGLOBAL hDefaultsData = NULL; + LPVOID pDefaultsData = NULL; + + hResDefaults = FindResourceW( g_hinst, + szResourceName, + L"TEXT" ); + if( !hResDefaults ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + hGlobDefaults = LoadResource( hInstance, hResDefaults ); + if( !hGlobDefaults ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + pDefaults = LockResource( hGlobDefaults ); + if( !pDefaults ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + cbDefaults = SizeofResource( g_hinst, hResDefaults ); + if( !cbDefaults ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + hDefaultsData = GlobalAlloc( GMEM_MOVEABLE, cbDefaults ); + if( !hDefaultsData ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + pDefaultsData = GlobalLock( hDefaultsData ); + if( !pDefaultsData ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + #pragma prefast( suppress:26010, "cbDefaults is allocated size for pDefaultsData" ) + CopyMemory( pDefaultsData, pDefaults, cbDefaults ); + + GlobalUnlock( hDefaultsData ); + + hr = CreateStreamOnHGlobal( hDefaultsData, TRUE, ppStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hDefaultsData = NULL; + +exit: + + if( hDefaultsData ) + { + GlobalFree( hDefaultsData ); + } + + return hr; +} + + +HRESULT +ResetConfigSectionFromResource( + IN CONST WCHAR * szResourceName, + IN CONST WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pStream; + + hr = CreateStreamFromTextResource( g_hinst, + szResourceName, + &pStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = ResetConfigSection( pAdminMgr, + szSectionName, + pStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Save + // + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return ( hr ); +} + +HRESULT +ResetConfigSectionFromFile( + IN CONST WCHAR * szFileName, + IN CONST WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pStream; + + hr = SHCreateStreamOnFileEx( szFileName, + STGM_READ, + FILE_ATTRIBUTE_NORMAL, + FALSE, + NULL, + &pStream); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = ResetConfigSection( pAdminMgr, + szSectionName, + pStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Save + // + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return ( hr ); +} + +HRESULT +AppendConfigSectionFromFile( + IN CONST WCHAR * szFileName, + IN CONST WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pStream; + + hr = SHCreateStreamOnFileEx( szFileName, + STGM_READ, + FILE_ATTRIBUTE_NORMAL, + FALSE, + NULL, + &pStream); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = AppendConfigSection( pAdminMgr, + szSectionName, + pStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Save + // + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return ( hr ); +} + + +HRESULT +AppendConfigSection( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN OUT IStream * pStreamDefaults + ) +{ + HRESULT hr = NOERROR; + + CComPtr pReader; + + + hr = CreateXmlReader(__uuidof(IXmlReader), (void**) &pReader, NULL); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error creating xml reader, error is %08.8lx", hr)); + goto exit; + } + + hr = pReader->SetProperty( XmlReaderProperty_DtdProcessing, + DtdProcessing_Prohibit ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error setting XmlReaderProperty_DtdProcessing, %08x", hr)); + goto exit; + } + + hr = pReader->SetInput( pStreamDefaults ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error setting input for reader, %08x", hr)); + goto exit; + } + + hr = ProcessSection( pAdminMgr, + szSectionName, + pReader, + NULL, + FALSE); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.h new file mode 100644 index 0000000000..491938dfc9 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.h @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _DEFAULTS_H_ +#define _DEFAULTS_H_ + + +// +// Helper routines for setting-up default module config. +// + +HRESULT +CreateStreamFromTextResource( + IN HINSTANCE hInstance, + IN CONST WCHAR * szResourceName, + OUT IStream ** ppStream + ); + +HRESULT +ResetConfigSection( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN OUT IStream * pStreamDefaults + ); + +HRESULT +ResetConfigSectionFromResource( + IN CONST WCHAR * szResourceName, + IN CONST WCHAR * szSectionName + ); + +HRESULT +ResetConfigSectionFromFile( + IN CONST WCHAR * szFileName, + IN CONST WCHAR * szSectionName + ); + +HRESULT +AppendConfigSectionFromFile( + IN CONST WCHAR * szFileName, + IN CONST WCHAR * szSectionName + ); + +HRESULT +AppendConfigSection( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN OUT IStream * pStreamDefaults + ); + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.cpp new file mode 100644 index 0000000000..bc9abda798 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.cpp @@ -0,0 +1,346 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +UINT +WINAPI +ScheduleMakeShortcutElevatedCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strShortcut, 128 ); + STACK_STRU( strDirectoryId, 256 ); // Directory Identifier + STACK_STRU( strDirectoryName, 256 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strShortcutName, 256 ); + STACK_STRU( strData, 256); + + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISElevatedShortcut`.`Shortcut_`, " + L"`Shortcut`.`Component_`, " + L"`Shortcut`.`Name`, " + L"`Directory`.`Directory` " + L"FROM `IISElevatedShortcut`, `Shortcut`, `Directory` " + L"WHERE `IISElevatedShortcut`.`Shortcut_`=`Shortcut`.`Shortcut` " + L"AND `Shortcut`.`Directory_`=`Directory`.`Directory`"; + + + CA_DATA_WRITER cadata; + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + BOOL scheduleDefferedCA = FALSE; + + enum { + CA_ELEVATESC_SHORTCUT = 1, + CA_ELEVATESC_COMPONENT, + CA_ELEVATESC_SHORTCUTNAME, + CA_ELEVATESC_DIRECTORY, + }; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting MSI database, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening View, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error executing view, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_ELEVATESC_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_ELEVATESC_COMPONENT, hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting state for component %s, hr=0x%x", strComponent.QueryStr(), hr); + goto exit; + } + + // Only run if the comonent is installing or reinstalling + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + // GET: directory where shortcut is + // Get the directory id for the shortcut + hr = MsiUtilRecordGetString( hRecord, + CA_ELEVATESC_DIRECTORY, + &strDirectoryId ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_ELEVATESC_DIRECTORY, hr); + goto exit; + } + + // Get directory path + hr = MsiUtilGetProperty(hInstall, strDirectoryId.QueryStr(), &strDirectoryName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting value for directory record %s, hr=0x%x", strDirectoryId.QueryStr(), hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Shortcut Directory: '%s'.", + strDirectoryName.QueryStr()); + // ENDGET: directory where shortcut is + + + // GET: Short and Long names of shortcuts + hr = MsiUtilRecordGetString( hRecord, + CA_ELEVATESC_SHORTCUTNAME, + &strShortcutName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_ELEVATESC_SHORTCUTNAME, hr); + goto exit; + } + + // strShortcutName contains the short and long file names of the shortcut + + PCWSTR pszPrevious = strShortcutName.QueryStr(); + // Append the shortcut name to the directory and write to cadata + // Write the short and long shortcut paths + for ( DWORD i = 0; i < strShortcutName.QueryCCH() + 1; i++ ) + { + if ( strShortcutName.QueryStr()[ i ] == L'|' || + strShortcutName.QueryStr()[ i ] == L'\0' ) + { + strShortcutName.QueryStr()[ i ] = L'\0'; + + strData.Copy( strDirectoryName ); + strData.Append(L"\\"); + strData.Append(pszPrevious); + strData.Append(L".lnk"); + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Potential shortcut path: %s", + strData.QueryStr()); + + hr = cadata.Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + + pszPrevious = strShortcutName.QueryStr() + i + 1; + + // Only schedule custom action if needed + scheduleDefferedCA = TRUE; + } + } + + // ENDGET: Short and Long names of shortcuts + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + if ( scheduleDefferedCA ) + { + hr = MsiUtilScheduleDeferredAction( hInstall, + L"ExecuteMakeShortcutElevated", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action ExecuteMakeShortcutElevated scheduled"); + } + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogClose(); + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} + +UINT +WINAPI +ExecuteMakeShortcutElevatedCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + + BOOL fCoInit = FALSE; + + WCHAR * szShortcutFile = NULL; + + CA_DATA_READER cadata; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + // + // Retrieve parameters from ca data + // + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error retrieving custom action data, hr=0x%x", hr); + goto exit; + } + + if ( SUCCEEDED( hr = CoInitialize(NULL) ) ) + { + fCoInit = TRUE; + } + + while ( SUCCEEDED(hr = cadata.Read( &szShortcutFile )) ) + { + if(GetFileAttributes(szShortcutFile) != 0xFFFFFFFF) + { + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Shortcut %s exists", szShortcutFile); + + // Get shell + CComPtr sppf; + + if (FAILED(hr = sppf.CoCreateInstance(L"lnkfile")) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error get ShellLink com object, hr=0x%x", hr); + goto exit; + } + + // Load shortcut file + if (FAILED(hr = sppf->Load(szShortcutFile, STGM_READWRITE))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error loading shortcut file %s, hr=0x%x", szShortcutFile, hr); + goto exit; + } + + CComQIPtr spdl(sppf); + if (!spdl) + { + DBGERROR_HR(hr); + goto exit; + } + + DWORD dwFlags; + if (FAILED(hr = spdl->GetFlags(&dwFlags))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting shortcut flags, hr=0x%x", hr); + goto exit; + } + + // Add "run as ..." flag + dwFlags |= SLDF_RUNAS_USER; + if (FAILED(hr = spdl->SetFlags(dwFlags))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error setting SLDF_RUNAS_USER flag, hr=0x%x", hr); + goto exit; + } + + // Save file. + if (FAILED(hr = sppf->Save(NULL, TRUE))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error saving changes to shortcut, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Successfully added SLDF_RUNAS_USER flag to shortcut %s", + szShortcutFile); + + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogClose(); + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.h new file mode 100644 index 0000000000..c5f5428510 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +UINT +WINAPI +ScheduleMakeShortcutElevatedCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +ExecuteMakeShortcutElevatedCA( + IN MSIHANDLE hInstall + ); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.cpp new file mode 100644 index 0000000000..1e824ae72e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.cpp @@ -0,0 +1,472 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +// +// Local function declarations +// + +// +// Public functions +// + +HRESULT +RegisterHandler( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN ULONG Index, + IN CONST WCHAR * szName, + IN CONST WCHAR * szPath, + IN CONST WCHAR * szVerbs, + IN OPTIONAL CONST WCHAR * szType, + IN OPTIONAL CONST WCHAR * szModules, + IN OPTIONAL CONST WCHAR * szScriptProcessor, + IN OPTIONAL CONST WCHAR * szResourceType, + IN OPTIONAL CONST WCHAR * szRequiredAccess, + IN OPTIONAL CONST WCHAR * szPreCondition + ) +{ + HRESULT hr; + CComPtr pHandlersCollection; + CComPtr pNewElement; + UINT numDeleted; + BSTR bstrAdd; + + bstrAdd = SysAllocString(L"add"); + + if (bstrAdd == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = GetHandlersCollection( + pAdminMgr, + szConfigPath, + &pHandlersCollection + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Just in case... delete if it's already there. + // + + hr = DeleteAllElementsFromCollection( + pHandlersCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + &numDeleted + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if (Index == HANDLER_INDEX_BEFORE_STATICFILE) + { + // + // If the StaticFile handler is installed (and it probably is) + // then install just before it. + // + + hr = FindHandlerByName( + pAdminMgr, + szConfigPath, + HANDLER_STATICFILE_NAME, + &Index + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (hr == S_FALSE) + { + // + // Not found. Install at end of list. + // + + Index = HANDLER_INDEX_LAST; + } + } + + // + // If the caller wants this to be the last handler, then + // chase down the current entry count. + // + + if (Index == HANDLER_INDEX_LAST) + { + hr = pHandlersCollection->get_Count(&Index); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = pHandlersCollection->CreateNewElement(bstrAdd, &pNewElement); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Required properties. + // + + hr = SetElementStringProperty( + pNewElement, + L"name", + szName + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementStringProperty( + pNewElement, + L"path", + szPath + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementStringProperty( + pNewElement, + L"verb", + szVerbs + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Optional properties. + // + + if (szType != NULL && szType[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"type", + szType + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szModules != NULL && szModules[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"modules", + szModules + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szScriptProcessor != NULL && szScriptProcessor[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"scriptProcessor", + szScriptProcessor + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szResourceType != NULL && szResourceType[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"resourceType", + szResourceType + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szRequiredAccess != NULL && szRequiredAccess[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"requireAccess", + szRequiredAccess + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szPreCondition != NULL && szPreCondition[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"preCondition", + szPreCondition + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = pHandlersCollection->AddElement(pNewElement, Index); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString(bstrAdd); + return hr; +} + +HRESULT +UnRegisterHandler( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szName + ) +{ + HRESULT hr; + CComPtr pHandlersCollection; + CComPtr pLocationCollection; + CComPtr pLocation; + CComPtr pElement; + ENUM_INDEX locationIndex; + BOOL found; + UINT numDeleted; + + // + // Enum the tags, look for any sections, + // and if found, remove the specified handler from each. + // + + hr = GetLocationCollection( + pAdminMgr, + szConfigPath, + &pLocationCollection + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + for (hr = FindFirstLocation(pLocationCollection, &locationIndex, &pLocation) ; + SUCCEEDED(hr) ; + hr = FindNextLocation(pLocationCollection, &locationIndex, &pLocation)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = GetSectionFromLocation( + pLocation, + L"system.webServer/handlers", + &pElement, + &found + ); + + if (SUCCEEDED(hr)) + { + if (found) + { + hr = pElement->get_Collection(&pHandlersCollection); + + if (SUCCEEDED(hr)) + { + hr = DeleteAllElementsFromCollection( + pHandlersCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + &numDeleted + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + } + + pHandlersCollection.Release(); + } + else + { + DBGERROR_HR(hr); + } + + pElement.Release(); + } + } + else + { + DBGERROR_HR(hr); + } + + pLocation.Release(); + } + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +FindHandlerByName( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szName, + OUT ULONG * pIndex + ) +{ + HRESULT hr; + CComPtr pHandlersCollection; + + *pIndex = 0; + + hr = GetHandlersCollection( + pAdminMgr, + szConfigPath, + &pHandlersCollection + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = FindElementInCollection( + pHandlersCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + pIndex + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +GetHandlersCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostElementCollection ** pHandlersCollection + ) +{ + HRESULT hr; + CComPtr pHandlersElement; + BSTR bstrConfigPath; + BSTR bstrHandlersSectionName; + + bstrConfigPath = SysAllocString(szConfigPath); + bstrHandlersSectionName = SysAllocString(L"system.webServer/handlers"); + *pHandlersCollection = NULL; + + if (bstrConfigPath == NULL || bstrHandlersSectionName == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + // + // Chase down the handlers collection. + // + + hr = pAdminMgr->GetAdminSection( bstrHandlersSectionName, + bstrConfigPath, + &pHandlersElement ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pHandlersElement->get_Collection(pHandlersCollection); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString(bstrHandlersSectionName); + SysFreeString(bstrConfigPath); + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.h new file mode 100644 index 0000000000..3024acf8fd --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.h @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _HANDLERS_H_ +#define _HANDLERS_H_ + + +#define HANDLER_INDEX_FIRST 0 +#define HANDLER_INDEX_LAST ((ULONG)(-1L)) +#define HANDLER_INDEX_BEFORE_STATICFILE ((ULONG)(-2L)) + +#define HANDLER_STATICFILE_NAME L"StaticFile" + +HRESULT +RegisterHandler( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN ULONG Index, + IN CONST WCHAR * szName, + IN CONST WCHAR * szPath, + IN CONST WCHAR * szVerbs, + IN OPTIONAL CONST WCHAR * szType, + IN OPTIONAL CONST WCHAR * szModules, + IN OPTIONAL CONST WCHAR * szScriptProcessor, + IN OPTIONAL CONST WCHAR * szResourceType, + IN OPTIONAL CONST WCHAR * szRequiredAccess, + IN OPTIONAL CONST WCHAR * szPreCondition = NULL + ); + +HRESULT +UnRegisterHandler( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szName + ); + +HRESULT +FindHandlerByName( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szName, + OUT ULONG * pIndex + ); + +HRESULT +GetHandlersCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostElementCollection ** pHandlersCollection + ); + + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/hotfix.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/hotfix.cpp new file mode 100644 index 0000000000..a800948b13 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/hotfix.cpp @@ -0,0 +1,766 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" +#include "wuerror.h" + +#define REBOOT_REQUIRED_REGKEY L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce" +#define REBOOT_REGVALUE L"IIS Extensions Reboot Required" + +HRESULT ExecuteCommandLine( + IN PCWSTR szCommandLine, + IN DWORD dwTimeout, + __out LPDWORD pExitCode + + ) +{ + HRESULT hr = NOERROR; + UINT status = 0; + PROCESS_INFORMATION oProcInfo = {0}; + STARTUPINFOW oStartInfo = {0}; + DWORD dwExitCode = ERROR_SUCCESS; + STACK_STRU( strModifiableCommandLine, MAX_PATH); + + oStartInfo.cb = sizeof ( STARTUPINFOW ); + oProcInfo.hThread = INVALID_HANDLE_VALUE; + oProcInfo.hProcess = INVALID_HANDLE_VALUE; + + _ASSERTE ( szCommandLine ); + _ASSERTE ( pExitCode ); + + hr = strModifiableCommandLine.Copy ( szCommandLine ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error copying command line, hr=0x%x", hr); + goto exit; + } + + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Launching process with command line %s", strModifiableCommandLine.QueryStr()); + + status = CreateProcessW(NULL, + strModifiableCommandLine.QueryStr(), // command line + NULL, // security info + NULL, // thread info + TRUE, // inherit handles + GetPriorityClass(GetCurrentProcess()), // creation flags + NULL, // environment + NULL, // cur dir + &oStartInfo, + &oProcInfo); + + if ( 0 == status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error creating process, hr=0x%x", hr); + goto exit; + } + + status = WaitForSingleObject( oProcInfo.hProcess, dwTimeout ); + if ( status == WAIT_FAILED ) + { + IISLogWrite(SETUP_LOG_SEVERITY_WARNING, L"Process wait failed, hr=0x%x", HRESULT_FROM_WIN32 ( GetLastError() ) ); + // but we can still continue + } + + status = GetExitCodeProcess ( oProcInfo.hProcess, &dwExitCode ); + if ( 0 == status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting exit code for process, hr=0x%x", hr); + goto exit; + } + + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Process returned with exit code %d", dwExitCode); + *pExitCode = dwExitCode; + +exit: + if ( INVALID_HANDLE_VALUE != oProcInfo.hThread ) + { + CloseHandle ( oProcInfo.hThread ); + oProcInfo.hThread = INVALID_HANDLE_VALUE; + } + + if ( INVALID_HANDLE_VALUE != oProcInfo.hProcess ) + { + CloseHandle ( oProcInfo.hProcess ); + oProcInfo.hProcess = INVALID_HANDLE_VALUE; + } + + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + return hr; +} + + +HRESULT +InstallWindowsHotfixQuietly( + IN PCWSTR szHotFixPath, + __out BOOL * pbRebootRequired +) +{ + HRESULT hr = NOERROR; + UINT status = 0; + STACK_STRU( strCommandLine, MAX_PATH); + DWORD cch = 0; + DWORD exitCode = 0; + + _ASSERTE(szHotFixPath); + _ASSERTE(pbRebootRequired); + + *pbRebootRequired = FALSE; + cch = strCommandLine.QuerySizeCCH(); + + status = GetSystemDirectoryW(strCommandLine.QueryStr(), cch); + if ( status > cch) + { + cch = status; + hr = strCommandLine.Resize( ++cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error resizing buffer, hr=0x%x", hr); + goto exit; + } + + status = GetSystemDirectoryW(strCommandLine.QueryStr(), cch); + } + + if ( 0 == status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting system folder path, hr=0x%x", hr); + goto exit; + } + + strCommandLine.SyncWithBuffer(); + + hr = strCommandLine.Append(L"\\wusa.exe /quiet /norestart \""); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error apppending wusa, hr=0x%x", hr); + goto exit; + } + + hr = strCommandLine.Append(szHotFixPath); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error apppending hotfixpath, hr=0x%x", hr); + goto exit; + } + + hr = strCommandLine.Append(L"\""); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error apppending end quote, hr=0x%x", hr); + goto exit; + } + + hr = ExecuteCommandLine ( strCommandLine.QueryStr(), INFINITE, &exitCode); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error running the hotfix installer, hr=0x%x", hr); + goto exit; + } + + // + // handle return codes based on WinSE team info regarding WUSA.exe + // + switch ( exitCode ) + { + case ERROR_SUCCESS: + // install succeeded, continue. + hr = S_OK; + break; + case ERROR_SUCCESS_REBOOT_INITIATED: + case ERROR_SUCCESS_REBOOT_REQUIRED: + case WU_S_REBOOT_REQUIRED: + *pbRebootRequired = TRUE; + hr = S_OK; + break; + case WU_S_ALREADY_INSTALLED: + // WUSA.exe can return the above codes if this DWORD registry value is set: + // HKLM\Software\Microsoft\Windows\CurrentVersion\WUSA\ExtendedReturnCode + hr = S_OK; + break; + case S_FALSE: + // WUSA.exe returns this when the MSU is already installed, or when its not applicable, continue. + hr = S_OK; + break; + + // + // need cases to handle new WU_S_ALREADY_INSTALLED and WU_E_NOT_APPLICABLE error codes + // + + default: + // the installation failed, abort + hr = HRESULT_FROM_WIN32 ( ERROR_INSTALL_FAILURE ); + goto exit; + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + return hr; +} +UINT +__stdcall +ExecuteCleanUpWindowsHotfixCA( + IN MSIHANDLE hInstall +) +{ + HRESULT hr = NOERROR; + UINT status = 0; + CA_DATA_READER cadata; + WCHAR * szHotFixName = NULL; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error retrieving custom action data, hr=0x%x", hr); + goto exit; + } + + while ( SUCCEEDED(hr = cadata.Read( &szHotFixName )) ) + { + status = 0; + status = DeleteFileW( szHotFixName ); + + if( FAILED(status) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error deleting hotfix temp file '%s', hr=0x%x", szHotFixName, hr); + //eat this error and try and delete other temp files + hr = NOERROR; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Success deleting hotfix temp file '%s'", szHotFixName ); + } + } + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + IISLogClose(); + //do not fail commit or rollback transaction for this + return ERROR_SUCCESS; +} + +UINT +__stdcall +ScheduleInstallWindowsHotfixCA( + IN MSIHANDLE hInstall +) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + OSVERSIONINFOEXW osVersionInfo = {0}; + + PMSIHANDLE hDatabase; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + BOOL bDeferredRequired = FALSE; + + CA_DATA_WRITER cadata; + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISWindowsHotfix`.`Name`, " + L"`IISWindowsHotfix`.`OSMajorVersion`, " + L"`IISWindowsHotfix`.`OSMinorVersion`, " + L"`IISWindowsHotfix`.`SPMajorVersion`, " + L"`IISWindowsHotfix`.`Condition`, " + L"`Binary`.`Data` " + L"FROM `IISWindowsHotfix`, `Binary` " + L"WHERE `IISWindowsHotfix`.`BinaryName_`=`Binary`.`Name`"; + + enum { CA_HOTFIX_NAME = 1, + CA_HOTFIX_OSMAJORVERSION, + CA_HOTFIX_OSMINORVERSION, + CA_HOTFIX_SPMAJORVERSION, + CA_HOTFIX_CONDITION, + CA_HOTFIX_BINARYDATA + }; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + osVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEXW ); +#pragma warning( push ) +#pragma warning( disable : 4996) + status = GetVersionEx( (LPOSVERSIONINFOW) &osVersionInfo ); +#pragma warning( pop ) + + if ( !status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting Windows version, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting MSI database, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening View, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error executing view, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + UINT dwTargetOSMajorVersion = 0; + UINT dwTargetOSMinorVersion = 0; + UINT dwTargetSPMajorVersion = 0; + STACK_STRU( strHotFixName, 128 ); + BOOL isApplicable = TRUE; // Applicable by default + + hr = MsiUtilRecordGetString( hRecord, + CA_HOTFIX_NAME, + &strHotFixName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_HOTFIX_NAME, hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Checking applicability of Hotfix '%s'.", + strHotFixName.QueryStr()); + + hr = MsiUtilRecordGetInteger( hRecord, + CA_HOTFIX_OSMAJORVERSION, + &dwTargetOSMajorVersion); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No OS Major Version available.", CA_HOTFIX_OSMAJORVERSION, hr); + // This column may be NULL + hr = S_FALSE; + } + + hr = MsiUtilRecordGetInteger( hRecord, + CA_HOTFIX_OSMINORVERSION, + &dwTargetOSMinorVersion); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No OS Minor Version available."); + // This column may be NULL + hr = S_FALSE; + } + + hr = MsiUtilRecordGetInteger( hRecord, + CA_HOTFIX_SPMAJORVERSION, + &dwTargetSPMajorVersion); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No OS SP Major Version available."); + // This column may be NULL + hr = S_FALSE; + } + + if ( hr == S_FALSE ) + { + // No OS Version information available + hr = S_OK; + } + else + { + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"OS Version: Actual '%d.%d'. Hotfix Target '%d.%d'.", + osVersionInfo.dwMajorVersion, + osVersionInfo.dwMinorVersion, + dwTargetOSMajorVersion, + dwTargetOSMinorVersion); + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"OS Service Pack Level: Actual '%d'. Hotfix Target '%d'.", + osVersionInfo.wServicePackMajor, + dwTargetSPMajorVersion); + + if ( osVersionInfo.dwMajorVersion != dwTargetOSMajorVersion || + osVersionInfo.dwMinorVersion != dwTargetOSMinorVersion) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"OS Version Mismatch! Will not apply the hotfix."); + isApplicable = FALSE; + } + else if(osVersionInfo.wServicePackMajor != dwTargetSPMajorVersion) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"OS SP Level Mismatch! Will not apply the hotfix."); + isApplicable = FALSE; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"OS Versions match! Will try to apply the hotfix."); + isApplicable = TRUE; + } + } + + if ( isApplicable ) + { + STACK_STRU( strCondition, 128 ); + MSICONDITION Condition; + + hr = MsiUtilRecordGetString( hRecord, + CA_HOTFIX_CONDITION, + &strCondition ); + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Error gettting column %d from record, hr=0x%x", + CA_HOTFIX_CONDITION, + hr); + goto exit; + } + + Condition = MsiEvaluateCondition( hInstall, strCondition.QueryStr() ); + + switch( Condition ) + { + case MSICONDITION_ERROR: + hr = E_UNEXPECTED; + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Cannot evaluate hotfix install condition \"%s\", hr=0x%x", + strCondition.QueryStr(), + hr ); + goto exit; + + case MSICONDITION_FALSE: + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Condition evaluation returned false! Will not apply the hotfix."); + isApplicable = FALSE; + break; + + case MSICONDITION_TRUE: + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Condition evaluation returned true! Will try to apply the hotfix."); + isApplicable = TRUE; + break; + + case MSICONDITION_NONE: + + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No condition available to evaluate."); + + break; + } + } + + if ( isApplicable ) + { + //apply the hotfix + STACK_STRU( hotFixFilePath, MAX_PATH * 2 ); + + hr = GenerateTempFileName ( strHotFixName.QueryStr(), + L"msu", + &hotFixFilePath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error generating temp file name for the hotfix, hr=0x%x", hr); + goto exit; + } + + hr = MsiUtilRecordReadStreamIntoFile ( hRecord, + CA_HOTFIX_BINARYDATA, + hotFixFilePath.QueryStr()); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error streaming binary data into file, hr=0x%x", hr); + goto exit; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Streamed hotfix '%s' into file '%s'.", strHotFixName.QueryStr(), hotFixFilePath.QueryStr()); + } + + bDeferredRequired = TRUE; + hr = cadata.Write( hotFixFilePath.QueryStr(), hotFixFilePath.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + if( bDeferredRequired ) + { + //schedule CA to install the msu files + hr = MsiUtilScheduleDeferredAction( hInstall, + L"ExecuteInstallWindowsHotfix", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action ExecuteInstallWindowsHotfix, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action ExecuteInstallWindowsHotfix scheduled"); + + + //schedule CA to delete the msu files if rollback transaction initiated + hr = MsiUtilScheduleDeferredAction( hInstall, + L"RollbackCleanUpWindowsHotfix", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action RollbackCleanUpWindowsHotfix, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action RollbackCleanUpWindowsHotfix scheduled"); + + //schedule CA to delete the msu files if commit transaction initiated + hr = MsiUtilScheduleDeferredAction( hInstall, + L"CommitCleanUpWindowsHotfix", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action CommitCleanUpWindowsHotfix, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action CommitCleanUpWindowsHotfix scheduled"); + + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + IISLogClose(); + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + + +UINT +__stdcall +ExecuteInstallWindowsHotfixCA( + IN MSIHANDLE hInstall +) +{ + HRESULT hr = NOERROR; + CA_DATA_READER cadata; + WCHAR * szHotFixName = NULL; + BOOL rebootRequired = FALSE; + HKEY regKey = NULL; + LONG status = ERROR_SUCCESS; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error retrieving custom action data, hr=0x%x", hr); + goto exit; + } + + while ( SUCCEEDED(hr = cadata.Read( &szHotFixName )) ) + { + BOOL requiresReboot = FALSE; + hr = InstallWindowsHotfixQuietly ( szHotFixName , &requiresReboot ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error installing hotfix '%s', hr=0x%x", szHotFixName, hr); + goto exit; + } + if ( requiresReboot ) + { + rebootRequired = TRUE; + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + if ( rebootRequired ) + { + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + REBOOT_REQUIRED_REGKEY, + 0, + KEY_SET_VALUE, + ®Key); + if(status != ERROR_SUCCESS) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening the reboot registry key, hr=0x%x", hr); + goto exit; + } + + status = RegSetValueEx(regKey, + REBOOT_REGVALUE, + 0, + REG_SZ, + (PBYTE)L"", + 4); + if(status != ERROR_SUCCESS) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error creating the reboot registry value, hr=0x%x", hr); + goto exit; + } + + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Created a registry key to signal reboot is required"); + } + +exit: + if(regKey != NULL) + { + RegCloseKey(regKey); + regKey = NULL; + } + + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + IISLogClose(); + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + +UINT +__stdcall +ScheduleRebootIfRequiredCA( + IN MSIHANDLE hInstall +) +{ + HRESULT hr = NOERROR; + HKEY regKey = NULL; + LONG status = ERROR_SUCCESS; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + REBOOT_REQUIRED_REGKEY, + 0, + KEY_QUERY_VALUE, + ®Key); + if(status != ERROR_SUCCESS) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening the reboot registry key, hr=0x%x", hr); + goto exit; + } + + status = RegQueryValueEx(regKey, + REBOOT_REGVALUE, + 0, + NULL, + NULL, + NULL); + switch(status) + { + case ERROR_SUCCESS: + status = MsiSetMode(hInstall, + MSIRUNMODE_REBOOTATEND, + TRUE); + if( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error setting reboot required for the installation, hr=0x%x", hr); + goto exit; + } + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Signalled the installer to reboot at the end of the installation."); + break; + + case ERROR_FILE_NOT_FOUND: + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No reboot is required by the IIS custom actions."); + hr = S_OK; + break; + + default: + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting the IIS registry key reboot value, hr=0x%x", hr); + goto exit; + } + +exit: + if(regKey != NULL) + { + RegCloseKey(regKey); + regKey = NULL; + } + + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + IISLogClose(); + + //dont report an error here. the install has completed so its too late to report a failure + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; + +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.cpp new file mode 100644 index 0000000000..c3b5d059ba --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.cpp @@ -0,0 +1,518 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +HRESULT GetSidStringForAccount( + const WCHAR * szAccount, + __inout STRU * pstr + ) +{ + HRESULT hr = NOERROR; + BOOL success = TRUE; + DWORD sidSize = 0; + DWORD domainSize = 0; + PSID psid = NULL; + SID_NAME_USE sidKind; + LPWSTR pszSid = NULL; + LPWSTR pszDomain = NULL; + + LookupAccountNameW(NULL, + szAccount, + NULL, + &sidSize, + NULL, + &domainSize, + &sidKind); + + _ASSERT ( sidSize > 0 ); + + psid = new BYTE[sidSize]; + if( psid == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + DBGERROR_HR(hr); + goto exit; + } + + pszDomain = new WCHAR[domainSize]; + if( pszDomain == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + DBGERROR_HR(hr); + goto exit; + } + + success = LookupAccountNameW(NULL, + szAccount, + psid, + &sidSize, + pszDomain, + &domainSize, + &sidKind); + if( !success ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + success = ConvertSidToStringSidW( psid, &pszSid ); + if( !success ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + _ASSERT(pszSid); + + hr = pstr->Copy(pszSid); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + if (pszSid) + { + LocalFree( pszSid ); + pszSid = NULL; + } + + delete [] psid; + psid = NULL; + delete [] pszDomain; + pszDomain = NULL; + + return hr; +} + +UINT +WINAPI +ScheduleHttpListenerCA( + IN MSIHANDLE hInstall, + IN const WCHAR * pszCAName, + IIS_HTTP_LISTENER_CA_TYPE caType + ) +{ + HRESULT hr = S_OK; + UINT status = ERROR_SUCCESS; + BOOL scheduleDefferedCA = FALSE; + + PMSIHANDLE hDatabase; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISHttpListener`.`Name`, " + L"`IISHttpListener`.`Component_`, " + L"`IISHttpListener`.`Account`, " + L"`IISHttpListener`.`Prefix` " + L"FROM `IISHttpListener`"; + + enum { CA_HTTP_NAME = 1, + CA_HTTP_COMPONENT, + CA_HTTP_ACCOUNT, + CA_HTTP_PREFIX}; + + CA_DATA_WRITER cadata; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + STACK_STRU( strName, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strAccount, 128 ); + STACK_STRU( strPrefix, 128 ); + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + BOOL scheduleThisComponent = FALSE; + + hr = MsiUtilRecordGetString( hRecord, + CA_HTTP_NAME, + &strName ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_HTTP_COMPONENT, + &strComponent ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if (MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + if (caType == IIS_HTTP_LISTENER_CA_INSTALL) + { + scheduleThisComponent = TRUE; + scheduleDefferedCA = TRUE; + } + } + else if (MsiUtilIsUnInstalling( installStateCurrent, installStateAction)) + { + if (caType == IIS_HTTP_LISTENER_CA_UNINSTALL) + { + scheduleThisComponent = TRUE; + scheduleDefferedCA = TRUE; + } + + } + + if (scheduleThisComponent) + { + hr = MsiUtilRecordGetString( hRecord, + CA_HTTP_ACCOUNT, + &strAccount ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_HTTP_PREFIX, + &strPrefix ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Write( strName.QueryStr(), strName.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilFormatString( hInstall, &strAccount); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Write( strAccount.QueryStr(), strAccount.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilFormatString( hInstall, &strPrefix); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Write( strPrefix.QueryStr(), strPrefix.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + } + + if ( scheduleDefferedCA ) + { + hr = MsiUtilScheduleDeferredAction( hInstall, + pszCAName, + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + +UINT +__stdcall +ExecuteHttpListenerCA( + IN MSIHANDLE hInstall, + IIS_HTTP_LISTENER_CA_TYPE caType + ) +{ + HRESULT hr = NOERROR; + ULONG status = NO_ERROR; + BOOL bHttpInitialized = FALSE; + CA_DATA_READER cadata; + WCHAR * szName = NULL; + WCHAR * szAccount = NULL; + WCHAR * szPrefix = NULL; + HTTPAPI_VERSION httpVersion1 = HTTPAPI_VERSION_1; + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + status = HttpInitialize( httpVersion1, HTTP_INITIALIZE_CONFIG, NULL ); + if ( status != NO_ERROR ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling HttpInitialize, hr=0x%x", hr); + goto exit; + } + bHttpInitialized = TRUE; + + while ( SUCCEEDED(hr = cadata.Read( &szName)) ) + { + const WCHAR * securityDescriptorFormat = L"D:(A;;GX;;;%s)"; + HTTP_SERVICE_CONFIG_URLACL_SET inputConfigInfo; + STACK_STRU( strSid, 128 ); + STACK_STRU( strSecurityString, 128 ); + + hr = cadata.Read( &szAccount); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &szPrefix); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetSidStringForAccount(szAccount, &strSid); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = strSecurityString.SafeSnwprintf(securityDescriptorFormat, strSid.QueryStr()); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + inputConfigInfo.KeyDesc.pUrlPrefix = szPrefix; + inputConfigInfo.ParamDesc.pStringSecurityDescriptor = strSecurityString.QueryStr(); + + status = HttpDeleteServiceConfiguration(NULL, + HttpServiceConfigUrlAclInfo, + &inputConfigInfo, + sizeof(inputConfigInfo), + NULL); + + if (status == E_INVALIDARG) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling Http API. Please make sure that the URL and Account information specified is correct."); + } + + if ( (status != NO_ERROR) && (status != ERROR_FILE_NOT_FOUND) ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling HttpDeleteServiceConfiguration for account '%s', prefix '%s', securityDescriptor '%s', hr=0x%x", + szAccount, + szPrefix, + strSecurityString.QueryStr(), + hr); + goto exit; + } + + if ( caType == IIS_HTTP_LISTENER_CA_INSTALL) + { + status = HttpSetServiceConfiguration(NULL, + HttpServiceConfigUrlAclInfo, + &inputConfigInfo, + sizeof(inputConfigInfo), + NULL); + if (status == E_INVALIDARG) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling Http API. Please make sure that the URL and Account information specified is correct."); + } + if ( status != NO_ERROR ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling HttpSetServiceConfiguration for account '%s', prefix '%s', securityDescriptor '%s', hr=0x%x", + szAccount, + szPrefix, + strSecurityString.QueryStr(), + hr); + goto exit; + } + } + } + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + if (bHttpInitialized) + { + HttpTerminate ( HTTP_INITIALIZE_CONFIG , NULL); + } + + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + + //for(inputConfigInfo.dwToken = 0; /* condition inside */ ; inputConfigInfo.dwToken++) + //{ + // HTTP_SERVICE_CONFIG_URLACL_SET * pOutputConfigInfo = NULL; + // ULONG outputConfigInfoSize = 0; + + // while (status == ERROR_INSUFFICIENT_BUFFER) + // { + // delete pOutputConfigInfo; + // pOutputConfigInfo = NULL; + // pOutputConfigInfo = new BYTE[outputConfigInfoSize]; + // if (pOutputConfigInfo == NULL) + // { + // hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + // DBGERROR_HR(hr); + // goto exit; + // } + + // status = HttpQueryServiceConfiguration ( NULL, + // HttpServiceConfigUrlAclInfo, + // &inputConfigInfo, + // sizeof(inputConfigInfo), + // pOutputConfigInfo, + // outputConfigInfoSize, + // &outputConfigInfoSize, + // NULL); + // } //end while + + // _ASSERT (status != ERROR_INSUFFICIENT_BUFFER) + // + // if (status == NO_ERROR) + // { + // //lookup output info + + // } + // else if (status == ERROR_NO_MORE_ITEMS) + // { + // //we're done + // break; + // } + // else + // { + // hr = HRESULT_FROM_WIN32( status ); + // DBGERROR_HR(hr); + // IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling HttpQueryServiceConfiguration, hr=0x%x", hr); + // goto exit; + // } + //} //end for + +UINT +WINAPI +ScheduleInstallHttpListenerCA( + IN MSIHANDLE hInstall + ) +{ + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + UINT retVal = ScheduleHttpListenerCA(hInstall, L"ExecuteInstallHttpListener", IIS_HTTP_LISTENER_CA_INSTALL); + IISLogClose(); + return retVal; +} + +UINT +WINAPI +ScheduleUnInstallHttpListenerCA( + IN MSIHANDLE hInstall + ) +{ + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + UINT retVal = ScheduleHttpListenerCA(hInstall, L"ExecuteUnInstallHttpListener", IIS_HTTP_LISTENER_CA_UNINSTALL); + IISLogClose(); + return retVal; +} +UINT +__stdcall +ExecuteInstallHttpListenerCA( + IN MSIHANDLE hInstall + ) +{ + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + UINT retVal = ExecuteHttpListenerCA(hInstall, IIS_HTTP_LISTENER_CA_INSTALL); + IISLogClose(); + return retVal; +} + +UINT +__stdcall +ExecuteUnInstallHttpListenerCA( + IN MSIHANDLE hInstall + ) +{ + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + UINT retVal = ExecuteHttpListenerCA(hInstall, IIS_HTTP_LISTENER_CA_UNINSTALL); + IISLogClose(); + return retVal; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.h new file mode 100644 index 0000000000..1783e4ddf8 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.h @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + + +enum IIS_HTTP_LISTENER_CA_TYPE +{ + IIS_HTTP_LISTENER_CA_INSTALL, + IIS_HTTP_LISTENER_CA_UNINSTALL +}; + +HRESULT GetSidStringForAccount( + const WCHAR * szAccount, + __inout STRU * pstr + ); + +UINT +WINAPI +ScheduleHttpListenerCA( + IN MSIHANDLE hInstall, + IN const WCHAR * pszCAName, + IIS_HTTP_LISTENER_CA_TYPE caType + ); + +UINT +__stdcall +ExecuteHttpListenerCA( + IN MSIHANDLE hInstall, + IIS_HTTP_LISTENER_CA_TYPE caType + ); + +UINT +WINAPI +ScheduleInstallHttpListenerCA( + IN MSIHANDLE hInstall + ); + +UINT +__stdcall +ExecuteInstallHttpListenerCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +ScheduleUnInstallHttpListenerCA( + IN MSIHANDLE hInstall + ); + +UINT +__stdcall +ExecuteUnInstallHttpListenerCA( + IN MSIHANDLE hInstall + ); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.cpp new file mode 100644 index 0000000000..06631ce964 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.cpp @@ -0,0 +1,4302 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +#define ROOT_CONFIG_PATH L"MACHINE/WEBROOT/APPHOST" + +#define MAX_NAME 256 +#define _UNITEXT(quote) L##quote +#define UNITEXT(quote) _UNITEXT(quote) + +HRESULT +GetFullTypeFromAssemblyTable( + IN MSIHANDLE hDatabase, + IN CONST WCHAR * szComponent, + IN CONST WCHAR * szTypeName, + IN OUT STRU * pstrFullType + ); + +BOOL IsSectionInAdminConfig( + IN CONST WCHAR * szIsInAdminConfig + ) +{ + if( 0 == _wcsicmp(szIsInAdminConfig, L"yes") ) + { + return TRUE; + } + else + { + return FALSE; + } +} + +HRESULT +ScheduleInstallModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + // + // If the module being installed includes the optional TypeName, + // then the we'll test the component to insure that the module + // is a .Net module. If so, then we will not install the module + // in and we'll include the TypeName and strong + // name info when we install in the . + // + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strTemp, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strTypeName, 128 ); + STACK_STRU( strFullType, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISGlobalModule`.`Name`, " + L"`IISGlobalModule`.`File_`, " + L"`IISGlobalModule`.`PreCondition`, " + L"`File`.`Component_`, " + L"`IISGlobalModule`.`TypeName` " + L"FROM `IISGlobalModule`, `File` " + L"WHERE `File`.`File`=`IISGlobalModule`.`File_`"; + + enum { CA_MODULE_NAME = 1, + CA_MODULE_IMAGE, + CA_MODULE_PRECONDITION, + CA_MODULE_COMPONENT, + CA_MODULE_TYPENAME }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + // does table exists + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISGlobalModule"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_MODULE ); + + // Get the module name + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // CA_MODULE_IMAGE is the name of the File element, need to + // resolve it to the full path by formatting it as [#ModuleDll] + // + + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_IMAGE, + &strTemp ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = strData.SafeSnwprintf( L"[#%s]", strTemp.QueryStr() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilFormatString( hInstall, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_PRECONDITION, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Get the type name (optional) + // If the type name is present, then this is a .Net and does not have + // to be registered in the + // + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_TYPENAME, + &strTypeName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( strTypeName.QueryCCH() > 0 ) + { + // TypeName is present. Get the assembly info + hr = GetFullTypeFromAssemblyTable( hDatabase, + strComponent.QueryStr(), + strTypeName.QueryStr(), + &strFullType ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + else + { + strFullType.Reset(); + } + + hr = cadata->Write( strFullType.QueryStr(), strFullType.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ScheduleUnInstallModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISGlobalModule`.`Name`, " + L"`File`.`Component_`, " + L"`IISGlobalModule`.`TypeName` " + L"FROM `IISGlobalModule`, `File` " + L"WHERE `File`.`File`=`IISGlobalModule`.`File_`"; + + enum { CA_MODULE_NAME = 1, + CA_MODULE_COMPONENT, + CA_MODULE_TYPENAME }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISGlobalModule"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_UNINSTALL_MODULE ); + + + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_TYPENAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteInstallModuleCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szName = NULL; + WCHAR * szImage = NULL; + WCHAR * szPreCondition = NULL; + WCHAR * szType = NULL; + + + hr = cadata->Read( &szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szImage ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Install the module + // + + hr = InstallModule( szName, + szImage, + szPreCondition, + szType ); + + if ( hr == HRESULT_FROM_WIN32( ERROR_ALREADY_EXISTS ) ) + { + // + // We'll quietly accept a module already exists. + // This will happen if a component has multiple features + // that each have a module. + // If a feature is omitted on the initial install, + // and added later using Change, the features that + // were initially installed will show up in the + // ScheduleInstallModuleCA with install + // INSTALLSTATE_UNKNOWN, which will trigger a reinstall. + // Reinstall will result in ERROR_ALREADY_EXISTS. + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, + L"Module: '%s' already installed.", + szName); + + hr = S_OK; + } + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteUnInstallModuleCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szName = NULL; + WCHAR * szType = NULL; + + + + hr = cadata->Read( &szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = UnInstallModule( szName, szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ScheduleRegisterSectionSchemaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISConfigSections`.`Name`, " + L"`IISConfigSections`.`File_`, " + L"`IISConfigSections`.`OverrideModeDefault`, " + L"`IISConfigSections`.`AllowDefinition`, " + L"`IISConfigSections`.`Type`, " + L"`IISConfigSections`.`InAdminConfig`, " + L"`File`.`Component_` " + L"FROM `IISConfigSections`, `File` " + L"WHERE `File`.`File`=`IISConfigSections`.`File_`"; + + enum + { + CA_SECTION_NAME = 1, + CA_SCHEMA_FILE, + CA_SECTION_OVERRIDEMODE, + CA_SECTION_ALLOWDEF, + CA_SECTION_TYPE, + CA_SECTION_INADMINCONFIG, + CA_SCHEMA_COMPONENT + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exists + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISConfigSections"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_SCHEMA_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_SECTIONSCHEMA ); + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_OVERRIDEMODE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_ALLOWDEF, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_TYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_INADMINCONFIG, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ScheduleUnRegisterSectionSchemaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISConfigSections`.`Name`, " + L"`IISConfigSections`.`InAdminConfig`, " + L"`File`.`Component_` " + L"FROM `IISConfigSections`, `File` " + L"WHERE `File`.`File`=`IISConfigSections`.`File_`"; + + enum { + CA_SECTION_NAME = 1, + CA_SECTION_INADMINCONFIG, + CA_SCHEMA_COMPONENT }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exists + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISConfigSections"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_SCHEMA_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + cadata->Write( IIS_UNINSTALL_SECTIONSCHEMA ); + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_INADMINCONFIG, + &strData ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteRegisterSectionSchemaCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szSectionName = NULL; + WCHAR * szOverrideMode = NULL; + WCHAR * szAllowDefinition = NULL; + WCHAR * szType = NULL; + WCHAR * szIsInAdminConfig = NULL; + + + // + // Retrieve parameters from ca data + // + hr = cadata->Read( &szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szOverrideMode ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szAllowDefinition ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szIsInAdminConfig ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Register the section + // + + hr = RegisterSectionSchema( IsSectionInAdminConfig(szIsInAdminConfig), + szSectionName, + szOverrideMode, + szAllowDefinition, + szType ); + + if ( hr == HRESULT_FROM_WIN32( ERROR_ALREADY_EXISTS ) ) + { + // + // We'll quietly accept a section name already exists. + // This will happen if a package has multiple features + // that each have a section. + // If a feature is omitted on the initial install, + // and added later using Change, the features that + // were initially installed will show up in the + // ScheduleRegisterSectionSchemaCA with install + // INSTALLSTATE_UNKNOWN, which will trigger a reinstall. + // Reinstall will result in ERROR_ALREADY_EXISTS. + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, + L"Section name: '%s' already exists.", + szSectionName); + + hr = S_OK; + } + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ExecuteUnRegisterSectionSchemaCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szSectionName = NULL; + WCHAR * szIsInAdminConfig = NULL; + + + hr = cadata->Read( &szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szIsInAdminConfig ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = UnRegisterSectionSchema( IsSectionInAdminConfig(szIsInAdminConfig), + szSectionName ); + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to unregister section schema for section: '%s', hr=0x%x .", + szSectionName, + hr ); + DBGERROR_HR(hr); + + // + // We need to keep going because this is an uninstall action + // and should be resilient to missing elements. + // + hr = S_OK; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + +HRESULT +CanonicalizeAssemblyVersion( + STRU & strValue +) +{ + // + // Converts 7.1.2.000 to 7.1.2.0 + // + + HRESULT hr = S_OK; + LPCWSTR psz = wcschr( strValue.QueryStr(), L'.' ); + DWORD dwDotCount = 0; + + // + // Find the 3rd '.' + // + while ( psz != NULL ) + { + dwDotCount++; + LPCWSTR psz2 = wcschr( psz + 1, L'.' ); + if ( psz2 == NULL ) + { + break; + } + psz = psz2; + } + + if ( dwDotCount == 3 && psz != NULL ) + { + // + // Convert "000" to integer and then back to string. + // + + psz ++; + DWORD dw = _wtoi( psz ); + STACK_STRU( strTemp, 16 ); + + hr = strTemp.SafeSnwprintf( L"%u", dw ); + if ( SUCCEEDED( hr ) ) + { + ptrdiff_t diff = psz - strValue.QueryStr(); + + _ASSERTE( diff >= 0 ); + + hr = strValue.SetLen( (DWORD) diff ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = strValue.Append(strTemp); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + +HRESULT +GetFullTypeFromAssemblyTable( + IN MSIHANDLE hDatabase, + IN CONST WCHAR * szComponent, + IN CONST WCHAR * szTypeName, + IN OUT STRU * pstrFullType + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + BOOL fRecordFound = FALSE; + BOOL fVersion = FALSE; + + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strQuery, 128 ); + STACK_STRU( strPropName, 64 ); + STACK_STRU( strPropValueName, 64 ); + STACK_STRU( strPropVersion, 64 ); + STACK_STRU( strPropCulture, 64 ); + STACK_STRU( strPropKeyToken, 64 ); + + CONST WCHAR * szQueryTemplate = + L"SELECT `Name`, `Value` " + L"FROM `MsiAssemblyName` " + L"WHERE `Component_`='%s'"; + + CONST WCHAR * szFullTypeTempl = L"%s, %s, Version=%s, Culture=%s, PublicKeyToken=%s"; + // szTypeName, name, version, culture, publicKeyToken + + enum { CA_ASSEMBLY_PROP_NAME = 1, CA_ASSEMBLY_PROP_VALUE }; + + hr = strQuery.SafeSnwprintf( szQueryTemplate, szComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, strQuery.QueryStr(), &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + STRU * pstr; + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + fRecordFound = TRUE; + hr = MsiUtilRecordGetString( hRecord, + CA_ASSEMBLY_PROP_NAME, + &strPropName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pstr = NULL; + + if ( 0 == wcscmp( strPropName.QueryStr(), L"name" ) ) + { + pstr = &strPropValueName; + } + else if ( 0 == wcscmp( strPropName.QueryStr(), L"version" ) ) + { + fVersion = TRUE; + pstr = &strPropVersion; + } + else if ( 0 == wcscmp( strPropName.QueryStr(), L"culture" ) ) + { + pstr = &strPropCulture; + } + else if ( 0 == wcscmp( strPropName.QueryStr(), L"publicKeyToken" ) ) + { + pstr = &strPropKeyToken; + } + + if ( pstr ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_ASSEMBLY_PROP_VALUE, + pstr ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( fVersion ) + { + hr = CanonicalizeAssemblyVersion( *pstr ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + fVersion = FALSE; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + hr = pstrFullType->SafeSnwprintf( szFullTypeTempl, + szTypeName, + strPropValueName.QueryStr(), + strPropVersion.QueryStr(), + strPropCulture.QueryStr(), + strPropKeyToken.QueryStr() + ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + _ASSERTE( fRecordFound ); + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ScheduleRegisterUIModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strComponent, 128 ); + STACK_STRU( strAssemblyInfoComponent, 128 ); + STACK_STRU( strData, 128 ); + STACK_STRU( strFullType, 128 ); + + const STRU * pstrComponentName = NULL; + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISUIModule`.`Name`, " + L"`IISUIModule`.`TypeName`, " + L"`IISUIModule`.`Component_` ," + L"`IISUIModule`.`AssemblyInfoComponent_` ," + L"`IISUIModule`.`RegisterInModulesSection` ," + L"`IISUIModule`.`PrependToList` " + L"FROM `IISUIModule` "; + + enum { + CA_UIMODULE_NAME = 1, + CA_UIMODULE_TYPE, + CA_UIMODULE_COMPONENT, + CA_UIMODULE_ASSEMBLYINFOCOMPONENT, + CA_UIMODULE_REGISTER, + CA_UIMODULE_PREPEND + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISUIModule"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_UIMODULE ); + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_ASSEMBLYINFOCOMPONENT, + &strAssemblyInfoComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // use the AssemblyInfoComponent_ to get the module assembly information + // fall back to using the component if the value is null. + if ( strAssemblyInfoComponent.QueryCCH() > 0 ) + { + pstrComponentName = &strAssemblyInfoComponent; + } + else + { + pstrComponentName = &strComponent; + } + _ASSERTE( pstrComponentName != NULL ); + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_TYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetFullTypeFromAssemblyTable( hDatabase, + pstrComponentName->QueryStr(), + strData.QueryStr(), + &strFullType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strFullType.QueryStr(), strFullType.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_REGISTER, + &strData ); + if (FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_PREPEND, + &strData ); + if (FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ScheduleUnRegisterUIModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strComponent, 128 ); + STACK_STRU( strAssemblyInfoComponent, 128 ); + STACK_STRU( strData, 128 ); + STACK_STRU( strFullType, 128 ); + + const STRU * pstrComponentName = NULL; + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISUIModule`.`Name`, " + L"`IISUIModule`.`TypeName`, " + L"`IISUIModule`.`Component_` ," + L"`IISUIModule`.`AssemblyInfoComponent_` " + L"FROM `IISUIModule` "; + + enum { + CA_UIMODULE_NAME = 1, + CA_UIMODULE_TYPE, + CA_UIMODULE_COMPONENT, + CA_UIMODULE_ASSEMBLYINFOCOMPONENT, + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISUIModule"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_UNINSTALL_UIMODULE ); + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_ASSEMBLYINFOCOMPONENT, + &strAssemblyInfoComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // use the AssemblyInfoComponent_ to get the module assembly information + // fall back to using the component if the value is null. + if ( strAssemblyInfoComponent.QueryCCH() > 0 ) + { + pstrComponentName = &strAssemblyInfoComponent; + } + else + { + pstrComponentName = &strComponent; + } + _ASSERTE( pstrComponentName != NULL ); + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_TYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetFullTypeFromAssemblyTable( hDatabase, + pstrComponentName->QueryStr(), + strData.QueryStr(), + &strFullType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strFullType.QueryStr(), strFullType.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ExecuteRegisterUIModuleCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szUIModuleName = NULL; + WCHAR * szUIModuleTypeInfo = NULL; + WCHAR * szUIModuleRegister = NULL; + WCHAR * szUIModulePrepend = NULL; + + hr = cadata->Read( &szUIModuleName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szUIModuleTypeInfo ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szUIModuleRegister ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szUIModulePrepend ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Register the section + // + + hr = RegisterUIModule( szUIModuleName, + szUIModuleTypeInfo, + szUIModuleRegister, + szUIModulePrepend ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteUnRegisterUIModuleCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szUIModuleName = NULL; + WCHAR * szUIModuleTypeInfo = NULL; + + hr = cadata->Read( &szUIModuleName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szUIModuleTypeInfo ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = UnRegisterUIModule( szUIModuleName, szUIModuleTypeInfo ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + +HRESULT +ScheduleRegisterTraceAreaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISTraceArea`.`Component_`, " + L"`IISTraceArea`.`ProviderName`, " + L"`IISTraceArea`.`ProviderGuid`, " + L"`IISTraceArea`.`AreaName`, " + L"`IISTraceArea`.`AreaValue` " + L"FROM `IISTraceArea` "; + + enum { CA_COMPONENT = 1, + CA_PROVIDER_NAME, + CA_PROVIDER_GUID, + CA_AREA_NAME, + CA_AREA_VALUE }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISTraceArea"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + cadata->Write( IIS_INSTALL_TRACEAREA ); + + // Get the values + for ( DWORD Index = CA_PROVIDER_NAME; Index <= CA_AREA_VALUE; Index++ ) + { + hr = MsiUtilRecordGetString( hRecord, + Index, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteRegisterTraceAreaCA( + IN CA_DATA_READER * cadata +) +{ + HRESULT hr = NOERROR; + + WCHAR * szTraceProviderName = NULL; + WCHAR * szTraceProviderGuid = NULL; + WCHAR * szAreaName = NULL; + WCHAR * szAreaValue = NULL; + + + hr = cadata->Read( &szTraceProviderName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szTraceProviderGuid ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szAreaName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szAreaValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Register the section + // + hr = RegisterTraceArea( szTraceProviderName, + szTraceProviderGuid, + szAreaName, + szAreaValue ); + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to register trace area (Provider: '%s'; " + L"Guid: '%s'; AreaName: '%s'; AreaValue: '%s') hr=0x%x", + szTraceProviderName, + szTraceProviderGuid, + szAreaName, + szAreaValue, + hr ); + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} + +/// The error messages are from setstrings.wxl. +/// The integer parameter is used to to get the string. +UINT +LogMsiCustomActionError( + IN MSIHANDLE hInstall, + UINT messageId + ) +{ + PMSIHANDLE pLogger = MsiCreateRecord(1); + if ( pLogger == NULL ) + { + return ERROR_INSTALL_FAILURE; + } + + MsiRecordSetInteger( pLogger, 1, messageId ); + MsiProcessMessage( hInstall, INSTALLMESSAGE_ERROR, pLogger ); + + if ( pLogger != NULL ) + { + MsiCloseHandle( pLogger ); + pLogger = NULL; + } + + return ERROR_INSTALL_FAILURE; +} + + +HRESULT +ScheduleRegisterMofFileCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISTraceArea`.`BinaryName_`, " + L"`Binary`.`Data`, " + L"`IISTraceArea`.`Component_` " + L"FROM `IISTraceArea`, `Binary` " + L"WHERE `Binary`.`Name`=`IISTraceArea`.`BinaryName_`"; + + enum { CA_BINARY_NAME = 1, + CA_FILE_DATA, + CA_MOF_COMPONENT }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISTraceArea"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_MOF_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_MOFFILE ); + + STACK_STRU( strBinaryName, 128 ); + STACK_STRU( strMofFilePath, MAX_PATH ); + + hr = MsiUtilRecordGetString( hRecord, + CA_BINARY_NAME, + &strBinaryName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GenerateTempFileName( strBinaryName.QueryStr(), + L"mof", + &strMofFilePath); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordReadStreamIntoFile( hRecord, + CA_FILE_DATA, + strMofFilePath.QueryStr()); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strMofFilePath.QueryStr(), strMofFilePath.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + } + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + +HRESULT +ExecuteRegisterMofFileCA( + IN CA_DATA_READER * cadata +) +{ + HRESULT hr = NOERROR; + + WCHAR * szMofFileName = NULL; + + hr = cadata->Read( &szMofFileName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Register the section + // + hr = RegisterMofFile( szMofFileName ); + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to register MOF file (File name: '%s') hr=0x%x", + szMofFileName, + hr ); + DBGERROR_HR(hr); + + // + // Continue setup, this is not a fatal error. + // + hr = S_OK; + + goto exit; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, + L"MOF file '%s' registered.", + szMofFileName ); + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + +HRESULT +ScheduleInstallHandlerCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISGlobalHandler`.`Name`, " + L"`IISGlobalHandler`.`Component_`, " + L"`IISGlobalHandler`.`Path`, " + L"`IISGlobalHandler`.`Verb`, " + L"`IISGlobalHandler`.`Type`, " + L"`IISGlobalHandler`.`Index`, " + L"`IISGlobalHandler`.`Modules`, " + L"`IISGlobalHandler`.`ScriptProcessor`, " + L"`IISGlobalHandler`.`ResourceType`, " + L"`IISGlobalHandler`.`RequiredAccess`, " + L"`IISGlobalHandler`.`PreCondition` " + L"FROM `IISGlobalHandler` "; + + enum { CA_HANDLER_NAME = 1, + CA_HANDLER_COMPONENT, + CA_HANDLER_PATH, + CA_HANDLER_VERB, + CA_HANDLER_TYPE, + CA_HANDLER_INDEX, + CA_HANDLER_MODULES, + CA_HANDLER_SCRIPTPROCESSOR, + CA_HANDLER_RESOURCETYPE, + CA_HANDLER_REQUIREDACCESS, + CA_HANDLER_PRECONDITION + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISGlobalHandler"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_HANDLER ); + + // Get the Handler name + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Get handler Path + // + + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_PATH, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + //Get handler Verb + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_VERB, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler Type + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_TYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler Index + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_INDEX, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler Modules + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_MODULES, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler Script Processor + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_SCRIPTPROCESSOR, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler ResourceType + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_RESOURCETYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler RequiredAccess + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_REQUIREDACCESS, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler PreCondition + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_PRECONDITION, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ScheduleUnInstallHandlerCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISGlobalHandler`.`Name`, " + L"`IISGlobalHandler`.`Component_` " + L"FROM `IISGlobalHandler` "; + + enum { CA_HANDLER_NAME = 1, + CA_HANDLER_COMPONENT + }; + + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISGlobalHandler"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_UNINSTALL_HANDLER ); + + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ExecuteInstallHandlerCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szName = NULL; + WCHAR * szPath = NULL; + WCHAR * szVerb = NULL; + WCHAR * szType = NULL; + WCHAR * szIndex = NULL; + WCHAR * szModules = NULL; + WCHAR * szScriptProcessor = NULL; + WCHAR * szResourceType = NULL; + WCHAR * szRequiredAccess = NULL; + WCHAR * szPreCondition = NULL; + + ULONG ulIndex = HANDLER_INDEX_FIRST; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + hr = cadata->Read( &szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szPath ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szVerb ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szIndex ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if( 0 == _wcsicmp( szIndex, L"FIRST" ) ) + { + ulIndex = HANDLER_INDEX_FIRST; + } + else if ( 0 == _wcsicmp( szIndex, L"LAST" ) ) + { + ulIndex = HANDLER_INDEX_FIRST; + } + else if ( 0 == _wcsicmp( szIndex, L"BEFORE_STATICFILE" ) ) + { + ulIndex = HANDLER_INDEX_BEFORE_STATICFILE; + } + + hr = cadata->Read( &szModules ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szScriptProcessor ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szResourceType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szRequiredAccess ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Install the Handler + // + hr = RegisterHandler( pAdminMgr, + ROOT_CONFIG_PATH, + ulIndex, + szName, + szPath, + szVerb, + szType, + szModules, + szScriptProcessor, + szResourceType, + szRequiredAccess, + szPreCondition + ); + + if ( hr == HRESULT_FROM_WIN32( ERROR_ALREADY_EXISTS ) ) + { + // + // We'll quietly accept a handler already exists. + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, + L"Handler: '%s' already installed.", + szName); + + hr = S_OK; + } + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ExecuteUnInstallHandlerCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szName = NULL; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + hr = cadata->Read( &szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = UnRegisterHandler( pAdminMgr, ROOT_CONFIG_PATH, szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + +HRESULT +ScheduleInstallSectionDefaultsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strName, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISConfigSectionDefaults`.`Name`, " + L"`IISConfigSectionDefaults`.`SectionName`, " + L"`IISConfigSectionDefaults`.`Component_`, " + L"`Binary`.`Data` " + L"FROM `IISConfigSectionDefaults`, `Binary` " + L"WHERE `IISConfigSectionDefaults`.`BinaryName_`=`Binary`.`Name`"; + + + enum { CA_DEFAULTS_NAME = 1, + CA_DEFAULTS_SECTIONNAME, + CA_DEFAULTS_COMPONENT, + CA_DEFAULTS_BINARYDATA + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISConfigSectionDefaults"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_DEFAULTS_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_DEFAULTS ); + + // Get the record name + hr = MsiUtilRecordGetString( hRecord, + CA_DEFAULTS_NAME, + &strName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the Section name + hr = MsiUtilRecordGetString( hRecord, + CA_DEFAULTS_SECTIONNAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Get File from binary, write to temp file + // + STACK_STRU( strFilePath, MAX_PATH * 2 ); + + hr = GenerateTempFileName ( strName.QueryStr(), + L"def", + &strFilePath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error generating temp file name for the hotfix, hr=0x%x", hr); + goto exit; + } + + hr = MsiUtilRecordReadStreamIntoFile ( hRecord, + CA_DEFAULTS_BINARYDATA, + strFilePath.QueryStr()); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error streaming binary data into file, hr=0x%x", hr); + goto exit; + } + + hr = cadata->Write( strFilePath.QueryStr(), strFilePath.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; + +} +HRESULT +ExecuteInstallSectionDefaultsCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szSectionName = NULL; + WCHAR * szTempFileName = NULL; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + hr = cadata->Read( &szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szTempFileName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Set Section Defaults from temp file created during schedule + // + hr = ResetConfigSectionFromFile( szTempFileName, szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // delete temp file. No error checking. + // + ::DeleteFileW( szTempFileName ); + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; + +} + +HRESULT +ScheduleInstallSectionAdditionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strName, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISConfigSectionAdditions`.`Name`, " + L"`IISConfigSectionAdditions`.`SectionName`, " + L"`IISConfigSectionAdditions`.`Component_`, " + L"`Binary`.`Data` " + L"FROM `IISConfigSectionAdditions`, `Binary` " + L"WHERE `IISConfigSectionAdditions`.`BinaryName_`=`Binary`.`Name`"; + + + enum { CA_SECTION_ADDITION_NAME = 1, + CA_SECTION_ADDITION_SECTIONNAME, + CA_SECTION_ADDITION_COMPONENT, + CA_SECTION_ADDITION_BINARYDATA + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + // + // Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISConfigSectionAdditions"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_ADDITION_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_SECTION_ADDITIONS); + + // Get the record name + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_ADDITION_NAME, + &strName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the Section name + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_ADDITION_SECTIONNAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Get File from binary, write to temp file + // + STACK_STRU( strFilePath, MAX_PATH * 2 ); + + hr = GenerateTempFileName ( strName.QueryStr(), + L"def", + &strFilePath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error generating temp file name for the hotfix, hr=0x%x", hr); + goto exit; + } + + hr = MsiUtilRecordReadStreamIntoFile ( hRecord, + CA_SECTION_ADDITION_BINARYDATA, + strFilePath.QueryStr()); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error streaming binary data into file, hr=0x%x", hr); + goto exit; + } + + hr = cadata->Write( strFilePath.QueryStr(), strFilePath.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; + +} +HRESULT +ExecuteInstallSectionAdditionsCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szSectionName = NULL; + WCHAR * szTempFileName = NULL; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + hr = cadata->Read( &szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szTempFileName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Set Section Defaults from temp file created during schedule + // + hr = AppendConfigSectionFromFile( szTempFileName, szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // delete temp file. No error checking. + // + ::DeleteFileW( szTempFileName ); + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; + +} + +HRESULT +ScheduleInstallCgiRestrictionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strName, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISCgiRestriction`.`Name`, " + L"`IISCgiRestriction`.`Component_`, " + L"`IISCgiRestriction`.`Path`, " + L"`IISCgiRestriction`.`Allowed`, " + L"`IISCgiRestriction`.`GroupId`, " + L"`IISCgiRestriction`.`Description` " + L"FROM `IISCgiRestriction` "; + + enum { CA_CGI_NAME = 1, + CA_CGI_COMPONENT, + CA_CGI_PATH, + CA_CGI_ALLOWED, + CA_CGI_GROUPID, + CA_CGI_DESC + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISCgiRestriction"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + cadata->Write( IIS_INSTALL_CGIRESTRICTIONS ); + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + // Get the Path + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_PATH, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the Allowed + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_ALLOWED, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the GroupId + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_GROUPID, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the Description + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_DESC, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; + +} + +HRESULT +ScheduleUnInstallCgiRestrictionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strName, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISCgiRestriction`.`Name`, " + L"`IISCgiRestriction`.`Component_`, " + L"`IISCgiRestriction`.`Path`, " + L"FROM `IISCgiRestriction` "; + + enum { CA_CGI_NAME = 1, + CA_CGI_COMPONENT, + CA_CGI_PATH, + CA_CGI_ALLOWED, + CA_CGI_GROUPID, + CA_CGI_DESC + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISCgiRestriction"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + + cadata->Write( IIS_UNINSTALL_CGIRESTRICTIONS ); + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + + // Get the Path + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_PATH, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; + +} + + +HRESULT +ExecuteInstallCgiRestrictionsCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szPath = NULL; + WCHAR * szAllowed = NULL; + WCHAR * szGroupId = NULL; + WCHAR * szDescription = NULL; + BOOL fAllowed = FALSE; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + while ( SUCCEEDED(hr = cadata->Read( &szPath )) ) + { + + hr = cadata->Read( &szAllowed ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szGroupId ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szDescription ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( 0 == wcscmp( szAllowed, L"true" ) ) + { + fAllowed = TRUE; + } + else if ( 0 == wcscmp( szAllowed, L"false" ) ) + { + fAllowed = FALSE; + } + + hr = RegisterCgiRestriction( + pAdminMgr, + ROOT_CONFIG_PATH, + szPath, + fAllowed, + szGroupId, + szDescription + ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; + +} + + +HRESULT +ExecuteUnInstallCgiRestrictionsCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szPath = NULL; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + while ( SUCCEEDED(hr = cadata->Read( &szPath )) ) + { + hr = UnRegisterCgiRestriction( + pAdminMgr, + ROOT_CONFIG_PATH, + szPath, + FALSE + ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + hr = S_OK; + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.h new file mode 100644 index 0000000000..40f7097845 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.h @@ -0,0 +1,255 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#define _UNITEXT(quote) L##quote +#define UNITEXT(quote) _UNITEXT(quote) + + +// IIS Custom action Types +enum IIS_COSTOM_ACTION_TYPE +{ + IIS_INSTALL_MODULE = 1, + IIS_UNINSTALL_MODULE, + IIS_INSTALL_UIMODULE, + IIS_UNINSTALL_UIMODULE, + IIS_INSTALL_HANDLER, + IIS_UNINSTALL_HANDLER, + IIS_INSTALL_SECTIONSCHEMA, + IIS_UNINSTALL_SECTIONSCHEMA, + IIS_INSTALL_TRACEAREA, + IIS_INSTALL_MOFFILE, + IIS_INSTALL_DEFAULTS, + IIS_INSTALL_SECTION_ADDITIONS, + IIS_INSTALL_CGIRESTRICTIONS, + IIS_UNINSTALL_CGIRESTRICTIONS, + IIS_INSTALL_, + IIS_UNINSTALL_, + IIS_END +}; + + +HRESULT +InstallModule( + IN CONST WCHAR * szName, + IN CONST WCHAR * szImage, + IN OPTIONAL CONST WCHAR * szPreCondition, + IN OPTIONAL CONST WCHAR * szTYpe + ); + + +HRESULT +UnInstallModule( + IN CONST WCHAR * szName, + IN OPTIONAL CONST WCHAR * szPreCondition + ); + +HRESULT +RegisterSectionSchema( + IN CONST BOOL isSectionInAdminSchema, + IN CONST WCHAR * szSectionName, + IN CONST WCHAR * szOverideModeDefault, + IN OPTIONAL CONST WCHAR * szAllowDefinition, + IN OPTIONAL CONST WCHAR * szType + ); + +HRESULT +UnRegisterSectionSchema( + IN CONST BOOL isSectionInAdminSchema, + IN CONST WCHAR * szSectionName + ); + +HRESULT +RegisterUIModule( + IN CONST WCHAR * szModuleName, + IN CONST WCHAR * szModuleTypeInfo, + IN OPTIONAL CONST WCHAR * szRegisterInModulesSection, + IN OPTIONAL CONST WCHAR * szPrependToList + ); + +HRESULT +UnRegisterUIModule( + IN CONST WCHAR * szModuleName, + IN CONST WCHAR * szModuleTypeInfo + ); + +UINT +WINAPI +CheckForAdminSIDCA( + MSIHANDLE hInstall + ); + +UINT +LogMsiCustomActionError( + IN MSIHANDLE hInstall, + UINT messageId + ); + +HRESULT +InitAdminMgrForAdminConfig( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szCommitPath +); + +HRESULT +RegisterMofFile( + IN PWSTR pszFileName +); + +HRESULT +ScheduleInstallModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ScheduleUnInstallModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteInstallModuleCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ExecuteUnInstallModuleCA( + IN CA_DATA_READER * cadata +); + + +HRESULT +ExecuteUnRegisterUIModuleCA( + IN CA_DATA_READER * cadata +); + + +HRESULT +ScheduleRegisterUIModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); +HRESULT +ExecuteRegisterUIModuleCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleUnRegisterUIModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + + +HRESULT +ScheduleInstallHandlerCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ); + +HRESULT +ScheduleUnInstallHandlerCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ); + +HRESULT +ExecuteInstallHandlerCA( + IN CA_DATA_READER * cadata + ); + +HRESULT +ExecuteUnInstallHandlerCA( + IN CA_DATA_READER * cadata + ); + +HRESULT +ExecuteUnRegisterSectionSchemaCA( + IN CA_DATA_READER * cadata +); + + +HRESULT +ScheduleRegisterSectionSchemaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteRegisterSectionSchemaCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleUnRegisterSectionSchemaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ScheduleRegisterTraceAreaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteRegisterTraceAreaCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleRegisterMofFileCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteRegisterMofFileCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleInstallSectionDefaultsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteInstallSectionDefaultsCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleInstallSectionAdditionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteInstallSectionAdditionsCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleInstallCgiRestrictionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ScheduleUnInstallCgiRestrictionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteInstallCgiRestrictionsCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ExecuteUnInstallCgiRestrictionsCA( + IN CA_DATA_READER * cadata +); diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj new file mode 100644 index 0000000000..b01b4ffbf7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj @@ -0,0 +1,131 @@ + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {b54a8f61-60de-4ad9-87ca-d102f230678e} + + + + {7324770c-0871-4d73-be3d-5e2f3e9e1b1e} + Win32Proj + iisca + + + + StaticLibrary + Unicode + v141 + + + + $(IIS-Common)version;$(IIS-Common)Include;$(AdditionalIncludeDirectories) + Create + precomp.h + $(IntDir)precomp.pch + + + + $(WIX)sdk\$(WixPlatformToolset)\inc;$(AdditionalIncludeDirectories) + Level4 + + + nothrownew.obj;httpapi.lib;shlwapi.lib;ahadmin.lib;xmllite.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies) + CustomAction.def + Windows + + + + + _DEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions) + + + + + MaxSpeed + + + true + + + + + $(VC_ReferencesPath_x86);$(WindowsSDK_LibraryPath)\$(PlatformTarget);$(WIX)sdk\$(WixPlatformToolset)\lib\x86;%(AdditionalLibraryDirectories) + MachineX86 + + + + + $(VC_ReferencesPath_x64);$(WindowsSDK_LibraryPath)\$(PlatformTarget);$(WIX)sdk\$(WixPlatformToolset)\lib\x64;%(AdditionalLibraryDirectories) + Machinex64 + + + + + + This project is trying to import a missing file: {0}. + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.cpp new file mode 100644 index 0000000000..e407497402 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.cpp @@ -0,0 +1,791 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + + +#define IIS_CONFIG_BACKUP_EXT L"IISOOBBACK" + + +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + +LPFN_ISWOW64PROCESS fnIsWow64Process; + +BOOL IsWow64() +{ + BOOL bIsWow64 = FALSE; + + //IsWow64Process is not available on all supported versions of Windows. + //Use GetModuleHandle to get a handle to the DLL that contains the function + //and GetProcAddress to get a pointer to the function if available. + + fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( + GetModuleHandle(TEXT("kernel32")),"IsWow64Process"); + + if(NULL != fnIsWow64Process) + { + if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) + { + //handle error + } + } + return bIsWow64; +} + +/******************************************************************** +IISScheduleInstall CA - CUSTOM ACTION ENTRY POINT for reading IIS custom +table settings into CA Data + +********************************************************************/ +UINT +WINAPI +IISScheduleInstallCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + CA_DATA_WRITER cadata; + BOOL bWriteToShared = FALSE; + BOOL fCoInit = FALSE; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + if ( SUCCEEDED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) ) + { + fCoInit = TRUE; + } + + // + //See if we are going to update shared config + // + hr = CheckInstallToSharedConfig( hInstall, &bWriteToShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if ( !bWriteToShared ) + { + //do not update config for this module + //ExecuteCA will not be scheduled. + } + // + // Schedule transactions + // + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISBeginTransactionCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISRollbackTransactionCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISCommitTransactionCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + if( bWriteToShared ) + { + // + // Do the Config Install actions + // + hr = ScheduleInstallModuleCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleRegisterUIModuleCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleInstallHandlerCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleRegisterSectionSchemaCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleRegisterTraceAreaCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleInstallSectionDefaultsCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleInstallSectionAdditionsCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleInstallCgiRestrictionsCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + } + + // + // Do the Non-Config Install actions + // + hr = ScheduleRegisterMofFileCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + + + // + // Schedule deferred execute CA + // + + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISExecuteCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + + hr = NOERROR; + + +exit: + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + IISLogClose(); + + return hr; +} +/******************************************************************** +IISScheduleUninstall CA - CUSTOM ACTION ENTRY POINT for reading IIS custom +table settings into CA Data + +********************************************************************/ +UINT +WINAPI +IISScheduleUninstallCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + CA_DATA_WRITER cadata; + BOOL bWriteToShared = FALSE; + BOOL fCoInit = FALSE; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + if ( SUCCEEDED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) ) + { + fCoInit = TRUE; + } + + // + //See if we are going to update shared config + // + hr = CheckInstallToSharedConfig( hInstall, &bWriteToShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if ( !bWriteToShared ) + { + //do not update config for this module + //ExecuteCA will not be scheduled. + } + + if( bWriteToShared ) + { + // + // Do the Config Uninstall actions + // + hr = ScheduleUnInstallModuleCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleUnRegisterUIModuleCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleUnInstallHandlerCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleUnRegisterSectionSchemaCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleUnInstallCgiRestrictionsCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + } + // + // Do the Non-Config Uninstall actions + // + + + // + // Schedule deferred execute CA + // + + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISExecuteCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + + hr = NOERROR; + + +exit: + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + IISLogClose(); + + // + // Don't fail while uninstalling. + // + return NOERROR; +} +/******************************************************************** +IISExecuteCA - CUSTOM ACTION ENTRY POINT for writing IIS custom +table settings to iis config + +********************************************************************/ +UINT +WINAPI +IISExecuteCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = NOERROR; + CA_DATA_READER cadata; + INT icaType = 0; + BOOL fCoInit = FALSE; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + if ( SUCCEEDED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) ) + { + fCoInit = TRUE; + } + // + // Retrieve parameters from ca data + // + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + while ( SUCCEEDED(hr = cadata.Read( &icaType )) ) + { + switch (icaType ) + { + case IIS_INSTALL_MODULE: + { + hr = ExecuteInstallModuleCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_MODULE: + { + hr = ExecuteUnInstallModuleCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_UIMODULE: + { + hr = ExecuteRegisterUIModuleCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_UIMODULE: + { + hr = ExecuteUnRegisterUIModuleCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_HANDLER: + { + hr = ExecuteInstallHandlerCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_HANDLER: + { + hr = ExecuteUnInstallHandlerCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_SECTIONSCHEMA: + { + hr = ExecuteRegisterSectionSchemaCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_SECTIONSCHEMA: + { + hr = ExecuteUnRegisterSectionSchemaCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_TRACEAREA: + { + hr = ExecuteRegisterTraceAreaCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_MOFFILE: + { + hr = ExecuteRegisterMofFileCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_DEFAULTS: + { + hr = ExecuteInstallSectionDefaultsCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_SECTION_ADDITIONS: + { + hr = ExecuteInstallSectionAdditionsCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_CGIRESTRICTIONS: + { + hr = ExecuteInstallCgiRestrictionsCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_CGIRESTRICTIONS: + { + hr = ExecuteInstallCgiRestrictionsCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + default: + { + //unknown execute CA action type + hr = E_UNEXPECTED; + goto exit; + } + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + IISLogClose(); + + return hr; +} + +/******************************************************************** + BeginTransaction - CUSTOM ACTION ENTRY POINT for backing up + config + + Input: deferred CustomActionData - BackupName +********************************************************************/ +UINT +WINAPI +IISBeginTransactionCA( + IN MSIHANDLE + ) + +{ + HRESULT hr = S_OK; + STACK_STRU( wzConfigSource, MAX_PATH ); + STACK_STRU( wzConfigCopy, MAX_PATH ); + DWORD dwSize = 0; + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\applicationHost.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigSource.SyncWithBuffer(); + hr = wzConfigCopy.Copy( wzConfigSource ); + + //add ca action as extension + + hr = wzConfigCopy.Append( L"."); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT); + + if ( !::CopyFileW(wzConfigSource.QueryStr(), wzConfigCopy.QueryStr(), FALSE) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure2(hr, "Failed to copy config backup %S -> %S", wzConfigSource, wzConfigCopy); + } + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\administration.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\administration.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigSource.SyncWithBuffer(); + hr = wzConfigCopy.Copy( wzConfigSource ); + + //add ca action as extension + + hr = wzConfigCopy.Append( L"."); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT); + + if ( !::CopyFileW(wzConfigSource.QueryStr(), wzConfigCopy.QueryStr(), FALSE) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure2(hr, "Failed to copy config backup %S -> %S", wzConfigSource, wzConfigCopy); + } + + +exit: + + return S_OK; + +} + + +/******************************************************************** + RollbackTransaction - CUSTOM ACTION ENTRY POINT for unbacking up + config + + Input: deferred CustomActionData - BackupName +********************************************************************/ +UINT +WINAPI +IISRollbackTransactionCA( + IN MSIHANDLE + ) +{ + + HRESULT hr = S_OK; + STACK_STRU( wzConfigSource, MAX_PATH ); + STACK_STRU( wzConfigCopy, MAX_PATH ); + DWORD dwSize = 0; + + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\applicationHost.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigSource.SyncWithBuffer(); + hr = wzConfigCopy.Copy( wzConfigSource ); + + //add ca action as extension + + hr = wzConfigCopy.Append( L"." ); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT ); + + //rollback copy is reverse of start transaction + if( !::CopyFileW( wzConfigCopy.QueryStr(), wzConfigSource.QueryStr(), FALSE) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to restore config backup"); + } + + if ( !::DeleteFileW( wzConfigCopy.QueryStr() ) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to delete config backup"); + } + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\administration.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\administration.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigSource.SyncWithBuffer(); + hr = wzConfigCopy.Copy( wzConfigSource ); + + //add ca action as extension + + hr = wzConfigCopy.Append( L"." ); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT ); + + //rollback copy is reverse of start transaction + if( !::CopyFileW( wzConfigCopy.QueryStr(), wzConfigSource.QueryStr(), FALSE) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to restore config backup"); + } + + if ( !::DeleteFileW( wzConfigCopy.QueryStr() ) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to delete config backup"); + } + + +exit: + + return S_OK; + +} +/******************************************************************** + CommitTransaction - CUSTOM ACTION ENTRY POINT for unbacking up + config + + Input: deferred CustomActionData - BackupName +********************************************************************/ +UINT +WINAPI +IISCommitTransactionCA( + IN MSIHANDLE + ) +{ + HRESULT hr = S_OK; + STACK_STRU( wzConfigCopy, MAX_PATH ); + DWORD dwSize = 0; + + + + // Config AdminMgr changes already committed, just + // delete backup config file. + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\applicationHost.config", + wzConfigCopy.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config", + wzConfigCopy.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigCopy.SyncWithBuffer(); + + hr = wzConfigCopy.Append( L"." ); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT); + + if( !::DeleteFileW(wzConfigCopy.QueryStr() ) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to delete config backup"); + } + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\administration.config", + wzConfigCopy.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\administration.config", + wzConfigCopy.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigCopy.SyncWithBuffer(); + + hr = wzConfigCopy.Append( L"." ); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT); + + if( !::DeleteFileW(wzConfigCopy.QueryStr() ) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to delete config backup"); + } + + +exit: + + return S_OK; + +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.h new file mode 100644 index 0000000000..184df8aff8 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.h @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +UINT +WINAPI +IISScheduleInstallCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISScheduleUninstallCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISExecuteCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISBeginTransactionCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISRollbackTransactionCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISCommitTransactionCA( + IN MSIHANDLE hInstall + ); + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/modules.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/modules.cpp new file mode 100644 index 0000000000..341306461d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/modules.cpp @@ -0,0 +1,655 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +// +// Local function declarations +// + +HRESULT +AddModuleToGlobalModules( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szName, + IN CONST WCHAR * szImage, + IN OPTIONAL CONST WCHAR * szPreCondition + ); + +HRESULT +AddModuleToRootModules( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szName, + IN CONST WCHAR * szPreCondition, + IN OPTIONAL CONST WCHAR * szType + ); + +HRESULT +DeleteModuleFromRootModules( + IAppHostAdminManager * pAdminMgr, + CONST WCHAR * szName, + BOOL * pfDeleted + ); + +// +// Public functions +// + +HRESULT +InstallModule( + IN CONST WCHAR * szName, + IN CONST WCHAR * szImage, + IN OPTIONAL CONST WCHAR * szPreCondition, + IN OPTIONAL CONST WCHAR * szType + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // If the type is present, this is a .Net module and + // should not be added to the globalModules + if ( ( szType == NULL ) || ( *szType == L'\0' ) ) + { + STRU strFinalImage; + WCHAR ProgFiles[64]; + WCHAR SysRoot[64]; + WCHAR SysDrive[16]; + PCWSTR szSubstFrom = NULL; + PCWSTR szSubstTo = NULL; + + if (GetEnvironmentVariable(L"ProgramFiles", + ProgFiles, + _countof(ProgFiles)) > _countof(ProgFiles) || + GetEnvironmentVariable(L"SystemRoot", + SysRoot, + _countof(SysRoot)) > _countof(SysRoot) || + GetEnvironmentVariable(L"SystemDrive", + SysDrive, + _countof(SysDrive)) > _countof(SysDrive)) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + if (_wcsnicmp(szImage, ProgFiles, wcslen(ProgFiles)) == 0) + { + szSubstFrom = ProgFiles; + szSubstTo = L"%ProgramFiles%"; + } + else if (_wcsnicmp(szImage, SysRoot, wcslen(SysRoot)) == 0) + { + szSubstFrom = SysRoot; + szSubstTo = L"%SystemRoot%"; + } + else if (_wcsnicmp(szImage, SysDrive, wcslen(SysDrive)) == 0) + { + szSubstFrom = SysDrive; + szSubstTo = L"%SystemDrive%"; + } + + if (szSubstFrom != NULL) + { + if (FAILED(hr = strFinalImage.Copy(szSubstTo)) || + FAILED(hr = strFinalImage.Append(szImage + wcslen(szSubstFrom)))) + { + goto exit; + } + szImage = strFinalImage.QueryStr(); + } + + hr = AddModuleToGlobalModules( pAdminMgr, + szName, + szImage, + szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = AddModuleToRootModules( pAdminMgr, + szName, + szPreCondition, + szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +UnInstallModule( + IN CONST WCHAR * szName, + IN OPTIONAL CONST WCHAR * szType + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pGlobalModulesSection; + CComPtr pGlobalModulesCollection; + + BSTR bstrAppHostConfigPath = SysAllocString( L"MACHINE/WEBROOT/APPHOST" ); + BSTR bstrGlobalModules = SysAllocString( L"system.webServer/globalModules" ); + + BOOL fChanged = FALSE; + BOOL fDeleted = FALSE; + UINT numDeleted; + + if ( !bstrAppHostConfigPath || + !bstrGlobalModules ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Remove from root modules + // + + hr = DeleteModuleFromRootModules( pAdminMgr, + szName, + &fDeleted ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !fDeleted ) + { + DBGWARN(( DBG_CONTEXT, + "Expected to find %S in root modules collection\n" , + szName )); + } + + fChanged = fDeleted; + + if ( ( szType == NULL ) || ( *szType == L'\0' ) ) + { + // + // Remove from globalModules + // + + hr = pAdminMgr->GetAdminSection( bstrGlobalModules, + bstrAppHostConfigPath, + &pGlobalModulesSection ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pGlobalModulesSection->get_Collection( &pGlobalModulesCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + + hr = DeleteAllElementsFromCollection( pGlobalModulesCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + &numDeleted ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( numDeleted == 0 ) + { + DBGWARN(( DBG_CONTEXT, + "Expected to find %S in globalModules list.\n", + szName )); + } + else + { + fChanged = TRUE; + } + } + + if ( fChanged ) + { + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + +exit: + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrGlobalModules ); + + return hr; +} + +// +// Local functions +// + +HRESULT +AddModuleToGlobalModules( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szName, + IN CONST WCHAR * szImage, + IN OPTIONAL CONST WCHAR * szPreCondition + ) +{ + HRESULT hr = NOERROR; + + CComPtr pGlobalModulesSection; + CComPtr pGlobalModulesCollection; + CComPtr pNewGlobalModuleElement; + + VARIANT varPropValue; + VariantInit( &varPropValue ); + + BSTR bstrAppHostConfigPath = SysAllocString( L"MACHINE/WEBROOT/APPHOST" ); + BSTR bstrGlobalModules = SysAllocString( L"system.webServer/globalModules" ); + BSTR bstrAdd = SysAllocString( L"add" ); + + if ( !bstrAppHostConfigPath || + !bstrGlobalModules || + !bstrAdd ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + // + // Get the global modules collection + // + + hr = pAdminMgr->GetAdminSection( bstrGlobalModules, + bstrAppHostConfigPath, + &pGlobalModulesSection ); + + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pGlobalModulesSection->get_Collection( &pGlobalModulesCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + // + // Create a new module element + // + + hr = pGlobalModulesCollection->CreateNewElement( bstrAdd, + &pNewGlobalModuleElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = VariantAssign( &varPropValue, szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewGlobalModuleElement, + L"name", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = VariantAssign( &varPropValue, szImage ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewGlobalModuleElement, + L"image", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + if ( szPreCondition && *szPreCondition ) + { + hr = VariantAssign( &varPropValue, szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewGlobalModuleElement, + L"preCondition", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + // + // Add the new element + // + + hr = pGlobalModulesCollection->AddElement( pNewGlobalModuleElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + VariantClear( &varPropValue ); + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrGlobalModules ); + SysFreeString( bstrAdd ); + + return hr; +} + +HRESULT +AddModuleToRootModules( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szName, + IN CONST WCHAR * szPreCondition, + IN OPTIONAL CONST WCHAR * szType + ) +{ + HRESULT hr = NOERROR; + + BOOL found = FALSE; + + CComPtr pLocation; + CComPtr pModulesSection; + CComPtr pModuleCollection; + CComPtr pNewModuleElement; + + VARIANT varPropValue; + VariantInit( &varPropValue ); + + BSTR bstrAdd = SysAllocString( L"add" ); + + if ( !bstrAdd ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = GetLocationFromFile( pAdminMgr, + L"MACHINE/WEBROOT/APPHOST", + L"", + &pLocation, + &found ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !found ) + { + hr = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ); + DBGERROR(( DBG_CONTEXT, + "Failed to find root location path\n" )); + goto exit; + } + + hr = GetSectionFromLocation( pLocation, + L"system.webServer/modules", + &pModulesSection, + &found ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !found ) + { + hr = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ); + DBGERROR(( DBG_CONTEXT, + "Failed to find modules section\n" )); + goto exit; + } + + // + // Create a new module element + // + + hr = pModulesSection->get_Collection( &pModuleCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pModuleCollection->CreateNewElement( bstrAdd, + &pNewModuleElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varPropValue, szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"name", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + if ( szPreCondition && *szPreCondition ) + { + hr = VariantAssign( &varPropValue, szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"preCondition", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + if ( szType && *szType ) + { + hr = VariantAssign( &varPropValue, szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"type", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + hr = pModuleCollection->AddElement( pNewModuleElement, + -1 ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrAdd ); + VariantClear( &varPropValue ); + + return hr; +} + +HRESULT +DeleteModuleFromRootModules( + IAppHostAdminManager * pAdminMgr, + CONST WCHAR * szName, + BOOL * pfDeleted + ) +{ + HRESULT hr = NOERROR; + + CComPtr pLocation; + CComPtr pModulesSection; + CComPtr pModulesCollection; + + UINT numDeleted; + BOOL found = FALSE; + + *pfDeleted = FALSE; + + hr = GetLocationFromFile( pAdminMgr, + L"MACHINE/WEBROOT/APPHOST", + L"", + &pLocation, + &found ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !found ) + { + DBGWARN(( DBG_CONTEXT, + "Failed to find root location path\n" )); + goto exit; + } + + hr = GetSectionFromLocation( pLocation, + L"system.webServer/modules", + &pModulesSection, + &found ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !found ) + { + DBGWARN(( DBG_CONTEXT, + "Failed to find modules section in root\n" )); + goto exit; + } + + hr = pModulesSection->get_Collection( &pModulesCollection ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = DeleteAllElementsFromCollection( pModulesCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + &numDeleted ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( numDeleted == 0 ) + { + DBGWARN(( DBG_CONTEXT, + "Failed to find %S in root modules\n", + szName )); + } + else + { + *pfDeleted = TRUE; + } + +exit: + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/mof.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/mof.cpp new file mode 100644 index 0000000000..2f13ab1dfc --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/mof.cpp @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" +#include + +HRESULT +RegisterMofFile( + __in PWSTR pszFileName +) +{ + HRESULT hr = S_OK; + WBEM_COMPILE_STATUS_INFO CompileStatusInfo; + CComPtr pCompiler; + + hr = CoCreateInstance( _uuidof(MofCompiler), + 0, + CLSCTX_INPROC_SERVER, + _uuidof(IMofCompiler), + (LPVOID *) &pCompiler); + if ( FAILED( hr ) ) + { + // + // Register the COM object if is not registered. + // + WCHAR * pszDllPath = new WCHAR[ MAX_PATH ]; + if ( pszDllPath != NULL ) + { + if ( GetSystemDirectory( pszDllPath, MAX_PATH ) != 0 ) + { + HRESULT (STDAPICALLTYPE *pfDllRegisterServer)(VOID); + + (VOID) StringCchCat( pszDllPath, MAX_PATH, L"\\wbem\\mofd.dll" ); + + HINSTANCE hLib = LoadLibraryEx( pszDllPath, + NULL, + LOAD_WITH_ALTERED_SEARCH_PATH ); + if ( hLib != NULL ) + { + pfDllRegisterServer = (HRESULT (STDAPICALLTYPE *)(VOID))GetProcAddress(hLib, "DllRegisterServer"); + if ( pfDllRegisterServer != NULL ) + { + pfDllRegisterServer(); + hr = CoCreateInstance( _uuidof(MofCompiler), + 0, + CLSCTX_INPROC_SERVER, + _uuidof(IMofCompiler), + (LPVOID *) &pCompiler); + } + FreeLibrary( hLib ); + } + } + delete [] pszDllPath; + } + if ( FAILED( hr ) ) + { + goto Finished; + } + } + + hr = pCompiler->CompileFile( pszFileName, + NULL, // namespace + NULL, // username + NULL, // authoroty + NULL, // password + 0, // option flags + 0, // class flags + 0, // instance + &CompileStatusInfo ); + if ( hr != S_OK ) + { + // + // Means failure. + // + goto Finished; + } + +Finished: + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.cpp new file mode 100644 index 0000000000..2a9b65ab37 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.cpp @@ -0,0 +1,581 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +MsiUtilGetProperty( + IN MSIHANDLE hInstall, + __in PCWSTR szName, + __inout STRU * pstrProperty + ) +{ + HRESULT hr = NOERROR; + DWORD cch = 0; + WCHAR dummy = L'\0'; + DWORD status; + + pstrProperty->Reset(); + + // + // Get the length. + // + + status = MsiGetPropertyW( hInstall, + szName, + &dummy, + &cch ); + + if( status != ERROR_MORE_DATA ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + // + // Return is count of characters w/o NULL + // + + cch++; + + hr = pstrProperty->Resize( cch ); + if( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetPropertyW( hInstall, + szName, + pstrProperty->QueryStr(), + &cch ); + + if( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + pstrProperty->SyncWithBuffer(); + +exit: + + return hr; +} + + +HRESULT +MsiUtilScheduleDeferredAction( + IN MSIHANDLE hInstall, + __in PCWSTR szAction, + __in PCWSTR szData + ) +{ + HRESULT hr = NOERROR; + UINT status; + + status = MsiSetPropertyW( hInstall, + szAction, + szData ); + if( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDoActionW( hInstall, + szAction ); + + if( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32(status ); + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +MsiUtilRecordGetInteger( + IN MSIHANDLE hRecord, + IN UINT field, + __inout UINT * pInt + ) +{ + HRESULT hr = NOERROR; + UINT tempValue = 0; + + _ASSERTE(pInt); + + tempValue = MsiRecordGetInteger(hRecord, field); + + if( MSI_NULL_INTEGER == tempValue ) + { + hr = E_UNEXPECTED; + DBGERROR(( DBG_CONTEXT, "Non-integer value encountered in Integer field, %08x\n", hr )); + goto exit; + } + + *pInt = tempValue; + +exit: + return hr; +} + +HRESULT +MsiUtilRecordGetString( + IN MSIHANDLE hRecord, + IN UINT field, + __inout STRU * pstr + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + DWORD cch = pstr->QuerySizeCCH(); + + status = MsiRecordGetStringW( hRecord, + field, + pstr->QueryStr(), + &cch ); + + if( ERROR_MORE_DATA == status ) + { + hr = pstr->Resize( ++cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiRecordGetStringW( hRecord, + field, + pstr->QueryStr(), + &cch ); + } + + if( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + hr = pstr->SetLen( cch ); + if( FAILED(hr) ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +MsiUtilRecordReadStreamIntoFile( + IN MSIHANDLE hRecord, + IN UINT field, + IN PCWSTR szFileName + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + HANDLE hOutputFile = INVALID_HANDLE_VALUE; + + _ASSERTE(szFileName); + + hOutputFile = CreateFileW( szFileName, + GENERIC_WRITE, + 0, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if ( INVALID_HANDLE_VALUE == hOutputFile ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + do + { + DWORD bytesWritten = 0; + BOOL fRet = FALSE; + CHAR szBuffer[4096]; + DWORD cbBuf = sizeof(szBuffer); + + status = MsiRecordReadStream(hRecord, field, szBuffer, &cbBuf); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + else if ( 0 == cbBuf ) + { + //we've reached the end of the stream + break; + } + + fRet = WriteFile(hOutputFile, szBuffer, cbBuf, &bytesWritten, NULL); + if( !fRet ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + } while (1); + + +exit: + + if( INVALID_HANDLE_VALUE != hOutputFile) + { + CloseHandle( hOutputFile ); + hOutputFile = INVALID_HANDLE_VALUE; + } + + return hr; +} + +HRESULT +MsiUtilFormatString( + IN MSIHANDLE hInstall, + __inout STRU * pstrData + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + MSIHANDLE hRecord = NULL; + + hRecord = MsiCreateRecord( 1 ); + if( !hRecord ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + status = MsiRecordSetStringW( hRecord, + 0, + pstrData->QueryStr() ); + if( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + DWORD cch = pstrData->QuerySizeCCH(); + + status = MsiFormatRecordW( hInstall, + hRecord, + pstrData->QueryStr(), + &cch ); + if( ERROR_MORE_DATA == status ) + { + hr = pstrData->Resize( ++cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiFormatRecordW( hInstall, + hRecord, + pstrData->QueryStr(), + &cch ); + } + + if( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + hr = pstrData->SetLen( cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + if( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + return hr; +} + +WCHAR CA_DATA_DELIM[] = { '^', 0 }; + +// +// BUGBUG - Prefix will barf on this +// Can I really trust this data hasn't been tampered with? +// +WCHAR * +CA_DATA_READER::ExtractString() +{ + if( !_current || *_current == 0 ) + { + return NULL; + } + + // + // String format is: + // (len - delim - data - delim) (xN) \0 + // "3^cat^4^fish^\0" + // + + // + // extract length of data + // + + WCHAR * psz = wcsstr( _current, CA_DATA_DELIM ); + + _ASSERTE( psz ); + if( psz ) + { + *psz = 0; + INT cch = wcstol( _current, NULL, 0 ); + + // + // advance to data + // + + psz++; + + // + // terminate and advance to next block + // + + _current = psz + cch; + *_current = 0; + + _current++; + } + + return psz; +} + +HRESULT +CA_DATA_WRITER::WriteInternal( + CONST WCHAR * sz, + INT n +) +{ + HRESULT hr = NOERROR; + + // + // Write out the data length + // + + WCHAR buffer[20]; + StringCchPrintfW( buffer, sizeof(buffer)/sizeof(buffer[0]), L"%d", n ); + + hr = _data.Append( buffer ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = _data.Append( CA_DATA_DELIM ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Write out the data + // + + hr = _data.Append( sz ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = _data.Append( CA_DATA_DELIM ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + + + +BOOL +MsiUtilIsInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ) +{ + return (INSTALLSTATE_LOCAL == isAction || + INSTALLSTATE_SOURCE == isAction || + (INSTALLSTATE_DEFAULT == isAction && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled))); +} + + +BOOL +MsiUtilIsReInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ) +{ + return ((INSTALLSTATE_LOCAL == isAction || + INSTALLSTATE_SOURCE == isAction || + INSTALLSTATE_DEFAULT == isAction || + INSTALLSTATE_UNKNOWN == isAction) && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled)); +} + + +BOOL +MsiUtilIsUnInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ) +{ + return ((INSTALLSTATE_ABSENT == isAction || + INSTALLSTATE_REMOVED == isAction) && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled)); +} + +HRESULT +GenerateTempFileName( + __in PCWSTR szPrefix, + __in PCWSTR szExtension, + __inout STRU * pstr +) +{ + HRESULT hr = NOERROR; + UINT status = 0; + STACK_STRU( guidName, 128 ); + GUID guid = {0}; + DWORD cch = 0; + + _ASSERTE(szPrefix); + _ASSERTE(szExtension); + _ASSERTE(pstr); + + cch = pstr->QuerySizeCCH(); + + status = GetTempPathW(cch, pstr->QueryStr()); + if ( status > cch) + { + cch = status; + hr = pstr->Resize( ++cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error resizing buffer, hr=0x%x", hr); + goto exit; + } + + status = GetTempPathW(cch, pstr->QueryStr()); + } + + if ( 0 == status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting temp path, hr=0x%x", hr); + goto exit; + } + + pstr->SyncWithBuffer(); + + hr = pstr->Append(L"\\"); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error apppending \\, hr=0x%x", hr); + goto exit; + } + + hr = pstr->Append(szPrefix); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error appending file prefix, hr=0x%x", hr); + goto exit; + } + + cch = guidName.QuerySizeCCH(); + hr = CoCreateGuid ( &guid ); + if ( FAILED (hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error generating the GUID, hr=0x%x", hr); + goto exit; + } + + if ( !StringFromGUID2( guid, guidName.QueryStr(), cch ) ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting string from GUID, hr=0x%x", hr); + goto exit; + } + + guidName.SyncWithBuffer(); + + hr = pstr->Append(guidName.QueryStr()); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error appending GUID, hr=0x%x", hr); + goto exit; + } + + hr = pstr->Append(L"."); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error appending ., hr=0x%x", hr); + goto exit; + } + + hr = pstr->Append(szExtension); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error appending extension, hr=0x%x", hr); + goto exit; + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + return hr; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.h new file mode 100644 index 0000000000..e7c770c534 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.h @@ -0,0 +1,192 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +HRESULT +MsiUtilGetProperty( + IN MSIHANDLE hInstall, + __in PCWSTR szName, + __inout STRU * pstrProperty + ); + +HRESULT +MsiUtilScheduleDeferredAction( + IN MSIHANDLE hInstall, + __in PCWSTR szAction, + __in PCWSTR szData + ); + +HRESULT +MsiUtilRecordGetInteger( + IN MSIHANDLE hRecord, + IN UINT field, + __inout UINT * pInt + ); + +HRESULT +MsiUtilRecordGetString( + IN MSIHANDLE hRecord, + IN UINT field, + __inout STRU * pstr + ); + +HRESULT +MsiUtilRecordReadStreamIntoFile( + IN MSIHANDLE hRecord, + IN UINT field, + IN PCWSTR szFileName + ); + +HRESULT +MsiUtilFormatString( + IN MSIHANDLE hInstall, + __inout STRU * pstrData + ); + +class CA_DATA_WRITER +{ +public: + + CA_DATA_WRITER() + { + } + + HRESULT + Write( + CONST WCHAR * sz + ) + { + return WriteInternal( sz, (INT)wcslen(sz) ); + } + + HRESULT + Write( + CONST WCHAR * sz, + INT cch + ) + { + return WriteInternal( sz, cch ); + } + + HRESULT + Write( + INT n + ) + { + HRESULT hr; + + WCHAR buffer[20]; + hr = StringCchPrintfW( buffer, + sizeof(buffer)/sizeof(buffer[0]), + L"%d", + n ); + if( FAILED(hr) ) + { + return hr; + } + + return WriteInternal( buffer, (INT)wcslen(buffer) ); + } + + CONST WCHAR * + QueryData() const + { + return _data.QueryStr(); + } + +protected: + + HRESULT + WriteInternal( + CONST WCHAR * sz, + INT n + ); + + STRU _data; +}; + +class CA_DATA_READER +{ +public: + + CA_DATA_READER() : + _current( NULL ) + { + } + + ~CA_DATA_READER() + { + } + + HRESULT + LoadDeferredCAData( + MSIHANDLE hInstall + ) + { + HRESULT hr = MsiUtilGetProperty( hInstall, L"CustomActionData", &_strCustomActionData ); + _current = _strCustomActionData.QueryStr(); + return hr; + } + + HRESULT + Read( + __deref_out_z WCHAR ** psz + ) + { + *psz = ExtractString(); + if( !*psz ) + { + return HRESULT_FROM_WIN32( ERROR_NO_MORE_ITEMS ); + } + return S_OK; + } + + HRESULT + Read( + INT * pi + ) + { + CONST WCHAR * sz = ExtractString(); + if( !sz ) + { + return HRESULT_FROM_WIN32( ERROR_NO_MORE_ITEMS ); + } + *pi = wcstol( sz, NULL, 10 ); + return S_OK; + } + +private: + + WCHAR * + ExtractString(); + + STRU _strCustomActionData; + WCHAR * _current; +}; + + +BOOL +MsiUtilIsReInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ); + +BOOL +MsiUtilIsInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ); + +BOOL +MsiUtilIsUnInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ); + +HRESULT +GenerateTempFileName( + __in PCWSTR szPrefix, + __in PCWSTR szExtension, + __inout STRU * pstr +); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/packages.config b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/packages.config new file mode 100644 index 0000000000..21d9344493 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/precomp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/precomp.h new file mode 100644 index 0000000000..5f32044523 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/precomp.h @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +// Don't throw exceptions for CComVariant failures. +// Check for VT_ERROR instead. +#define _ATL_NO_VARIANT_THROW +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#pragma warning( disable:4127 ) +#include +#include "dbgutil.h" +#include +#define IRTL_DLLEXP +#include +#include +#include +#include +#include +#include +#include + +// +// Security APIs. +// +#include +#include +#include +#include + + +#include "ahutil.h" +#include "msiutil.h" +#include "defaults.h" +#include "cgi_restrictions.h" +#include "handlers.h" +#include "tracing.h" +#include "config_custom.h" +#include "setup_log.h" +#include "httpapi.h" +#include "secutils.h" +#include "ConfigShared.h" +#include "iisca.h" +#include "iiscaexp.h" +extern HINSTANCE g_hinst; + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/schema.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/schema.cpp new file mode 100644 index 0000000000..fe39b356f0 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/schema.cpp @@ -0,0 +1,741 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +GetChildSectionGroup( + IN IAppHostSectionGroup * pParentSectionGroup, + IN CONST WCHAR * szChildGroupName, + OUT IAppHostSectionGroup ** ppChildSectionGroup + ) +{ + HRESULT hr = NOERROR; + + CComPtr pChildSectionGroup; + + VARIANT varChildGroupName; + VariantInit( &varChildGroupName ); + + *ppChildSectionGroup = NULL; + + hr = VariantAssign( &varChildGroupName, + szChildGroupName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pParentSectionGroup->get_Item( varChildGroupName, + &pChildSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + *ppChildSectionGroup = pChildSectionGroup.Detach(); + +exit: + + VariantClear( &varChildGroupName ); + + return hr; +} + +HRESULT +GetRootSectionGroup( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostSectionGroup ** ppRootSectionGroup + ) +{ + HRESULT hr = NOERROR; + + CComPtr pRootSectionGroup; + CComPtr pConfigMgr; + CComPtr pConfigFile; + + BSTR bstrConfigPath = NULL; + + *ppRootSectionGroup = NULL; + + bstrConfigPath = SysAllocString( szConfigPath ); + + if( !bstrConfigPath ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->get_ConfigManager( &pConfigMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigMgr->GetConfigFile( bstrConfigPath, + &pConfigFile ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigFile->get_RootSectionGroup( &pRootSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + *ppRootSectionGroup = pRootSectionGroup.Detach(); + +exit: + + SysFreeString( bstrConfigPath ); + + return hr; +} + +HRESULT +InitializeAdminManager( + IN CONST BOOL isSectionInAdminSchema, + IN IAppHostWritableAdminManager * pAdminMgr, + OUT CONST WCHAR ** pszCommitPath +) +{ + HRESULT hr = NOERROR; + CONST WCHAR * szAdminCommitPath = L"MACHINE/WEBROOT"; + CONST WCHAR * szAppHostCommitPath = L"MACHINE/WEBROOT/APPHOST"; + + CONST WCHAR * szCommitPath = NULL; + + *pszCommitPath = NULL; + + if(isSectionInAdminSchema) + { + szCommitPath = szAdminCommitPath; + hr = InitAdminMgrForAdminConfig( pAdminMgr, + szCommitPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + else + { + szCommitPath = szAppHostCommitPath; + } + + *pszCommitPath = szCommitPath; + +exit: + return hr; +} + +HRESULT +RegisterSectionSchema( + IN CONST BOOL isSectionInAdminSchema, + IN CONST WCHAR * szSectionName, + IN CONST WCHAR * szOverrideModeDefault, + IN OPTIONAL CONST WCHAR * szAllowDefinition, + IN OPTIONAL CONST WCHAR * szType + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pRootSectionGroup; + CComPtr pParentSectionGroup; + CComPtr pChildSectionGroup; + CComPtr pSections; + CComPtr pNewSection; + + + BSTR bstrSectionGroupName = NULL; + BSTR bstrSectionName = NULL; + BSTR bstrOverrideModeDefault = NULL; + BSTR bstrAllowDefinition = NULL; + BSTR bstrType = NULL; + + CONST WCHAR * szCommitPath = NULL; + + WCHAR * szSectionNameCopy = _wcsdup( szSectionName ); + if( !szSectionNameCopy ) + { + hr = E_OUTOFMEMORY; + goto exit; + } + szSectionName = NULL; + + // + // szSectionNameCopy is the full name of the section. The last + // segment szShortName will be registered as the name of the + // section and the other segments are section groups + // + // eg. "system.webServer/foo/bar/mysection" + // + + WCHAR * szShortName = wcsrchr( szSectionNameCopy, L'/' ); + if( szShortName == NULL ) + { + szShortName = szSectionNameCopy; + } + else + { + *szShortName++ = L'\0'; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = InitializeAdminManager( isSectionInAdminSchema, + pAdminMgr, + &szCommitPath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetRootSectionGroup( pAdminMgr, + szCommitPath, + &pRootSectionGroup); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // For each section group referenced in szSectionNameCopy retrieve or + // create it. + // + + WCHAR * pszGroupName = szSectionNameCopy; + WCHAR * pszNext = NULL; + + pParentSectionGroup = pRootSectionGroup; + + if (szShortName == szSectionNameCopy) + { + goto SkipAddingGroups; + } + + while( pszGroupName ) + { + pszNext = wcschr( pszGroupName, L'/' ); + if( pszNext ) + { + *pszNext++ = 0; + } + + hr = GetChildSectionGroup( pParentSectionGroup, + pszGroupName, + &pChildSectionGroup ); + + if( hr == HRESULT_FROM_WIN32( ERROR_INVALID_INDEX ) ) + { + // + // Create the group if it does not exist + // + bstrSectionGroupName = SysAllocString( pszGroupName ); + if( !bstrSectionGroupName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pParentSectionGroup->AddSectionGroup( bstrSectionGroupName, + &pChildSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + else if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pParentSectionGroup = pChildSectionGroup; + pChildSectionGroup.Release(); + + SysFreeString( bstrSectionGroupName ); + bstrSectionGroupName = NULL; + + pszGroupName = pszNext; + } + + SkipAddingGroups: + // + // Add the new section + // + + hr = pParentSectionGroup->get_Sections( &pSections ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + bstrSectionName = SysAllocString( szShortName ); + if( !bstrSectionName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pSections->AddSection( bstrSectionName, + &pNewSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + bstrOverrideModeDefault = SysAllocString( szOverrideModeDefault ); + if( !bstrOverrideModeDefault ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pNewSection->put_OverrideModeDefault( bstrOverrideModeDefault ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( szAllowDefinition && *szAllowDefinition ) + { + bstrAllowDefinition = SysAllocString( szAllowDefinition ); + if( !bstrAllowDefinition ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pNewSection->put_AllowDefinition( bstrAllowDefinition ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if( szType && *szType ) + { + bstrType = SysAllocString( szType ); + if( !bstrType ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pNewSection->put_Type( bstrType ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + // + // Persist changes + // + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrSectionGroupName ); + SysFreeString( bstrSectionName ); + SysFreeString( bstrOverrideModeDefault ); + SysFreeString( bstrType ); + SysFreeString( bstrAllowDefinition ); + + free( szSectionNameCopy ); + + return hr; +} + +HRESULT +RemoveSectionDefinition( + IN IAppHostSectionGroup * pParentSection, + __in_z WCHAR * szSectionPath, + __in_z WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pChildSectionGroup; + CComPtr pSections; + + WCHAR * pszNextPath = NULL; + + VARIANT varIndex; + VariantInit( &varIndex ); + + // + // If there are no more path segments, remove the section + // + + if( !szSectionPath ) + { + hr = pParentSection->get_Sections( &pSections ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varIndex, szSectionName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSections->DeleteSection( varIndex ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // End recursion + goto exit; + } + + // + // We have more path segments, so move to the next segment + // and call RemoveSectionDefinition recursively + // + + pszNextPath = wcschr( szSectionPath, L'/' ); + if( pszNextPath ) + { + *pszNextPath++ = 0; + } + + hr = GetChildSectionGroup( pParentSection, + szSectionPath, + &pChildSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = RemoveSectionDefinition( pChildSectionGroup, + pszNextPath, + szSectionName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // The section has been removed, check to see if the + // child section group is empty and clean up if it is. + // + + ULONG childCount = 0; + hr = pChildSectionGroup->get_Count( &childCount ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( childCount == 0 ) + { + hr = pChildSectionGroup->get_Sections( &pSections ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSections->get_Count( &childCount ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( childCount == 0 ) + { + hr = VariantAssign( &varIndex, szSectionPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pParentSection->DeleteSectionGroup( varIndex ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + } + +exit: + + VariantClear( &varIndex ); + + return hr; +} + +HRESULT +RemoveSectionData( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN CONST WCHAR * szConfigPath + ) +{ + HRESULT hr = NOERROR; + + CComPtr pSectionElement; + CComPtr pConfigMgr; + CComPtr pConfigFile; + CComPtr pLocations; + CComPtr pLocation; + + BSTR bstrSectionName = SysAllocString( szSectionName ); + BSTR bstrPath = SysAllocString( szConfigPath ); + + VARIANT varSectionName; + VariantInit( &varSectionName ); + + if( !bstrSectionName || + !bstrPath ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varSectionName, szSectionName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrSectionName, + bstrPath, + &pSectionElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSectionElement->Clear(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Go through the location tags and delete the section + // + + hr = pAdminMgr->get_ConfigManager( &pConfigMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigMgr->GetConfigFile( bstrPath, + &pConfigFile ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigFile->get_Locations( &pLocations ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + DWORD count; + VARIANT varIndex; + VariantInit( &varIndex ); + + hr = pLocations->get_Count( &count ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for( DWORD i = 0; i < count; i++ ) + { + varIndex.vt = VT_UI4; + varIndex.ulVal = i; + + hr = pLocations->get_Item( varIndex, &pLocation ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pLocation->DeleteConfigSection( varSectionName ); + if( HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) == hr ) + { + hr = S_OK; + } + else if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pLocation.Release(); + } + +exit: + + SysFreeString( bstrSectionName ); + SysFreeString( bstrPath ); + + return hr; +} + +HRESULT +UnRegisterSectionSchema( + IN CONST BOOL isSectionInAdminSchema, + IN CONST WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pRootSectionGroup; + + CONST WCHAR * szCommitPath = NULL; + + WCHAR * szSectionNameCopy = _wcsdup( szSectionName ); + if( !szSectionNameCopy ) + { + hr = E_OUTOFMEMORY; + goto exit; + } + + // + // szSectionNameCopy is the full name of the section. The last + // segment szShortName will be registered as the name of the + // section and the other segments are section groups + // + // eg. "system.webServer/foo/bar/mysection" + // + + WCHAR * szShortName = wcsrchr( szSectionNameCopy, L'/' ); + if( szShortName == NULL ) + { + szShortName = szSectionNameCopy; + } + else + { + *szShortName++ = 0; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = InitializeAdminManager( isSectionInAdminSchema, + pAdminMgr, + &szCommitPath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = RemoveSectionData( pAdminMgr, + szSectionName, + szCommitPath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetRootSectionGroup( pAdminMgr, + szCommitPath, + &pRootSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = RemoveSectionDefinition( pRootSectionGroup, + (szShortName == szSectionNameCopy) ? NULL : szSectionNameCopy, + szShortName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + free( szSectionNameCopy ); + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.cpp new file mode 100644 index 0000000000..8806cd667e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.cpp @@ -0,0 +1,1125 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + +#ifndef STATUS_SOME_NOT_MAPPED +// +// MessageId: STATUS_SOME_NOT_MAPPED +// +// MessageText: +// +// Some of the information to be translated has not been translated. +// +#define STATUS_SOME_NOT_MAPPED ((NTSTATUS)0x00000107L) +#endif + +#ifndef STATUS_NONE_MAPPED +#define STATUS_NONE_MAPPED ((NTSTATUS)0xc0000073L) +#endif + + +HRESULT +IsVistaOrGreater( + __out BOOL & fIsVistaOrGreater +) +/*++ + +Routine Description: + + Return TRUE if we are running in a Server SKU, + otherwise return FALSE. + +Arguments: + + pfIsServer - The return value. + +Return Value: + + BOOL + +--*/ +{ + HRESULT hr = S_OK; + OSVERSIONINFOEX osVersionInfoEx = { 0 }; + DWORDLONG dwlConditionMask = 0; + BOOL fReturn = FALSE; + + fIsVistaOrGreater = FALSE; + osVersionInfoEx.dwOSVersionInfoSize = sizeof( osVersionInfoEx ); + osVersionInfoEx.dwMajorVersion = 6; + + VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL ); + + fReturn = VerifyVersionInfo( + &osVersionInfoEx, + VER_MAJORVERSION, + dwlConditionMask ); + + // + // If the function fails, the return value is zero + // and GetLastError returns an error code other than ERROR_OLD_WIN_VERSION + // + if ( fReturn == FALSE && GetLastError() != ERROR_OLD_WIN_VERSION ) + { + hr = HRESULT_FROM_WIN32 ( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + + fIsVistaOrGreater = ( fReturn ); + +Finished: + + return hr; + +} + +HRESULT +CreateDirectory( + __in LPCWSTR pszFileName +) +{ + HRESULT hr = S_OK; + DWORD dwFileAttributes = 0; + + dwFileAttributes = GetFileAttributes( pszFileName ); + if ( dwFileAttributes == INVALID_FILE_ATTRIBUTES ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + + if ( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) || + hr == HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) ) + { + hr = S_OK; + + // + // Create the folder. + // + if ( !CreateDirectory( pszFileName, NULL ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + } + else + { + DBGERROR_HR( hr ); + } + } + +Finished: + + return hr; +} + +HRESULT +AddExplicitAccessToFileDacl( + __in LPWSTR pszFilePath, + DWORD cExplicitAccess, + EXPLICIT_ACCESS rgExplicitAccess[] +) +/*++ + +Routine Description: + + Add EXPLICIT_ACCESS entries to a file DACL + +Arguments: + + pszFilePath - The path to the file where the DACL will be modified + cExplicitAccess - The count of EXPLICIT_ACCESS entires to add + rgExplicitAccess - The EXPLICIT_ACCESS entries + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + DWORD dwError = ERROR_SUCCESS; + PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; + PACL pOldFileDacl = NULL; + PACL pNewFileDacl = NULL; + + if ( pszFilePath == NULL || + cExplicitAccess == 0 || + rgExplicitAccess == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Finished; + } + + // + // Get the current file DACL + // + dwError = GetNamedSecurityInfo( pszFilePath, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, // ppsidOwner + NULL, // ppsidGroup + &pOldFileDacl, + NULL, // ppSacl + &pSecurityDescriptor ); + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + goto Finished; + } + + // + // Create a new DACL with the EXPLICIT_ACCESS entries + // + + dwError = SetEntriesInAcl( cExplicitAccess, + rgExplicitAccess, + pOldFileDacl, + &pNewFileDacl ); + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + goto Finished; + } + + // + // Write the new DACL + // + + dwError = SetNamedSecurityInfo( pszFilePath, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, // psidOwner + NULL, // psidGroup + pNewFileDacl, + NULL ); // pSacl + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + goto Finished; + } + +Finished: + + if ( pNewFileDacl != NULL ) + { + LocalFree( pNewFileDacl ); + pNewFileDacl = NULL; + } + + if ( pSecurityDescriptor != NULL ) + { + LocalFree( pSecurityDescriptor ); + pSecurityDescriptor = NULL; + } + + return hr; +} + +HRESULT +GrantFileAccessToIisIusrs( + __in LPWSTR pszFilePath, + DWORD dwAccessMask, + DWORD dwInheritance +) +/*++ + +Routine Description: + + This method gives the IIS_IUSRS group access to a specified file + path. In the case that this is executed on a domain controller, + this method will grant access explicitly to Local Service and + Network Service instead. + +Arguments: + + pszFilePath - The path where access is granted + dwAccessMask - Desired access to grant + dwInhertiance - Inheritance for access mask + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + DWORD cExplicitAccess = 1; + PSID pSidUserAccount = NULL; + DWORD cbUserAccount = 0; + EXPLICIT_ACCESS rgExplicitAccess[ 1 ]; + + if ( pszFilePath == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Finished; + } + + // Zero out the struct + ZeroMemory( &(rgExplicitAccess[0]), sizeof( EXPLICIT_ACCESS ) ); + + // Get the SID for IIS_IUSRS + if ( CreateWellKnownSid( WinBuiltinIUsersSid, + NULL, // DomainSid + pSidUserAccount, + &cbUserAccount ) ) + { + // + // We are expecing a FALSE return value since we + // are obtaining required buffer sizes. + // + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + + hr = HRESULT_FROM_WIN32( GetLastError() ); + if ( hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) ) + { + goto Finished; + } + hr = S_OK; + + pSidUserAccount = (PSID) LocalAlloc( LPTR, cbUserAccount ); + if ( pSidUserAccount == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + goto Finished; + } + + if ( !CreateWellKnownSid( WinBuiltinIUsersSid, + NULL, // DomainSid + pSidUserAccount, + &cbUserAccount ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + + // Build TRUSTEE with the IIS_IUSRS SID + BuildTrusteeWithSid( &(rgExplicitAccess[0].Trustee), pSidUserAccount ); + rgExplicitAccess[0].grfAccessPermissions = dwAccessMask; + rgExplicitAccess[0].grfAccessMode = GRANT_ACCESS; + rgExplicitAccess[0].grfInheritance = dwInheritance; + + // Add access to file DACL + hr = AddExplicitAccessToFileDacl( pszFilePath, + cExplicitAccess, + rgExplicitAccess ); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + return hr; +} + +HRESULT +GetStringSddlFromFile( + __in LPWSTR pszFileName, + __out STRU & strFileSddl, + __in BOOL fCreateIfDoesNotExist +) +/*++ + +Routine Description: + + Returns the DACL in the format SDDL for the + specified file or directory. + +Arguments: + + pszFileName - The file or directory path from to get the DACL. + strFileSddl - The file's security descriptor as string. + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + DWORD dwResult = ERROR_SUCCESS; + PACL pFileObjectAcl = NULL; + PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; + LPWSTR pszSddl = NULL; + ULONG cchSddlLen = 0; + + if ( fCreateIfDoesNotExist ) + { + hr = CreateDirectory( pszFileName ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + } + + dwResult = GetNamedSecurityInfo( + pszFileName, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, + NULL, + &pFileObjectAcl, + NULL, + &pSecurityDescriptor ); + if ( dwResult != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwResult ); + DBGERROR_HR( hr ); + goto Finished; + } + + if ( ! ConvertSecurityDescriptorToStringSecurityDescriptor( + pSecurityDescriptor, + SDDL_REVISION_1, + DACL_SECURITY_INFORMATION, + &pszSddl, + &cchSddlLen ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + + hr = strFileSddl.Copy( pszSddl ); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + if ( pSecurityDescriptor != NULL ) + { + LocalFree( pSecurityDescriptor ); + pSecurityDescriptor = NULL; + } + + if ( pszSddl != NULL ) + { + LocalFree( pszSddl ); + pszSddl = NULL; + } + + return hr; +} + +VOID +FreeStringSids( + __in DWORD cStringSids, + __in_bcount(cStringSids) LPWSTR rgszStringSids[] +) +/*++ + +Routine Description: + + Frees the memory allocated by ConvertAccountNamesToStringSids. + +Arguments: + + cStringSids - The number of string in the array rgszStringSids. + rgszStringSids - An array of SIDs represented as string. + +Return Value: + + HRESULT + +--*/ +{ + if ( rgszStringSids == NULL ) + { + return; + } + + for ( DWORD dwIndex = 0; dwIndex < cStringSids; dwIndex ++ ) + { + LocalFree( rgszStringSids [ dwIndex ] ); + } + + LocalFree ( rgszStringSids ); +} + +HRESULT +ConvertAccountNamesToStringSids ( + __in DWORD dwNameCount, + __in_ecount(dwNameCount) LPWSTR rgszNames[], + __deref_out_ecount(*pcStringSids) LPWSTR** StringSids, + __out DWORD* pcStringSids +) +/*++ + +Routine Description: + + Converts a list of local users or groups to string SIDs. + The StringSids array must be freed via the FreeStringSids function + +Arguments: + + dwNameCount - Number of names to convert. + + rgszNames - Array of pointers to Domain\Member strings + + StringSids - Returns a pointer to an array of pointers to String SIDs. + The array should be freed via FreeStringSids. + + pcStringSids - The number of String SIDs translated. + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + NTSTATUS ntStatus = ERROR_SUCCESS; + LSA_HANDLE hPolicy = NULL; + LSA_OBJECT_ATTRIBUTES ObjectAttributes = {0}; + PUNICODE_STRING pUnicodeNames = NULL; + PLSA_REFERENCED_DOMAIN_LIST pReferencedDomainList = NULL; + PLSA_TRANSLATED_SID2 pTranslatedSid = NULL; + SIZE_T cchLength = 0; + LPWSTR * rgszStringSids = NULL; + DWORD cStringSids = 0; + DWORD dwStringIndex = 0; + + HMODULE hModule = NULL; + + typedef NTSTATUS + (NTAPI * PFN_LSALOOKUPNAMES2) ( + __in LSA_HANDLE PolicyHandle, + __in ULONG Flags, // Reserved + __in ULONG Count, + __in PLSA_UNICODE_STRING Names, + __out PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + __out PLSA_TRANSLATED_SID2 *Sids + ); + + PFN_LSALOOKUPNAMES2 pfn = NULL; + + hModule = LoadLibrary( L"Advapi32.dll" ); + if ( hModule == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + + pfn = ( PFN_LSALOOKUPNAMES2 ) GetProcAddress( hModule, "LsaLookupNames2" ); + if ( pfn == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + if ( hr == HRESULT_FROM_WIN32( ERROR_PROC_NOT_FOUND ) ) + { + // + // This must be an OS before Windows 2003. + // + hr = S_OK; + } + goto Finished; + } + + // + // Open the local LSA database + // + ntStatus = LsaOpenPolicy( NULL, // Open the local policy + &ObjectAttributes, + POLICY_LOOKUP_NAMES, + &hPolicy ) ; + + if ( !NT_SUCCESS( ntStatus ) ) + { + hr = HRESULT_FROM_NT( ntStatus ); + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Convert the names to unicode strings + // + pUnicodeNames = (PUNICODE_STRING) LocalAlloc( + LMEM_FIXED, + sizeof(UNICODE_STRING) * dwNameCount ); + + if ( pUnicodeNames == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto Finished; + } + + for ( DWORD dwIndex = 0; dwIndex < dwNameCount; dwIndex++ ) + { + cchLength = wcslen( rgszNames[dwIndex] ) * sizeof( *rgszNames[dwIndex] ); + if ( ( cchLength + sizeof( UNICODE_NULL ) ) > USHRT_MAX ) + { + hr = HRESULT_FROM_WIN32 ( ERROR_ARITHMETIC_OVERFLOW ); + goto Finished; + } + + pUnicodeNames[dwIndex].Buffer = rgszNames[dwIndex]; + pUnicodeNames[dwIndex].Length = ( USHORT ) cchLength; + pUnicodeNames[dwIndex].MaximumLength = ( USHORT ) ( cchLength + sizeof( UNICODE_NULL ) ); + } + + // + // Convert the names to sids + // + ntStatus = (*pfn) ( hPolicy, + 0, // Flags + dwNameCount, + pUnicodeNames, + &pReferencedDomainList, + &pTranslatedSid ); + + if ( !NT_SUCCESS( ntStatus ) ) + { + hr = HRESULT_FROM_WIN32( ntStatus ); + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Some of the names could not be translated. + // This is an informational-level return value. + // + if ( ntStatus == STATUS_SOME_NOT_MAPPED ) + { + hr = HRESULT_FROM_WIN32( ntStatus ); + DBGERROR_HR( hr ); + hr = S_OK; + } + + // + // Count the number of SIDs retrieved + // + for ( DWORD dwIndex = 0; dwIndex < dwNameCount; dwIndex++ ) + { + if ( pTranslatedSid[dwIndex].Sid != NULL ) + { + cStringSids ++; + } + } + + // + // Allocate the SID list to return + // + rgszStringSids = (LPWSTR *) LocalAlloc( + LMEM_FIXED, + sizeof( LPWSTR ) * cStringSids ); + + if ( rgszStringSids == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Construct a string SID for each name + // + dwStringIndex = 0; + for ( DWORD dwIndex = 0; dwIndex < dwNameCount; dwIndex++ ) + { + if ( pTranslatedSid[dwIndex].Sid != NULL ) + { + if ( ! ConvertSidToStringSid( + pTranslatedSid [dwIndex].Sid, + &rgszStringSids [dwStringIndex] ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + dwStringIndex ++; + } + } + +Finished: + + if ( pUnicodeNames != NULL ) + { + LocalFree( pUnicodeNames ); + pUnicodeNames = NULL; + } + + if ( pReferencedDomainList != NULL ) + { + LsaFreeMemory( pReferencedDomainList ); + pReferencedDomainList = NULL; + } + + if ( pTranslatedSid != NULL ) + { + LsaFreeMemory( pTranslatedSid ); + pTranslatedSid = NULL; + } + + if ( hPolicy != NULL ) + { + LsaClose( hPolicy ); + hPolicy = NULL; + } + + // + // If the translation wasn't successful, + // free any partial translation. + // + + if ( FAILED( hr ) ) + { + if ( rgszStringSids != NULL ) + { + FreeStringSids( cStringSids, rgszStringSids ); + rgszStringSids = NULL; + } + } + + // + // Assign the output parameters + // + (*StringSids) = rgszStringSids; + (*pcStringSids) = cStringSids; + + if ( hModule != NULL ) + { + FreeLibrary( hModule ); + hModule = NULL; + } + + return hr; +} + +HRESULT +SetFileSddl( + __in LPCWSTR pszSddl, + __in LPWSTR pszPath +) +{ + HRESULT hr = S_OK; + SECURITY_ATTRIBUTES sa = { 0 }; + DWORD status = 0; + BOOL fIsVistaOrGreater = FALSE; + + sa.nLength = sizeof( sa ); + sa.bInheritHandle = FALSE; + if ( ! ConvertStringSecurityDescriptorToSecurityDescriptor( + pszSddl, + SDDL_REVISION_1, + &sa.lpSecurityDescriptor, + NULL)) + { + hr = HRESULT_FROM_WIN32 ( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + + hr = IsVistaOrGreater ( fIsVistaOrGreater ); + if ( FAILED(hr) ) + { + fIsVistaOrGreater = FALSE; + hr = S_OK; + } + + if ( fIsVistaOrGreater ) + { + status = SetNamedSecurityInfo( pszPath, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, + NULL, + (PACL) sa.lpSecurityDescriptor, + NULL ); + if ( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32 (status ); + DBGERROR_HR( hr ); + goto Finished; + } + } + else + { + if ( ! SetFileSecurity( pszPath, + DACL_SECURITY_INFORMATION, + (PSECURITY_DESCRIPTOR) sa.lpSecurityDescriptor ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + } + + +Finished: + + if ( sa.lpSecurityDescriptor != NULL ) + { + LocalFree( sa.lpSecurityDescriptor ); + sa.lpSecurityDescriptor = NULL; + } + + return hr; +} + +HRESULT +GetIISWPGSid( + __out STRU & strIISWPGSid +) +{ + HRESULT hr = S_OK; + LPWSTR* ppszStringSids = NULL; + DWORD cStringSids = 0; + + LPWSTR rgszIisAccountsToResolve [] = { L"IIS_WPG" }; + + hr = ConvertAccountNamesToStringSids( _countof( rgszIisAccountsToResolve ), + rgszIisAccountsToResolve, + &ppszStringSids, + &cStringSids ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + if ( cStringSids < 1 ) + { + hr = E_INVALIDARG; + goto Finished; + } + + hr = strIISWPGSid.Copy( ppszStringSids[0] ); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + if ( ppszStringSids != NULL ) + { + FreeStringSids( cStringSids, ppszStringSids ); + ppszStringSids = NULL; + } + + return hr; +} + +ULONG +GetRealAclSize( + __in PACL Acl + ) +/*++ + +Routine Description: + + Walks the sids in an ACL to determine it's minimum size + +Arguments: + + Acl - Acl to scan + +Return Value: + + Byte count + +--*/ +{ + PACE_HEADER Ace = FirstAce( Acl ); + int i = 0; + while (i < Acl->AceCount ) { + i++; + Ace = NextAce( Ace ); + } + + return (ULONG) ((PBYTE) Ace - (PBYTE) Acl); + +} + +HRESULT +MakeAutoInheritFromParent( + __in LPWSTR pszPath +) +{ + HRESULT hr = S_OK; + DWORD dwError; + PACL Acl; + PACE_HEADER Ace; + PSECURITY_DESCRIPTOR pSecurityDescriptor; + SECURITY_INFORMATION SecurityInfo = DACL_SECURITY_INFORMATION; + + // + // Get the current file DACL + // + dwError = GetNamedSecurityInfo( pszPath, + SE_FILE_OBJECT, + SecurityInfo, + NULL, + NULL, + &Acl, + NULL, + &pSecurityDescriptor ); + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Remove all the ACEs + // + Ace = FirstAce( Acl ); + int i = 0; + while ( i < Acl->AceCount ) + { + // + // The Ace was not inherited + // + if( (Ace->AceFlags & INHERITED_ACE) == 0 ) + { + if (!DeleteAce( Acl, i )) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + } + else + { + i++; + Ace = NextAce( Ace ); + } + } + Acl->AclSize = (WORD) GetRealAclSize( Acl ); + + // + // Auto-inherit + // + SecurityInfo |= UNPROTECTED_DACL_SECURITY_INFORMATION; + + dwError = SetNamedSecurityInfo( pszPath, + SE_FILE_OBJECT, + SecurityInfo, + NULL, + NULL, + Acl, + NULL ); + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + DBGERROR_HR( hr ); + goto Finished; + } + +Finished: + + if ( pSecurityDescriptor != NULL ) + { + LocalFree( pSecurityDescriptor ); + pSecurityDescriptor = NULL; + } + + return hr; +} + +HRESULT +GrantIISWPGReadWritePermissions( + __in LPWSTR pszPath +) +{ + HRESULT hr = S_OK; + STACK_STRU( strAces, 128 ); + STACK_STRU( strFileSddl, 128 ); + STACK_STRU( strFileSddlTemp, 128 ); + STACK_STRU( strIISWPGSid, 32 ); + + hr = GetStringSddlFromFile( pszPath, + strFileSddlTemp ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + hr = GetIISWPGSid( strIISWPGSid ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + if ( hr == STATUS_NONE_MAPPED ) + { + // + // No maps found. + // + hr = S_OK; + } + goto Finished; + } + + // + // Add Read/Write permissions. + // + hr = strAces.Copy( L"(A;OICI;0x12019f;;;" ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = strAces.Append( strIISWPGSid ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = strAces.Append( L")", 1 ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + // + // Insert the ACE before any other ACE. + // + + // + // Search for the first ACE '(' + // + LPCWSTR psz = wcschr( strFileSddlTemp.QueryStr(), SDDL_ACE_BEGINC ); + + // + // Copy the first part before the first '(' + // + hr = strFileSddl.Append( strFileSddlTemp.QueryStr(), + (DWORD)(psz - strFileSddlTemp.QueryStr()) ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Copy the new ACE + // + hr = strFileSddl.Append( strAces ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Copy the other ACEs. + // + hr = strFileSddl.Append( psz ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + hr = SetFileSddl( strFileSddl.QueryStr(), + pszPath ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + +Finished: + + return hr; +} + +HRESULT +SetupAclsWow64( + LPCWSTR pwszPath +) +{ + HRESULT hr = S_OK; + HMODULE hModule = NULL; + STACK_STRU( strPath, MAX_PATH ); + + typedef UINT + (WINAPI *PFN_GETSYSTEMWOW64DIRECTORY) + ( + __out LPTSTR lpBuffer, + __in UINT uSize + ); + + PFN_GETSYSTEMWOW64DIRECTORY pfn; + + hModule = LoadLibrary( L"kernel32.dll" ); + if ( hModule == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + pfn = ( PFN_GETSYSTEMWOW64DIRECTORY ) GetProcAddress( hModule, "GetSystemWow64DirectoryW" ); + if ( pfn == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + if ( hr == HRESULT_FROM_WIN32( ERROR_PROC_NOT_FOUND ) ) + { + // + // This must be an OS before Windows 2003. + // + hr = S_OK; + } + goto Finished; + } + + if ( ! (*pfn)( strPath.QueryStr(), + strPath.QuerySizeCCH() ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + if ( hr == HRESULT_FROM_WIN32( ERROR_CALL_NOT_IMPLEMENTED ) ) + { + // + // This is not Win64. + // + hr = S_OK; + } + else + { + DBGERROR_HR( hr ); + } + goto Finished; + } + strPath.SyncWithBuffer(); + + if (pwszPath != NULL) + { + hr = strPath.Append( pwszPath ); + if ( FAILED( hr ) ) + { + goto Finished; + } + } + + hr = MakeAutoInheritFromParent( strPath.QueryStr() ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + +Finished: + + if ( hModule != NULL ) + { + FreeLibrary( hModule ); + hModule = NULL; + } + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.h new file mode 100644 index 0000000000..416ffd369c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.h @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +HRESULT +IsVistaOrGreater( + __out BOOL & fIsVistaOrGreater +); + +HRESULT +CreateDirectory( + __in LPCWSTR pszFileName +); + +HRESULT +AddExplicitAccessToFileDacl( + __in LPWSTR pszFilePath, + DWORD cExplicitAccess, + EXPLICIT_ACCESS rgExplicitAccess[] +); + +HRESULT +GrantFileAccessToIisIusrs( + __in LPWSTR pszFilePath, + DWORD dwAccessMask, + DWORD dwInheritance +); + +HRESULT +GetStringSddlFromFile( + __in LPWSTR pszFileName, + __out STRU & strFileSddl, + __in BOOL fCreateIfDoesNotExist = TRUE +); + +VOID +FreeStringSids( + __in DWORD cStringSids, + __in_bcount(cStringSids) LPWSTR rgszStringSids[] +); + +HRESULT +ConvertAccountNamesToStringSids ( + __in DWORD dwNameCount, + __in_ecount(dwNameCount) LPWSTR rgszNames[], + __deref_out_ecount(*pcStringSids) LPWSTR** StringSids, + __out DWORD* pcStringSids +); + +HRESULT +SetFileSddl( + __in LPCWSTR pszSddl, + __in LPWSTR pszPath +); + +HRESULT +GetIISWPGSid( + __out STRU & strIISWPGSid +); + +inline PACE_HEADER +FirstAce( __in PACL Acl ) +{ + return (PACE_HEADER)(((PBYTE)Acl) + sizeof( ACL )); +} + +inline PACE_HEADER +NextAce( __in PACE_HEADER Ace ) +{ + return (PACE_HEADER)(((PBYTE)Ace) + Ace->AceSize ); +} + +inline PSID +SidFromAce( __in PACE_HEADER Ace ) +{ + return (PSID)&((PACCESS_ALLOWED_ACE)Ace)->SidStart; +} + +ULONG +GetRealAclSize( + __in PACL Acl +); + + +HRESULT +MakeAutoInheritFromParent( + __in LPWSTR pszPath +); + +HRESULT +GrantIISWPGReadWritePermissions( + __in LPWSTR pszPath +); + +HRESULT +SetupAclsWow64( + LPCWSTR pwszPath +); + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.cpp new file mode 100644 index 0000000000..86a8857096 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.cpp @@ -0,0 +1,423 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" +#include "ntassert.h" +// +// SETUP_LOG class, used only by MsiLogXXX functions not used directly by CA code +// +class SETUP_LOG +{ + +public: + + SETUP_LOG( + VOID + ) + { + _severityThreshold = SETUP_LOG_SEVERITY_INFORMATION; + } + + ~SETUP_LOG( + VOID + ) + { + } + + VOID + Initialize( + IN MSIHANDLE hInstall, + IN LPCWSTR pszCAName + ); + + VOID + Close( + VOID + ); + + VOID + Write( + IN CONST SETUP_LOG_SEVERITY setupLogSeverity, + IN LPCWSTR pszLogMessageFormat + ); + +private: + + MSIHANDLE _hInstall; + SETUP_LOG_SEVERITY _severityThreshold; + STRU _strSCANamePrefix; + +private: + HRESULT + WriteMSIMessage( + IN STRU * pstrLogMessage + ); + + HRESULT + SETUP_LOG::FmtCAName( + IN STRU * pstrFmtCAName + ); +}; + + +VOID +SETUP_LOG::Initialize( + IN MSIHANDLE hInstall, + IN LPCWSTR pszCAName + ) +/*++ + +Routine Description: + + Initialization. Opens handle to the log file and writes a message. + +Return Value: + + HRESULT + +--*/ +{ + STACK_STRU ( strMsiRegKey, 64 ); + STACK_STRU ( strStartLogMessage, MAX_PATH ); + STACK_STRU ( strMsiLoggingValue, 32 ); + DWORD dwBufLen = strMsiRegKey.QuerySizeCCH(); + DWORD status = ERROR_SUCCESS; + HKEY hKey = NULL; + + //for checking logging level + WORD i; + + // + //Set MSI handle & CA name + // + + _hInstall = hInstall; + + // + //Prefix message with CAname + // + _strSCANamePrefix.Copy( L"IISCA " ); + _strSCANamePrefix.Append( pszCAName ); + _strSCANamePrefix.Append( L" : " ); + + // + //test MsiLogging property MSI 4.0+ + // + + (VOID) MsiUtilGetProperty( hInstall, L"MsiLogging", &strMsiLoggingValue ); + + if( !strMsiLoggingValue.IsEmpty() ) + { + WCHAR * szValueBuf = strMsiLoggingValue.QueryStr(); + if( wcschr( szValueBuf, L'v' ) || wcschr( szValueBuf, L'V' ) ) + { + _severityThreshold = SETUP_LOG_SEVERITY_DEBUG ; + } + } + + if ( _severityThreshold != SETUP_LOG_SEVERITY_DEBUG ) + { + // + // Last chance - check Logging Registry Key/value + // + + status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer", + 0, + KEY_QUERY_VALUE, + &hKey ); + + if ( status == ERROR_SUCCESS ) + { + status = RegQueryValueEx( hKey, + L"Logging", + NULL, + NULL, + (LPBYTE) strMsiRegKey.QueryStr(), + &dwBufLen); + + strMsiRegKey.SyncWithBuffer( ); + } + + if ( !( status != ERROR_SUCCESS ) || ( dwBufLen > strMsiRegKey.QuerySizeCCH() ) ) + { + // + //Have Logging key Value.. we will log something + // + // Check logging flags for verbosity 'v' + // + for ( i = 0; i < strMsiRegKey.QueryCCH() ; i++ ) + { + if ( strMsiRegKey.QueryStr()[ i ] == L'V' || strMsiRegKey.QueryStr()[ i ] == L'v' ) + { + _severityThreshold = SETUP_LOG_SEVERITY_DEBUG ; + break; + } + } + } + } + + // + // write the start message, prifix message with CAname + // + strStartLogMessage.Append( _strSCANamePrefix.QueryStr() ); + + strStartLogMessage.Append( L"Begin CA Setup" ); + + // + // write the message + // + + WriteMSIMessage( &strStartLogMessage ); + + + if ( hKey != NULL ) + { + RegCloseKey( hKey ); + hKey = NULL; + } + + return; +} + +VOID +SETUP_LOG::Close( + VOID + ) + +{ + STACK_STRU ( strEndLogMessage, MAX_PATH ); + + strEndLogMessage.Append( _strSCANamePrefix.QueryStr() ); + strEndLogMessage.Append( L"End CA Setup" ); + + // + // write the message + // + + WriteMSIMessage( &strEndLogMessage); + + return; +} + +VOID +SETUP_LOG::Write( + IN SETUP_LOG_SEVERITY setupLogSeverity, + IN LPCWSTR pszLogMessage + ) +/*++ + +Routine Description: + + Write a formatted message to the log file. Note that the message + will not be written to the log file if the severity is below that + of the current threshold. + +Arguments: + + setupLogSeverity - Severity of the message + pszLogMessageFormat - Format of the log message + +--*/ +{ + STACK_STRU ( struLogMessage, MAX_PATH ); + + DBG_ASSERT( pszLogMessage); + + if ( pszLogMessage == NULL ) + { + goto Exit; + } + + // + // If this message does not have high enough severity, we are done. + // + if ( setupLogSeverity < _severityThreshold ) + { + goto Exit; + } + + // + //Prefix message with CAname + // + + struLogMessage.Append( _strSCANamePrefix.QueryStr() ); + + // + // Prefix the high severity messages so we can easily spot errors. + // + + if ( setupLogSeverity == SETUP_LOG_SEVERITY_WARNING ) + { + struLogMessage.Append( L"< WARNING! > " ); + } + else if ( setupLogSeverity == SETUP_LOG_SEVERITY_ERROR ) + { + struLogMessage.Append( L"< !!ERROR!! > " ); + } + + struLogMessage.Append( pszLogMessage ); + + // + // Write to the log file + // + + WriteMSIMessage( &struLogMessage ); + +Exit: + + return; +} + +HRESULT +SETUP_LOG::WriteMSIMessage( + STRU * pstrLogMessage + ) + +{ + HRESULT hr = S_OK; + PMSIHANDLE msiRow; + UINT status = 0; + // + // get an MSI record + // + + //consider passing a parameterized string here + msiRow = MsiCreateRecord( 1 ); + if ( msiRow == NULL ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto Exit; + } + + // + // put message in msi record + // + + status = MsiRecordSetStringW( msiRow, 1, (LPCWSTR)pstrLogMessage->QueryStr() ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto Exit; + } + + // + // send message to MSI log file + // + + status = MsiProcessMessage( _hInstall, INSTALLMESSAGE_INFO, msiRow ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto Exit; + } + +Exit: + + return hr; +} + +// +//Use static global instance of SETUP_LOG class +// +static SETUP_LOG * g_pSetupLog = NULL; + +// +//MSI Log safe functions, used directly by CA code +// +VOID +IISLogInitialize( + IN MSIHANDLE hInstall, + IN LPCWSTR pszCAName + ) +{ + HRESULT hr = S_OK; + + //debug assert that it is always null. becaues previous custom action should have cleaned it up + DBG_ASSERT( g_pSetupLog == NULL ); + + if ( g_pSetupLog == NULL ) + { + g_pSetupLog = new SETUP_LOG(); + if ( g_pSetupLog == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + DBGERROR_HR(hr); + goto Exit; + } + } + + // + // init + // + + g_pSetupLog->Initialize( hInstall, pszCAName ); + +Exit: + return; +} + + +VOID +IISLogClose( + VOID + ) +{ + if ( !g_pSetupLog ) + { + goto Exit; + } + + // + // do the call + // + + g_pSetupLog->Close(); + + // + //Done with SETUP_LOG instance + // + + delete g_pSetupLog; + g_pSetupLog = NULL; + +Exit: + + return ; +} + + +VOID +IISLogWrite( + IN SETUP_LOG_SEVERITY setupLogSeverity, + IN LPCWSTR pszLogMessageFormat, + ... + ) +{ + va_list argsList; + va_start ( argsList, pszLogMessageFormat ); + + STACK_STRU ( struLogMessage, 128 ); + //debug assert that it is not null + DBG_ASSERT( g_pSetupLog ); + + if ( !g_pSetupLog ) + { + goto Exit; + } + + // + // Form struLogMessage so that we can write a single string + // + + struLogMessage.SafeVsnwprintf( pszLogMessageFormat, argsList ); + + g_pSetupLog->Write( setupLogSeverity, struLogMessage.QueryStr() ); + +Exit: + va_end ( argsList ); + return; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.h new file mode 100644 index 0000000000..848fe4d0a3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.h @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _SETUP_LOG_H_ +#define _SETUP_LOG_H_ + + +// +// Severity levels for setup log information. This is arranged in the +// order of increasing severity. +// +enum SETUP_LOG_SEVERITY +{ + SETUP_LOG_SEVERITY_DEBUG, + SETUP_LOG_SEVERITY_INFORMATION, + SETUP_LOG_SEVERITY_WARNING, + SETUP_LOG_SEVERITY_ERROR +}; + +//consider using an IIS prefix for Msi* methods - they conflict with MSI apis + +// +// Initalize logging once at begining of CA +// + +VOID +IISLogInitialize( + IN MSIHANDLE hInstall, + IN LPCWSTR pszCAName + ); + +// +// Close logging at end / exit of CA +// + +VOID +IISLogClose( + VOID + ); + +// +// Writes a message to msi log file +// +VOID +IISLogWrite( + IN SETUP_LOG_SEVERITY setupLogSeverity, + IN LPCWSTR pszLogMessageFormat, + ... + ); + +#endif + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.cpp new file mode 100644 index 0000000000..a7e051b92e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.cpp @@ -0,0 +1,343 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +RegisterTraceArea( + IN CONST WCHAR * szTraceProviderName, + IN CONST WCHAR * szTraceProviderGuid, + IN CONST WCHAR * szAreaName, + IN CONST WCHAR * szAreaValue +) +{ + HRESULT hr = NOERROR; + CComPtr pAdminMgr; + CComPtr pTraceProviderSection; + CComPtr pTraceProvidersCollection; + CComPtr pTraceProvider; + CComPtr pAreasElement; + CComPtr pAreasCollection; + CComPtr pAreaElement; + + BSTR bstrAppHostConfigPath = SysAllocString( L"MACHINE/WEBROOT/APPHOST" ); + BSTR bstrTracingSection = SysAllocString( L"system.webServer/tracing/traceProviderDefinitions" ); + BSTR bstrAreas = SysAllocString( L"areas" ); + + NAME_VALUE_PAIR ProviderProperties[] = + { + { L"name", CComVariant( szTraceProviderName )}, + { L"guid", CComVariant( szTraceProviderGuid )} + }; + + NAME_VALUE_PAIR AreaProperties[] = + { + { L"name", CComVariant( szAreaName )}, + { L"value", CComVariant( szAreaValue )} + }; + + if ( bstrAppHostConfigPath == NULL || + bstrTracingSection == NULL || + bstrAreas == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrTracingSection, + bstrAppHostConfigPath, + &pTraceProviderSection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pTraceProviderSection->get_Collection( &pTraceProvidersCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetElementFromCollection( pTraceProvidersCollection, + L"name", + szTraceProviderName, + &pTraceProvider ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Create the trace provider if it doesn't exist. + // + if ( hr == S_FALSE ) + { + hr = AddElementToCollection( pTraceProvidersCollection, + L"add", + ProviderProperties, + _countof( ProviderProperties ), + &pTraceProvider ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = pTraceProvider->GetElementByName( bstrAreas, + &pAreasElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAreasElement->get_Collection( &pAreasCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetElementFromCollection( pAreasCollection, + L"name", + szAreaName, + &pAreaElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Add the trace area if it doesn't exist. + // + if ( hr != S_FALSE ) + { + hr = S_OK; + goto exit; + } + + hr = AddElementToCollection( pAreasCollection, + L"add", + AreaProperties, + _countof( AreaProperties ), + NULL ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrTracingSection ); + SysFreeString( bstrAreas ); + + return hr; +} + +HRESULT +AddElementToCollection( + IN IAppHostElementCollection * pCollection, + IN CONST WCHAR * pElementName, + IN NAME_VALUE_PAIR rgProperties[], + IN DWORD cProperties, + OUT IAppHostElement ** ppElement +) +{ + HRESULT hr = NOERROR; + CComPtr pElement; + CComPtr pProperty; + + BSTR bstrName = NULL; + BSTR bstrElementName = SysAllocString( pElementName ); + + if ( bstrElementName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pCollection->CreateNewElement( bstrElementName, + &pElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for ( DWORD Index = 0; Index < cProperties; Index ++ ) + { + bstrName = SysAllocString( rgProperties[Index].Name ); + if ( bstrName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrName, + &pProperty ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( rgProperties[Index].Value.vt == VT_ERROR ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pProperty->put_Value( rgProperties[Index].Value ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + SysFreeString( bstrName ); + pProperty.Detach()->Release(); + } + + hr = pCollection->AddElement( pElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( ppElement != NULL ) + { + *ppElement = pElement.Detach(); + } + +exit: + + SysFreeString( bstrElementName ); + SysFreeString( bstrName ); + + return hr; +} + +HRESULT +GetElementFromCollection( + IN IAppHostElementCollection * pCollection, + IN CONST WCHAR * szIndex, + IN CONST WCHAR * szExpectedPropertyValue, + OUT IAppHostElement ** ppElement, + OUT DWORD * pIndex +) +{ + HRESULT hr = NOERROR; + DWORD dwElementCount = 0; + CComPtr pElement; + CComPtr pProperty; + + BSTR bstrPropertyName = SysAllocString( szIndex ); + + if ( bstrPropertyName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pCollection->get_Count( &dwElementCount ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for ( DWORD Index = 0; Index < dwElementCount; Index ++ ) + { + CComVariant value; + + hr = pCollection->get_Item( CComVariant( Index ), + &pElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrPropertyName, + &pProperty ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pProperty->get_Value( &value ); + if ( value.vt == VT_ERROR ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + if ( value.vt != VT_BSTR ) + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + DBGERROR_HR(hr); + goto exit; + } + + if ( _wcsicmp( value.bstrVal, szExpectedPropertyValue ) == 0 ) + { + // + // Element found. + // + *ppElement = pElement.Detach(); + if ( pIndex != NULL ) + { + *pIndex = Index; + } + hr = S_OK; + goto exit; + } + + pProperty.Detach()->Release(); + pElement.Detach()->Release(); + } + + // + // Element not found. + // + hr = S_FALSE; + +exit: + + SysFreeString( bstrPropertyName ); + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.h new file mode 100644 index 0000000000..087e8ded74 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +HRESULT +RegisterTraceArea( + IN CONST WCHAR * szTraceProviderName, + IN CONST WCHAR * szTraceProviderGuid, + IN CONST WCHAR * szAreaName, + IN CONST WCHAR * szAreaValue +); + +HRESULT +GetElementFromCollection( + IN IAppHostElementCollection * pCollection, + IN CONST WCHAR * szPropertyName, + IN CONST WCHAR * szExpectedPropertyValue, + OUT IAppHostElement ** ppElement, + OUT DWORD * pIndex = NULL +); + +struct NAME_VALUE_PAIR +{ + LPCWSTR Name; + CComVariant Value; +}; + +HRESULT +AddElementToCollection( + IN IAppHostElementCollection * pCollection, + IN CONST WCHAR * pElementName, + IN NAME_VALUE_PAIR rgProperties[], + IN DWORD cProperties, + OUT IAppHostElement ** ppElement +); diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/uimodule.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/uimodule.cpp new file mode 100644 index 0000000000..76adb89ca6 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/uimodule.cpp @@ -0,0 +1,637 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +class ADMINISTRATION_CONFIG_PATH_MAPPER : public IAppHostPathMapper +{ + +public: + + ADMINISTRATION_CONFIG_PATH_MAPPER( + VOID + ) : _cRefs( 1 ) + { + } + + ~ADMINISTRATION_CONFIG_PATH_MAPPER( + VOID + ) + { + } + + HRESULT + Initialize() + { + // TODO this could be more reliable. + HRESULT hr = NOERROR; + DWORD cch; + + cch = ExpandEnvironmentStringsW( + L"%windir%\\system32\\inetsrv\\config\\administration.config", + _strMappedPath.QueryStr(), + _strMappedPath.QuerySizeCCH() + ); + if( !cch ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto exit; + } + + if( cch > _strMappedPath.QuerySizeCCH() ) + { + hr = _strMappedPath.Resize( cch ); + if( FAILED(hr) ) + { + goto exit; + } + + cch = ExpandEnvironmentStringsW( + L"%windir%\\system32\\inetsrv\\config\\administration.config", + _strMappedPath.QueryStr(), + _strMappedPath.QuerySizeCCH() + ); + if( !cch || + cch > _strMappedPath.QuerySizeCCH() ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto exit; + } + } + + _strMappedPath.SyncWithBuffer(); + + exit: + + return hr; + + } + + ULONG + STDMETHODCALLTYPE + AddRef( + VOID + ) + { + return InterlockedIncrement( &_cRefs ); + } + + ULONG + STDMETHODCALLTYPE + Release( + VOID + ) + { + ULONG ulRet = 0; + + ulRet = InterlockedDecrement( &_cRefs ); + + if ( ulRet == 0 ) + { + delete this; + } + return ulRet; + } + + HRESULT + STDMETHODCALLTYPE + QueryInterface( + REFIID riid, + void ** ppObject + ) + { + if ( riid == __uuidof(IUnknown) || + riid == __uuidof(IAppHostPathMapper) ) + { + AddRef(); + *ppObject = (IAppHostPathMapper*) this; + return S_OK; + } + else + { + *ppObject = NULL; + return E_NOINTERFACE; + } + } + + HRESULT + STDMETHODCALLTYPE + MapPath( + BSTR bstrConfigPath, + BSTR bstrMappedPhysicalPath, + BSTR * pbstrNewPhysicalPath + ) + { + BSTR bstrNewPhysicalPath = NULL; + + if ( wcscmp( bstrConfigPath, L"MACHINE/WEBROOT" ) == 0 ) + { + bstrNewPhysicalPath = SysAllocString( _strMappedPath.QueryStr() ); + } + else + { + bstrNewPhysicalPath = SysAllocString( bstrMappedPhysicalPath ); + } + + if ( bstrNewPhysicalPath == NULL ) + { + return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + } + + *pbstrNewPhysicalPath = bstrNewPhysicalPath; + return S_OK; + } + +private: + + LONG _cRefs; + STRU _strMappedPath; +}; + +HRESULT +InitAdminMgrForAdminConfig( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szCommitPath + ) +{ + HRESULT hr = NOERROR; + + VARIANT varPathMapper; + VariantInit( &varPathMapper ); + + BSTR bstrPathMapperName = SysAllocString( L"pathMapper" ); + BSTR bstrCommitPath = SysAllocString( szCommitPath ); + + ADMINISTRATION_CONFIG_PATH_MAPPER * pPathMapper = NULL; + + if( !bstrPathMapperName || !bstrCommitPath) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->put_CommitPath( bstrCommitPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pPathMapper = new ADMINISTRATION_CONFIG_PATH_MAPPER(); + if( !pPathMapper ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pPathMapper->Initialize(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + varPathMapper.vt = VT_UNKNOWN; + varPathMapper.punkVal = pPathMapper; + pPathMapper = NULL; + + hr = pAdminMgr->SetMetadata( bstrPathMapperName, varPathMapper ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrPathMapperName ); + SysFreeString( bstrCommitPath ); + + VariantClear( &varPathMapper ); + + if( pPathMapper ) + { + pPathMapper->Release(); + pPathMapper = NULL; + } + + return hr; +} + + +HRESULT +RegisterUIModule( + IN CONST WCHAR * szModuleName, + IN CONST WCHAR * szModuleTypeInfo, + IN OPTIONAL CONST WCHAR * szRegisterInModulesSection, + IN OPTIONAL CONST WCHAR * szPrependToList + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pProvidersSection; + CComPtr pProvidersCollection; + CComPtr pNewModuleElement; + CComPtr pModulesSection; + CComPtr pModulesCollection; + CComPtr pModulesCollectionElement; + + VARIANT varValue; + VariantInit( &varValue ); + DWORD dwIndex; + BOOL fAddElement = FALSE; + INT cIndex; + + BSTR bstrCommitPath = SysAllocString( L"MACHINE/WEBROOT" ); + BSTR bstrModuleProvidersName = SysAllocString( L"moduleProviders" ); + BSTR bstrAdd = SysAllocString( L"add" ); + BSTR bstrModulesSectionName = SysAllocString( L"modules" ); + + if( !bstrCommitPath || + !bstrModuleProvidersName || + !bstrAdd || + !bstrModulesSectionName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = InitAdminMgrForAdminConfig( pAdminMgr, + bstrCommitPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrModuleProvidersName, + bstrCommitPath, + &pProvidersSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pProvidersSection->get_Collection( &pProvidersCollection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = FindElementInCollection( + pProvidersCollection, + L"name", + szModuleName, + FIND_ELEMENT_CASE_SENSITIVE, + &dwIndex); + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (hr == S_OK) + { + VARIANT vtIndex; + vtIndex.vt = VT_UI4; + vtIndex.ulVal = dwIndex; + + hr = pProvidersCollection->get_Item( + vtIndex, + &pNewModuleElement); + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + } + else + { + hr = pProvidersCollection->CreateNewElement( bstrAdd, + &pNewModuleElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + fAddElement = TRUE; + } + + hr = VariantAssign( &varValue, szModuleName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"name", + &varValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varValue, szModuleTypeInfo ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"type", + &varValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if (fAddElement) + { + cIndex = -1; + if (szPrependToList && *szPrependToList) + { + cIndex = 0; + } + + hr = pProvidersCollection->AddElement( pNewModuleElement, + cIndex ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if( szRegisterInModulesSection && *szRegisterInModulesSection ) + { + // register global section + hr = pAdminMgr->GetAdminSection( bstrModulesSectionName, + bstrCommitPath, + &pModulesSection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pModulesSection->get_Collection( &pModulesCollection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pModulesCollection->CreateNewElement( bstrAdd, + &pModulesCollectionElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varValue, szModuleName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty( pModulesCollectionElement, + L"name", + &varValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + cIndex = -1; + if (szPrependToList && *szPrependToList) + { + cIndex = 0; + } + + hr = pModulesCollection->AddElement( pModulesCollectionElement, + cIndex ); + if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) + { + hr = S_OK; + } + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrCommitPath ); + SysFreeString( bstrModuleProvidersName ); + SysFreeString( bstrAdd ); + SysFreeString( bstrModulesSectionName ); + + VariantClear( &varValue ); + + return hr; +} + +HRESULT +UnRegisterUIModule( + IN CONST WCHAR * szModuleName, + IN CONST WCHAR * szModuleTypeInfo + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pProvidersSection; + CComPtr pProvidersCollection; + CComPtr pProviderElement; + CComPtr pModulesSection; + CComPtr pModulesCollection; + + BSTR bstrCommitPath = SysAllocString( L"MACHINE/WEBROOT" ); + BSTR bstrModuleProvidersName = SysAllocString( L"moduleProviders" ); + BSTR bstrModulesSectionName = SysAllocString( L"modules" ); + BSTR bstrType = NULL; + DWORD dwIndex; + + if( !bstrCommitPath || + !bstrModuleProvidersName || + !bstrModulesSectionName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = InitAdminMgrForAdminConfig( pAdminMgr, bstrCommitPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrModuleProvidersName, + bstrCommitPath, + &pProvidersSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pProvidersSection->get_Collection( &pProvidersCollection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + BOOL fProvidersDeleted = FALSE; + + hr = FindElementInCollection( + pProvidersCollection, + L"name", + szModuleName, + FIND_ELEMENT_CASE_SENSITIVE, + &dwIndex); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if (hr == S_OK) + { + VARIANT vtIndex; + vtIndex.vt = VT_UI4; + vtIndex.ulVal = dwIndex; + + hr = pProvidersCollection->get_Item( + vtIndex, + &pProviderElement); + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetElementStringProperty( + pProviderElement, + L"type", + &bstrType); + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (wcscmp(bstrType, szModuleTypeInfo) == 0) + { + hr = pProvidersCollection->DeleteElement(vtIndex); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + fProvidersDeleted = TRUE; + } + else + { + goto exit; + } + } + + // now remove from global section if present + hr = pAdminMgr->GetAdminSection( bstrModulesSectionName, + bstrCommitPath, + &pModulesSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pModulesSection->get_Collection( &pModulesCollection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + BOOL fModulesDeleted = FALSE; + hr = DeleteElementFromCollection( pModulesCollection, + L"name", + szModuleName, + FIND_ELEMENT_CASE_SENSITIVE, + &fModulesDeleted ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( fProvidersDeleted || fModulesDeleted ) + { + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + +exit: + + SysFreeString( bstrCommitPath ); + SysFreeString( bstrModuleProvidersName ); + SysFreeString( bstrModulesSectionName ); + SysFreeString( bstrType ); + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/wuerror.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/wuerror.h new file mode 100644 index 0000000000..a735af0cf7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/wuerror.h @@ -0,0 +1,2456 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +/*************************************************************************** +* * +* wuerror.mc -- error code definitions for Windows Update. * +* * +***************************************************************************/ +#ifndef _WUERROR_ +#define _WUERROR_ + +#if defined (_MSC_VER) && (_MSC_VER >= 1020) && !defined(__midl) +#pragma once +#endif + +#ifdef RC_INVOKED +#define _HRESULT_TYPEDEF_(_sc) _sc +#else // RC_INVOKED +#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc) +#endif // RC_INVOKED + + +/////////////////////////////////////////////////////////////////////////////// +// Windows Update Success Codes +/////////////////////////////////////////////////////////////////////////////// +// +// Values are 32 bit values laid out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// + + +// +// Define the severity codes +// + + +// +// MessageId: WU_S_SERVICE_STOP +// +// MessageText: +// +// Windows Update Agent was stopped successfully. +// +#define WU_S_SERVICE_STOP _HRESULT_TYPEDEF_(0x00240001L) + +// +// MessageId: WU_S_SELFUPDATE +// +// MessageText: +// +// Windows Update Agent updated itself. +// +#define WU_S_SELFUPDATE _HRESULT_TYPEDEF_(0x00240002L) + +// +// MessageId: WU_S_UPDATE_ERROR +// +// MessageText: +// +// Operation completed successfully but there were errors applying the updates. +// +#define WU_S_UPDATE_ERROR _HRESULT_TYPEDEF_(0x00240003L) + +// +// MessageId: WU_S_MARKED_FOR_DISCONNECT +// +// MessageText: +// +// A callback was marked to be disconnected later because the request to disconnect the operation came while a callback was executing. +// +#define WU_S_MARKED_FOR_DISCONNECT _HRESULT_TYPEDEF_(0x00240004L) + +// +// MessageId: WU_S_REBOOT_REQUIRED +// +// MessageText: +// +// The system must be restarted to complete installation of the update. +// +#define WU_S_REBOOT_REQUIRED _HRESULT_TYPEDEF_(0x00240005L) + +// +// MessageId: WU_S_ALREADY_INSTALLED +// +// MessageText: +// +// The update to be installed is already installed on the system. +// +#define WU_S_ALREADY_INSTALLED _HRESULT_TYPEDEF_(0x00240006L) + +// +// MessageId: WU_S_ALREADY_UNINSTALLED +// +// MessageText: +// +// The update to be removed is not installed on the system. +// +#define WU_S_ALREADY_UNINSTALLED _HRESULT_TYPEDEF_(0x00240007L) + +// +// MessageId: WU_S_ALREADY_DOWNLOADED +// +// MessageText: +// +// The update to be downloaded has already been downloaded. +// +#define WU_S_ALREADY_DOWNLOADED _HRESULT_TYPEDEF_(0x00240008L) + +/////////////////////////////////////////////////////////////////////////////// +// Windows Update Error Codes +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_NO_SERVICE +// +// MessageText: +// +// Windows Update Agent was unable to provide the service. +// +#define WU_E_NO_SERVICE _HRESULT_TYPEDEF_(0x80240001L) + +// +// MessageId: WU_E_MAX_CAPACITY_REACHED +// +// MessageText: +// +// The maximum capacity of the service was exceeded. +// +#define WU_E_MAX_CAPACITY_REACHED _HRESULT_TYPEDEF_(0x80240002L) + +// +// MessageId: WU_E_UNKNOWN_ID +// +// MessageText: +// +// An ID cannot be found. +// +#define WU_E_UNKNOWN_ID _HRESULT_TYPEDEF_(0x80240003L) + +// +// MessageId: WU_E_NOT_INITIALIZED +// +// MessageText: +// +// The object could not be initialized. +// +#define WU_E_NOT_INITIALIZED _HRESULT_TYPEDEF_(0x80240004L) + +// +// MessageId: WU_E_RANGEOVERLAP +// +// MessageText: +// +// The update handler requested a byte range overlapping a previously requested range. +// +#define WU_E_RANGEOVERLAP _HRESULT_TYPEDEF_(0x80240005L) + +// +// MessageId: WU_E_TOOMANYRANGES +// +// MessageText: +// +// The requested number of byte ranges exceeds the maximum number (2^31 - 1). +// +#define WU_E_TOOMANYRANGES _HRESULT_TYPEDEF_(0x80240006L) + +// +// MessageId: WU_E_INVALIDINDEX +// +// MessageText: +// +// The index to a collection was invalid. +// +#define WU_E_INVALIDINDEX _HRESULT_TYPEDEF_(0x80240007L) + +// +// MessageId: WU_E_ITEMNOTFOUND +// +// MessageText: +// +// The key for the item queried could not be found. +// +#define WU_E_ITEMNOTFOUND _HRESULT_TYPEDEF_(0x80240008L) + +// +// MessageId: WU_E_OPERATIONINPROGRESS +// +// MessageText: +// +// Another conflicting operation was in progress. Some operations such as installation cannot be performed twice simultaneously. +// +#define WU_E_OPERATIONINPROGRESS _HRESULT_TYPEDEF_(0x80240009L) + +// +// MessageId: WU_E_COULDNOTCANCEL +// +// MessageText: +// +// Cancellation of the operation was not allowed. +// +#define WU_E_COULDNOTCANCEL _HRESULT_TYPEDEF_(0x8024000AL) + +// +// MessageId: WU_E_CALL_CANCELLED +// +// MessageText: +// +// Operation was cancelled. +// +#define WU_E_CALL_CANCELLED _HRESULT_TYPEDEF_(0x8024000BL) + +// +// MessageId: WU_E_NOOP +// +// MessageText: +// +// No operation was required. +// +#define WU_E_NOOP _HRESULT_TYPEDEF_(0x8024000CL) + +// +// MessageId: WU_E_XML_MISSINGDATA +// +// MessageText: +// +// Windows Update Agent could not find required information in the update's XML data. +// +#define WU_E_XML_MISSINGDATA _HRESULT_TYPEDEF_(0x8024000DL) + +// +// MessageId: WU_E_XML_INVALID +// +// MessageText: +// +// Windows Update Agent found invalid information in the update's XML data. +// +#define WU_E_XML_INVALID _HRESULT_TYPEDEF_(0x8024000EL) + +// +// MessageId: WU_E_CYCLE_DETECTED +// +// MessageText: +// +// Circular update relationships were detected in the metadata. +// +#define WU_E_CYCLE_DETECTED _HRESULT_TYPEDEF_(0x8024000FL) + +// +// MessageId: WU_E_TOO_DEEP_RELATION +// +// MessageText: +// +// Update relationships too deep to evaluate were evaluated. +// +#define WU_E_TOO_DEEP_RELATION _HRESULT_TYPEDEF_(0x80240010L) + +// +// MessageId: WU_E_INVALID_RELATIONSHIP +// +// MessageText: +// +// An invalid update relationship was detected. +// +#define WU_E_INVALID_RELATIONSHIP _HRESULT_TYPEDEF_(0x80240011L) + +// +// MessageId: WU_E_REG_VALUE_INVALID +// +// MessageText: +// +// An invalid registry value was read. +// +#define WU_E_REG_VALUE_INVALID _HRESULT_TYPEDEF_(0x80240012L) + +// +// MessageId: WU_E_DUPLICATE_ITEM +// +// MessageText: +// +// Operation tried to add a duplicate item to a list. +// +#define WU_E_DUPLICATE_ITEM _HRESULT_TYPEDEF_(0x80240013L) + +// +// MessageId: WU_E_INSTALL_NOT_ALLOWED +// +// MessageText: +// +// Operation tried to install while another installation was in progress or the system was pending a mandatory restart. +// +#define WU_E_INSTALL_NOT_ALLOWED _HRESULT_TYPEDEF_(0x80240016L) + +// +// MessageId: WU_E_NOT_APPLICABLE +// +// MessageText: +// +// Operation was not performed because there are no applicable updates. +// +#define WU_E_NOT_APPLICABLE _HRESULT_TYPEDEF_(0x80240017L) + +// +// MessageId: WU_E_NO_USERTOKEN +// +// MessageText: +// +// Operation failed because a required user token is missing. +// +#define WU_E_NO_USERTOKEN _HRESULT_TYPEDEF_(0x80240018L) + +// +// MessageId: WU_E_EXCLUSIVE_INSTALL_CONFLICT +// +// MessageText: +// +// An exclusive update cannot be installed with other updates at the same time. +// +#define WU_E_EXCLUSIVE_INSTALL_CONFLICT _HRESULT_TYPEDEF_(0x80240019L) + +// +// MessageId: WU_E_POLICY_NOT_SET +// +// MessageText: +// +// A policy value was not set. +// +#define WU_E_POLICY_NOT_SET _HRESULT_TYPEDEF_(0x8024001AL) + +// +// MessageId: WU_E_SELFUPDATE_IN_PROGRESS +// +// MessageText: +// +// The operation could not be performed because the Windows Update Agent is self-updating. +// +#define WU_E_SELFUPDATE_IN_PROGRESS _HRESULT_TYPEDEF_(0x8024001BL) + +// +// MessageId: WU_E_INVALID_UPDATE +// +// MessageText: +// +// An update contains invalid metadata. +// +#define WU_E_INVALID_UPDATE _HRESULT_TYPEDEF_(0x8024001DL) + +// +// MessageId: WU_E_SERVICE_STOP +// +// MessageText: +// +// Operation did not complete because the service or system was being shut down. +// +#define WU_E_SERVICE_STOP _HRESULT_TYPEDEF_(0x8024001EL) + +// +// MessageId: WU_E_NO_CONNECTION +// +// MessageText: +// +// Operation did not complete because the network connection was unavailable. +// +#define WU_E_NO_CONNECTION _HRESULT_TYPEDEF_(0x8024001FL) + +// +// MessageId: WU_E_NO_INTERACTIVE_USER +// +// MessageText: +// +// Operation did not complete because there is no logged-on interactive user. +// +#define WU_E_NO_INTERACTIVE_USER _HRESULT_TYPEDEF_(0x80240020L) + +// +// MessageId: WU_E_TIME_OUT +// +// MessageText: +// +// Operation did not complete because it timed out. +// +#define WU_E_TIME_OUT _HRESULT_TYPEDEF_(0x80240021L) + +// +// MessageId: WU_E_ALL_UPDATES_FAILED +// +// MessageText: +// +// Operation failed for all the updates. +// +#define WU_E_ALL_UPDATES_FAILED _HRESULT_TYPEDEF_(0x80240022L) + +// +// MessageId: WU_E_EULAS_DECLINED +// +// MessageText: +// +// The license terms for all updates were declined. +// +#define WU_E_EULAS_DECLINED _HRESULT_TYPEDEF_(0x80240023L) + +// +// MessageId: WU_E_NO_UPDATE +// +// MessageText: +// +// There are no updates. +// +#define WU_E_NO_UPDATE _HRESULT_TYPEDEF_(0x80240024L) + +// +// MessageId: WU_E_USER_ACCESS_DISABLED +// +// MessageText: +// +// Group Policy settings prevented access to Windows Update. +// +#define WU_E_USER_ACCESS_DISABLED _HRESULT_TYPEDEF_(0x80240025L) + +// +// MessageId: WU_E_INVALID_UPDATE_TYPE +// +// MessageText: +// +// The type of update is invalid. +// +#define WU_E_INVALID_UPDATE_TYPE _HRESULT_TYPEDEF_(0x80240026L) + +// +// MessageId: WU_E_URL_TOO_LONG +// +// MessageText: +// +// The URL exceeded the maximum length. +// +#define WU_E_URL_TOO_LONG _HRESULT_TYPEDEF_(0x80240027L) + +// +// MessageId: WU_E_UNINSTALL_NOT_ALLOWED +// +// MessageText: +// +// The update could not be uninstalled because the request did not originate from a WSUS server. +// +#define WU_E_UNINSTALL_NOT_ALLOWED _HRESULT_TYPEDEF_(0x80240028L) + +// +// MessageId: WU_E_INVALID_PRODUCT_LICENSE +// +// MessageText: +// +// Search may have missed some updates before there is an unlicensed application on the system. +// +#define WU_E_INVALID_PRODUCT_LICENSE _HRESULT_TYPEDEF_(0x80240029L) + +// +// MessageId: WU_E_MISSING_HANDLER +// +// MessageText: +// +// A component required to detect applicable updates was missing. +// +#define WU_E_MISSING_HANDLER _HRESULT_TYPEDEF_(0x8024002AL) + +// +// MessageId: WU_E_LEGACYSERVER +// +// MessageText: +// +// An operation did not complete because it requires a newer version of server. +// +#define WU_E_LEGACYSERVER _HRESULT_TYPEDEF_(0x8024002BL) + +// +// MessageId: WU_E_BIN_SOURCE_ABSENT +// +// MessageText: +// +// A delta-compressed update could not be installed because it required the source. +// +#define WU_E_BIN_SOURCE_ABSENT _HRESULT_TYPEDEF_(0x8024002CL) + +// +// MessageId: WU_E_SOURCE_ABSENT +// +// MessageText: +// +// A full-file update could not be installed because it required the source. +// +#define WU_E_SOURCE_ABSENT _HRESULT_TYPEDEF_(0x8024002DL) + +// +// MessageId: WU_E_WU_DISABLED +// +// MessageText: +// +// Access to an unmanaged server is not allowed. +// +#define WU_E_WU_DISABLED _HRESULT_TYPEDEF_(0x8024002EL) + +// +// MessageId: WU_E_CALL_CANCELLED_BY_POLICY +// +// MessageText: +// +// Operation did not complete because the DisableWindowsUpdateAccess policy was set. +// +#define WU_E_CALL_CANCELLED_BY_POLICY _HRESULT_TYPEDEF_(0x8024002FL) + +// +// MessageId: WU_E_INVALID_PROXY_SERVER +// +// MessageText: +// +// The format of the proxy list was invalid. +// +#define WU_E_INVALID_PROXY_SERVER _HRESULT_TYPEDEF_(0x80240030L) + +// +// MessageId: WU_E_INVALID_FILE +// +// MessageText: +// +// The file is in the wrong format. +// +#define WU_E_INVALID_FILE _HRESULT_TYPEDEF_(0x80240031L) + +// +// MessageId: WU_E_INVALID_CRITERIA +// +// MessageText: +// +// The search criteria string was invalid. +// +#define WU_E_INVALID_CRITERIA _HRESULT_TYPEDEF_(0x80240032L) + +// +// MessageId: WU_E_EULA_UNAVAILABLE +// +// MessageText: +// +// License terms could not be downloaded. +// +#define WU_E_EULA_UNAVAILABLE _HRESULT_TYPEDEF_(0x80240033L) + +// +// MessageId: WU_E_DOWNLOAD_FAILED +// +// MessageText: +// +// Update failed to download. +// +#define WU_E_DOWNLOAD_FAILED _HRESULT_TYPEDEF_(0x80240034L) + +// +// MessageId: WU_E_UPDATE_NOT_PROCESSED +// +// MessageText: +// +// The update was not processed. +// +#define WU_E_UPDATE_NOT_PROCESSED _HRESULT_TYPEDEF_(0x80240035L) + +// +// MessageId: WU_E_INVALID_OPERATION +// +// MessageText: +// +// The object's current state did not allow the operation. +// +#define WU_E_INVALID_OPERATION _HRESULT_TYPEDEF_(0x80240036L) + +// +// MessageId: WU_E_NOT_SUPPORTED +// +// MessageText: +// +// The functionality for the operation is not supported. +// +#define WU_E_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80240037L) + +// +// MessageId: WU_E_WINHTTP_INVALID_FILE +// +// MessageText: +// +// The downloaded file has an unexpected content type. +// +#define WU_E_WINHTTP_INVALID_FILE _HRESULT_TYPEDEF_(0x80240038L) + +// +// MessageId: WU_E_TOO_MANY_RESYNC +// +// MessageText: +// +// Agent is asked by server to resync too many times. +// +#define WU_E_TOO_MANY_RESYNC _HRESULT_TYPEDEF_(0x80240039L) + +// +// MessageId: WU_E_NO_SERVER_CORE_SUPPORT +// +// MessageText: +// +// WUA API method does not run on Server Core installation. +// +#define WU_E_NO_SERVER_CORE_SUPPORT _HRESULT_TYPEDEF_(0x80240040L) + +// +// MessageId: WU_E_SYSPREP_IN_PROGRESS +// +// MessageText: +// +// Service is not available while sysprep is running. +// +#define WU_E_SYSPREP_IN_PROGRESS _HRESULT_TYPEDEF_(0x80240041L) + +// +// MessageId: WU_E_UNKNOWN_SERVICE +// +// MessageText: +// +// The update service is no longer registered with AU. +// +#define WU_E_UNKNOWN_SERVICE _HRESULT_TYPEDEF_(0x80240042L) + +// +// MessageId: WU_E_NO_UI_SUPPORT +// +// MessageText: +// +// There is no support for WUA UI. +// +#define WU_E_NO_UI_SUPPORT _HRESULT_TYPEDEF_(0x80240043L) + +// +// MessageId: WU_E_UNEXPECTED +// +// MessageText: +// +// An operation failed due to reasons not covered by another error code. +// +#define WU_E_UNEXPECTED _HRESULT_TYPEDEF_(0x80240FFFL) + +/////////////////////////////////////////////////////////////////////////////// +// Windows Installer minor errors +// +// The following errors are used to indicate that part of a search failed for +// MSI problems. Another part of the search may successfully return updates. +// All MSI minor codes should share the same error code range so that the caller +// tell that they are related to Windows Installer. +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_MSI_WRONG_VERSION +// +// MessageText: +// +// Search may have missed some updates because the Windows Installer is less than version 3.1. +// +#define WU_E_MSI_WRONG_VERSION _HRESULT_TYPEDEF_(0x80241001L) + +// +// MessageId: WU_E_MSI_NOT_CONFIGURED +// +// MessageText: +// +// Search may have missed some updates because the Windows Installer is not configured. +// +#define WU_E_MSI_NOT_CONFIGURED _HRESULT_TYPEDEF_(0x80241002L) + +// +// MessageId: WU_E_MSP_DISABLED +// +// MessageText: +// +// Search may have missed some updates because policy has disabled Windows Installer patching. +// +#define WU_E_MSP_DISABLED _HRESULT_TYPEDEF_(0x80241003L) + +// +// MessageId: WU_E_MSI_WRONG_APP_CONTEXT +// +// MessageText: +// +// An update could not be applied because the application is installed per-user. +// +#define WU_E_MSI_WRONG_APP_CONTEXT _HRESULT_TYPEDEF_(0x80241004L) + +// +// MessageId: WU_E_MSP_UNEXPECTED +// +// MessageText: +// +// Search may have missed some updates because there was a failure of the Windows Installer. +// +#define WU_E_MSP_UNEXPECTED _HRESULT_TYPEDEF_(0x80241FFFL) + +/////////////////////////////////////////////////////////////////////////////// +// Protocol Talker errors +// +// The following map to SOAPCLIENT_ERRORs from atlsoap.h. These errors +// are obtained from calling GetClientError() on the CClientWebService +// object. +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_PT_SOAPCLIENT_BASE +// +// MessageText: +// +// WU_E_PT_SOAPCLIENT_* error codes map to the SOAPCLIENT_ERROR enum of the ATL Server Library. +// +#define WU_E_PT_SOAPCLIENT_BASE _HRESULT_TYPEDEF_(0x80244000L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_INITIALIZE +// +// MessageText: +// +// Same as SOAPCLIENT_INITIALIZE_ERROR - initialization of the SOAP client failed, possibly because of an MSXML installation failure. +// +#define WU_E_PT_SOAPCLIENT_INITIALIZE _HRESULT_TYPEDEF_(0x80244001L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_OUTOFMEMORY +// +// MessageText: +// +// Same as SOAPCLIENT_OUTOFMEMORY - SOAP client failed because it ran out of memory. +// +#define WU_E_PT_SOAPCLIENT_OUTOFMEMORY _HRESULT_TYPEDEF_(0x80244002L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_GENERATE +// +// MessageText: +// +// Same as SOAPCLIENT_GENERATE_ERROR - SOAP client failed to generate the request. +// +#define WU_E_PT_SOAPCLIENT_GENERATE _HRESULT_TYPEDEF_(0x80244003L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_CONNECT +// +// MessageText: +// +// Same as SOAPCLIENT_CONNECT_ERROR - SOAP client failed to connect to the server. +// +#define WU_E_PT_SOAPCLIENT_CONNECT _HRESULT_TYPEDEF_(0x80244004L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_SEND +// +// MessageText: +// +// Same as SOAPCLIENT_SEND_ERROR - SOAP client failed to send a message for reasons of WU_E_WINHTTP_* error codes. +// +#define WU_E_PT_SOAPCLIENT_SEND _HRESULT_TYPEDEF_(0x80244005L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_SERVER +// +// MessageText: +// +// Same as SOAPCLIENT_SERVER_ERROR - SOAP client failed because there was a server error. +// +#define WU_E_PT_SOAPCLIENT_SERVER _HRESULT_TYPEDEF_(0x80244006L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_SOAPFAULT +// +// MessageText: +// +// Same as SOAPCLIENT_SOAPFAULT - SOAP client failed because there was a SOAP fault for reasons of WU_E_PT_SOAP_* error codes. +// +#define WU_E_PT_SOAPCLIENT_SOAPFAULT _HRESULT_TYPEDEF_(0x80244007L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_PARSEFAULT +// +// MessageText: +// +// Same as SOAPCLIENT_PARSEFAULT_ERROR - SOAP client failed to parse a SOAP fault. +// +#define WU_E_PT_SOAPCLIENT_PARSEFAULT _HRESULT_TYPEDEF_(0x80244008L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_READ +// +// MessageText: +// +// Same as SOAPCLIENT_READ_ERROR - SOAP client failed while reading the response from the server. +// +#define WU_E_PT_SOAPCLIENT_READ _HRESULT_TYPEDEF_(0x80244009L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_PARSE +// +// MessageText: +// +// Same as SOAPCLIENT_PARSE_ERROR - SOAP client failed to parse the response from the server. +// +#define WU_E_PT_SOAPCLIENT_PARSE _HRESULT_TYPEDEF_(0x8024400AL) + +// The following map to SOAP_ERROR_CODEs from atlsoap.h. These errors +// are obtained from the m_fault.m_soapErrCode member on the +// CClientWebService object when GetClientError() returned +// SOAPCLIENT_SOAPFAULT. +// +// MessageId: WU_E_PT_SOAP_VERSION +// +// MessageText: +// +// Same as SOAP_E_VERSION_MISMATCH - SOAP client found an unrecognizable namespace for the SOAP envelope. +// +#define WU_E_PT_SOAP_VERSION _HRESULT_TYPEDEF_(0x8024400BL) + +// +// MessageId: WU_E_PT_SOAP_MUST_UNDERSTAND +// +// MessageText: +// +// Same as SOAP_E_MUST_UNDERSTAND - SOAP client was unable to understand a header. +// +#define WU_E_PT_SOAP_MUST_UNDERSTAND _HRESULT_TYPEDEF_(0x8024400CL) + +// +// MessageId: WU_E_PT_SOAP_CLIENT +// +// MessageText: +// +// Same as SOAP_E_CLIENT - SOAP client found the message was malformed; fix before resending. +// +#define WU_E_PT_SOAP_CLIENT _HRESULT_TYPEDEF_(0x8024400DL) + +// +// MessageId: WU_E_PT_SOAP_SERVER +// +// MessageText: +// +// Same as SOAP_E_SERVER - The SOAP message could not be processed due to a server error; resend later. +// +#define WU_E_PT_SOAP_SERVER _HRESULT_TYPEDEF_(0x8024400EL) + +// +// MessageId: WU_E_PT_WMI_ERROR +// +// MessageText: +// +// There was an unspecified Windows Management Instrumentation (WMI) error. +// +#define WU_E_PT_WMI_ERROR _HRESULT_TYPEDEF_(0x8024400FL) + +// +// MessageId: WU_E_PT_EXCEEDED_MAX_SERVER_TRIPS +// +// MessageText: +// +// The number of round trips to the server exceeded the maximum limit. +// +#define WU_E_PT_EXCEEDED_MAX_SERVER_TRIPS _HRESULT_TYPEDEF_(0x80244010L) + +// +// MessageId: WU_E_PT_SUS_SERVER_NOT_SET +// +// MessageText: +// +// WUServer policy value is missing in the registry. +// +#define WU_E_PT_SUS_SERVER_NOT_SET _HRESULT_TYPEDEF_(0x80244011L) + +// +// MessageId: WU_E_PT_DOUBLE_INITIALIZATION +// +// MessageText: +// +// Initialization failed because the object was already initialized. +// +#define WU_E_PT_DOUBLE_INITIALIZATION _HRESULT_TYPEDEF_(0x80244012L) + +// +// MessageId: WU_E_PT_INVALID_COMPUTER_NAME +// +// MessageText: +// +// The computer name could not be determined. +// +#define WU_E_PT_INVALID_COMPUTER_NAME _HRESULT_TYPEDEF_(0x80244013L) + +// +// MessageId: WU_E_PT_REFRESH_CACHE_REQUIRED +// +// MessageText: +// +// The reply from the server indicates that the server was changed or the cookie was invalid; refresh the state of the internal cache and retry. +// +#define WU_E_PT_REFRESH_CACHE_REQUIRED _HRESULT_TYPEDEF_(0x80244015L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_BAD_REQUEST +// +// MessageText: +// +// Same as HTTP status 400 - the server could not process the request due to invalid syntax. +// +#define WU_E_PT_HTTP_STATUS_BAD_REQUEST _HRESULT_TYPEDEF_(0x80244016L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_DENIED +// +// MessageText: +// +// Same as HTTP status 401 - the requested resource requires user authentication. +// +#define WU_E_PT_HTTP_STATUS_DENIED _HRESULT_TYPEDEF_(0x80244017L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_FORBIDDEN +// +// MessageText: +// +// Same as HTTP status 403 - server understood the request, but declined to fulfill it. +// +#define WU_E_PT_HTTP_STATUS_FORBIDDEN _HRESULT_TYPEDEF_(0x80244018L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_NOT_FOUND +// +// MessageText: +// +// Same as HTTP status 404 - the server cannot find the requested URI (Uniform Resource Identifier). +// +// +#define WU_E_PT_HTTP_STATUS_NOT_FOUND _HRESULT_TYPEDEF_(0x80244019L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_BAD_METHOD +// +// MessageText: +// +// Same as HTTP status 405 - the HTTP method is not allowed. +// +#define WU_E_PT_HTTP_STATUS_BAD_METHOD _HRESULT_TYPEDEF_(0x8024401AL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_PROXY_AUTH_REQ +// +// MessageText: +// +// Same as HTTP status 407 - proxy authentication is required. +// +#define WU_E_PT_HTTP_STATUS_PROXY_AUTH_REQ _HRESULT_TYPEDEF_(0x8024401BL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_REQUEST_TIMEOUT +// +// MessageText: +// +// Same as HTTP status 408 - the server timed out waiting for the request. +// +#define WU_E_PT_HTTP_STATUS_REQUEST_TIMEOUT _HRESULT_TYPEDEF_(0x8024401CL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_CONFLICT +// +// MessageText: +// +// Same as HTTP status 409 - the request was not completed due to a conflict with the current state of the resource. +// +#define WU_E_PT_HTTP_STATUS_CONFLICT _HRESULT_TYPEDEF_(0x8024401DL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_GONE +// +// MessageText: +// +// Same as HTTP status 410 - requested resource is no longer available at the server. +// +#define WU_E_PT_HTTP_STATUS_GONE _HRESULT_TYPEDEF_(0x8024401EL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_SERVER_ERROR +// +// MessageText: +// +// Same as HTTP status 500 - an error internal to the server prevented fulfilling the request. +// +#define WU_E_PT_HTTP_STATUS_SERVER_ERROR _HRESULT_TYPEDEF_(0x8024401FL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_NOT_SUPPORTED +// +// MessageText: +// +// Same as HTTP status 500 - server does not support the functionality required to fulfill the request. +// +#define WU_E_PT_HTTP_STATUS_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80244020L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_BAD_GATEWAY +// +// MessageText: +// +// Same as HTTP status 502 - the server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request. +// +#define WU_E_PT_HTTP_STATUS_BAD_GATEWAY _HRESULT_TYPEDEF_(0x80244021L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_SERVICE_UNAVAIL +// +// MessageText: +// +// Same as HTTP status 503 - the service is temporarily overloaded. +// +#define WU_E_PT_HTTP_STATUS_SERVICE_UNAVAIL _HRESULT_TYPEDEF_(0x80244022L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_GATEWAY_TIMEOUT +// +// MessageText: +// +// Same as HTTP status 503 - the request was timed out waiting for a gateway. +// +#define WU_E_PT_HTTP_STATUS_GATEWAY_TIMEOUT _HRESULT_TYPEDEF_(0x80244023L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_VERSION_NOT_SUP +// +// MessageText: +// +// Same as HTTP status 505 - the server does not support the HTTP protocol version used for the request. +// +#define WU_E_PT_HTTP_STATUS_VERSION_NOT_SUP _HRESULT_TYPEDEF_(0x80244024L) + +// +// MessageId: WU_E_PT_FILE_LOCATIONS_CHANGED +// +// MessageText: +// +// Operation failed due to a changed file location; refresh internal state and resend. +// +#define WU_E_PT_FILE_LOCATIONS_CHANGED _HRESULT_TYPEDEF_(0x80244025L) + +// +// MessageId: WU_E_PT_REGISTRATION_NOT_SUPPORTED +// +// MessageText: +// +// Operation failed because Windows Update Agent does not support registration with a non-WSUS server. +// +#define WU_E_PT_REGISTRATION_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80244026L) + +// +// MessageId: WU_E_PT_NO_AUTH_PLUGINS_REQUESTED +// +// MessageText: +// +// The server returned an empty authentication information list. +// +#define WU_E_PT_NO_AUTH_PLUGINS_REQUESTED _HRESULT_TYPEDEF_(0x80244027L) + +// +// MessageId: WU_E_PT_NO_AUTH_COOKIES_CREATED +// +// MessageText: +// +// Windows Update Agent was unable to create any valid authentication cookies. +// +#define WU_E_PT_NO_AUTH_COOKIES_CREATED _HRESULT_TYPEDEF_(0x80244028L) + +// +// MessageId: WU_E_PT_INVALID_CONFIG_PROP +// +// MessageText: +// +// A configuration property value was wrong. +// +#define WU_E_PT_INVALID_CONFIG_PROP _HRESULT_TYPEDEF_(0x80244029L) + +// +// MessageId: WU_E_PT_CONFIG_PROP_MISSING +// +// MessageText: +// +// A configuration property value was missing. +// +#define WU_E_PT_CONFIG_PROP_MISSING _HRESULT_TYPEDEF_(0x8024402AL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_NOT_MAPPED +// +// MessageText: +// +// The HTTP request could not be completed and the reason did not correspond to any of the WU_E_PT_HTTP_* error codes. +// +#define WU_E_PT_HTTP_STATUS_NOT_MAPPED _HRESULT_TYPEDEF_(0x8024402BL) + +// +// MessageId: WU_E_PT_WINHTTP_NAME_NOT_RESOLVED +// +// MessageText: +// +// Same as ERROR_WINHTTP_NAME_NOT_RESOLVED - the proxy server or target server name cannot be resolved. +// +#define WU_E_PT_WINHTTP_NAME_NOT_RESOLVED _HRESULT_TYPEDEF_(0x8024402CL) + +// +// MessageId: WU_E_PT_SAME_REDIR_ID +// +// MessageText: +// +// Windows Update Agent failed to download a redirector cabinet file with a new redirectorId value from the server during the recovery. +// +#define WU_E_PT_SAME_REDIR_ID _HRESULT_TYPEDEF_(0x8024502DL) + +// +// MessageId: WU_E_PT_NO_MANAGED_RECOVER +// +// MessageText: +// +// A redirector recovery action did not complete because the server is managed. +// +#define WU_E_PT_NO_MANAGED_RECOVER _HRESULT_TYPEDEF_(0x8024502EL) + +// +// MessageId: WU_E_PT_ECP_SUCCEEDED_WITH_ERRORS +// +// MessageText: +// +// External cab file processing completed with some errors. +// +#define WU_E_PT_ECP_SUCCEEDED_WITH_ERRORS _HRESULT_TYPEDEF_(0x8024402FL) + +// +// MessageId: WU_E_PT_ECP_INIT_FAILED +// +// MessageText: +// +// The external cab processor initialization did not complete. +// +#define WU_E_PT_ECP_INIT_FAILED _HRESULT_TYPEDEF_(0x80244030L) + +// +// MessageId: WU_E_PT_ECP_INVALID_FILE_FORMAT +// +// MessageText: +// +// The format of a metadata file was invalid. +// +#define WU_E_PT_ECP_INVALID_FILE_FORMAT _HRESULT_TYPEDEF_(0x80244031L) + +// +// MessageId: WU_E_PT_ECP_INVALID_METADATA +// +// MessageText: +// +// External cab processor found invalid metadata. +// +#define WU_E_PT_ECP_INVALID_METADATA _HRESULT_TYPEDEF_(0x80244032L) + +// +// MessageId: WU_E_PT_ECP_FAILURE_TO_EXTRACT_DIGEST +// +// MessageText: +// +// The file digest could not be extracted from an external cab file. +// +#define WU_E_PT_ECP_FAILURE_TO_EXTRACT_DIGEST _HRESULT_TYPEDEF_(0x80244033L) + +// +// MessageId: WU_E_PT_ECP_FAILURE_TO_DECOMPRESS_CAB_FILE +// +// MessageText: +// +// An external cab file could not be decompressed. +// +#define WU_E_PT_ECP_FAILURE_TO_DECOMPRESS_CAB_FILE _HRESULT_TYPEDEF_(0x80244034L) + +// +// MessageId: WU_E_PT_ECP_FILE_LOCATION_ERROR +// +// MessageText: +// +// External cab processor was unable to get file locations. +// +#define WU_E_PT_ECP_FILE_LOCATION_ERROR _HRESULT_TYPEDEF_(0x80244035L) + +// +// MessageId: WU_E_PT_UNEXPECTED +// +// MessageText: +// +// A communication error not covered by another WU_E_PT_* error code. +// +#define WU_E_PT_UNEXPECTED _HRESULT_TYPEDEF_(0x80244FFFL) + +/////////////////////////////////////////////////////////////////////////////// +// Redirector errors +// +// The following errors are generated by the components that download and +// parse the wuredir.cab +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_REDIRECTOR_LOAD_XML +// +// MessageText: +// +// The redirector XML document could not be loaded into the DOM class. +// +#define WU_E_REDIRECTOR_LOAD_XML _HRESULT_TYPEDEF_(0x80245001L) + +// +// MessageId: WU_E_REDIRECTOR_S_FALSE +// +// MessageText: +// +// The redirector XML document is missing some required information. +// +#define WU_E_REDIRECTOR_S_FALSE _HRESULT_TYPEDEF_(0x80245002L) + +// +// MessageId: WU_E_REDIRECTOR_ID_SMALLER +// +// MessageText: +// +// The redirectorId in the downloaded redirector cab is less than in the cached cab. +// +#define WU_E_REDIRECTOR_ID_SMALLER _HRESULT_TYPEDEF_(0x80245003L) + +// +// MessageId: WU_E_REDIRECTOR_UNEXPECTED +// +// MessageText: +// +// The redirector failed for reasons not covered by another WU_E_REDIRECTOR_* error code. +// +#define WU_E_REDIRECTOR_UNEXPECTED _HRESULT_TYPEDEF_(0x80245FFFL) + +/////////////////////////////////////////////////////////////////////////////// +// driver util errors +// +// The device PnP enumerated device was pruned from the SystemSpec because +// one of the hardware or compatible IDs matched an installed printer driver. +// This is not considered a fatal error and the device is simply skipped. +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_DRV_PRUNED +// +// MessageText: +// +// A driver was skipped. +// +#define WU_E_DRV_PRUNED _HRESULT_TYPEDEF_(0x8024C001L) + +// +// MessageId: WU_E_DRV_NOPROP_OR_LEGACY +// +// MessageText: +// +// A property for the driver could not be found. It may not conform with required specifications. +// +#define WU_E_DRV_NOPROP_OR_LEGACY _HRESULT_TYPEDEF_(0x8024C002L) + +// +// MessageId: WU_E_DRV_REG_MISMATCH +// +// MessageText: +// +// The registry type read for the driver does not match the expected type. +// +#define WU_E_DRV_REG_MISMATCH _HRESULT_TYPEDEF_(0x8024C003L) + +// +// MessageId: WU_E_DRV_NO_METADATA +// +// MessageText: +// +// The driver update is missing metadata. +// +#define WU_E_DRV_NO_METADATA _HRESULT_TYPEDEF_(0x8024C004L) + +// +// MessageId: WU_E_DRV_MISSING_ATTRIBUTE +// +// MessageText: +// +// The driver update is missing a required attribute. +// +#define WU_E_DRV_MISSING_ATTRIBUTE _HRESULT_TYPEDEF_(0x8024C005L) + +// +// MessageId: WU_E_DRV_SYNC_FAILED +// +// MessageText: +// +// Driver synchronization failed. +// +#define WU_E_DRV_SYNC_FAILED _HRESULT_TYPEDEF_(0x8024C006L) + +// +// MessageId: WU_E_DRV_NO_PRINTER_CONTENT +// +// MessageText: +// +// Information required for the synchronization of applicable printers is missing. +// +#define WU_E_DRV_NO_PRINTER_CONTENT _HRESULT_TYPEDEF_(0x8024C007L) + +// +// MessageId: WU_E_DRV_UNEXPECTED +// +// MessageText: +// +// A driver error not covered by another WU_E_DRV_* code. +// +#define WU_E_DRV_UNEXPECTED _HRESULT_TYPEDEF_(0x8024CFFFL) + +////////////////////////////////////////////////////////////////////////////// +// data store errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_DS_SHUTDOWN +// +// MessageText: +// +// An operation failed because Windows Update Agent is shutting down. +// +#define WU_E_DS_SHUTDOWN _HRESULT_TYPEDEF_(0x80248000L) + +// +// MessageId: WU_E_DS_INUSE +// +// MessageText: +// +// An operation failed because the data store was in use. +// +#define WU_E_DS_INUSE _HRESULT_TYPEDEF_(0x80248001L) + +// +// MessageId: WU_E_DS_INVALID +// +// MessageText: +// +// The current and expected states of the data store do not match. +// +#define WU_E_DS_INVALID _HRESULT_TYPEDEF_(0x80248002L) + +// +// MessageId: WU_E_DS_TABLEMISSING +// +// MessageText: +// +// The data store is missing a table. +// +#define WU_E_DS_TABLEMISSING _HRESULT_TYPEDEF_(0x80248003L) + +// +// MessageId: WU_E_DS_TABLEINCORRECT +// +// MessageText: +// +// The data store contains a table with unexpected columns. +// +#define WU_E_DS_TABLEINCORRECT _HRESULT_TYPEDEF_(0x80248004L) + +// +// MessageId: WU_E_DS_INVALIDTABLENAME +// +// MessageText: +// +// A table could not be opened because the table is not in the data store. +// +#define WU_E_DS_INVALIDTABLENAME _HRESULT_TYPEDEF_(0x80248005L) + +// +// MessageId: WU_E_DS_BADVERSION +// +// MessageText: +// +// The current and expected versions of the data store do not match. +// +#define WU_E_DS_BADVERSION _HRESULT_TYPEDEF_(0x80248006L) + +// +// MessageId: WU_E_DS_NODATA +// +// MessageText: +// +// The information requested is not in the data store. +// +#define WU_E_DS_NODATA _HRESULT_TYPEDEF_(0x80248007L) + +// +// MessageId: WU_E_DS_MISSINGDATA +// +// MessageText: +// +// The data store is missing required information or has a NULL in a table column that requires a non-null value. +// +#define WU_E_DS_MISSINGDATA _HRESULT_TYPEDEF_(0x80248008L) + +// +// MessageId: WU_E_DS_MISSINGREF +// +// MessageText: +// +// The data store is missing required information or has a reference to missing license terms, file, localized property or linked row. +// +#define WU_E_DS_MISSINGREF _HRESULT_TYPEDEF_(0x80248009L) + +// +// MessageId: WU_E_DS_UNKNOWNHANDLER +// +// MessageText: +// +// The update was not processed because its update handler could not be recognized. +// +#define WU_E_DS_UNKNOWNHANDLER _HRESULT_TYPEDEF_(0x8024800AL) + +// +// MessageId: WU_E_DS_CANTDELETE +// +// MessageText: +// +// The update was not deleted because it is still referenced by one or more services. +// +#define WU_E_DS_CANTDELETE _HRESULT_TYPEDEF_(0x8024800BL) + +// +// MessageId: WU_E_DS_LOCKTIMEOUTEXPIRED +// +// MessageText: +// +// The data store section could not be locked within the allotted time. +// +#define WU_E_DS_LOCKTIMEOUTEXPIRED _HRESULT_TYPEDEF_(0x8024800CL) + +// +// MessageId: WU_E_DS_NOCATEGORIES +// +// MessageText: +// +// The category was not added because it contains no parent categories and is not a top-level category itself. +// +#define WU_E_DS_NOCATEGORIES _HRESULT_TYPEDEF_(0x8024800DL) + +// +// MessageId: WU_E_DS_ROWEXISTS +// +// MessageText: +// +// The row was not added because an existing row has the same primary key. +// +#define WU_E_DS_ROWEXISTS _HRESULT_TYPEDEF_(0x8024800EL) + +// +// MessageId: WU_E_DS_STOREFILELOCKED +// +// MessageText: +// +// The data store could not be initialized because it was locked by another process. +// +#define WU_E_DS_STOREFILELOCKED _HRESULT_TYPEDEF_(0x8024800FL) + +// +// MessageId: WU_E_DS_CANNOTREGISTER +// +// MessageText: +// +// The data store is not allowed to be registered with COM in the current process. +// +#define WU_E_DS_CANNOTREGISTER _HRESULT_TYPEDEF_(0x80248010L) + +// +// MessageId: WU_E_DS_UNABLETOSTART +// +// MessageText: +// +// Could not create a data store object in another process. +// +#define WU_E_DS_UNABLETOSTART _HRESULT_TYPEDEF_(0x80248011L) + +// +// MessageId: WU_E_DS_DUPLICATEUPDATEID +// +// MessageText: +// +// The server sent the same update to the client with two different revision IDs. +// +#define WU_E_DS_DUPLICATEUPDATEID _HRESULT_TYPEDEF_(0x80248013L) + +// +// MessageId: WU_E_DS_UNKNOWNSERVICE +// +// MessageText: +// +// An operation did not complete because the service is not in the data store. +// +#define WU_E_DS_UNKNOWNSERVICE _HRESULT_TYPEDEF_(0x80248014L) + +// +// MessageId: WU_E_DS_SERVICEEXPIRED +// +// MessageText: +// +// An operation did not complete because the registration of the service has expired. +// +#define WU_E_DS_SERVICEEXPIRED _HRESULT_TYPEDEF_(0x80248015L) + +// +// MessageId: WU_E_DS_DECLINENOTALLOWED +// +// MessageText: +// +// A request to hide an update was declined because it is a mandatory update or because it was deployed with a deadline. +// +#define WU_E_DS_DECLINENOTALLOWED _HRESULT_TYPEDEF_(0x80248016L) + +// +// MessageId: WU_E_DS_TABLESESSIONMISMATCH +// +// MessageText: +// +// A table was not closed because it is not associated with the session. +// +#define WU_E_DS_TABLESESSIONMISMATCH _HRESULT_TYPEDEF_(0x80248017L) + +// +// MessageId: WU_E_DS_SESSIONLOCKMISMATCH +// +// MessageText: +// +// A table was not closed because it is not associated with the session. +// +#define WU_E_DS_SESSIONLOCKMISMATCH _HRESULT_TYPEDEF_(0x80248018L) + +// +// MessageId: WU_E_DS_NEEDWINDOWSSERVICE +// +// MessageText: +// +// A request to remove the Windows Update service or to unregister it with Automatic Updates was declined because it is a built-in service and/or Automatic Updates cannot fall back to another service. +// +#define WU_E_DS_NEEDWINDOWSSERVICE _HRESULT_TYPEDEF_(0x80248019L) + +// +// MessageId: WU_E_DS_INVALIDOPERATION +// +// MessageText: +// +// A request was declined because the operation is not allowed. +// +#define WU_E_DS_INVALIDOPERATION _HRESULT_TYPEDEF_(0x8024801AL) + +// +// MessageId: WU_E_DS_SCHEMAMISMATCH +// +// MessageText: +// +// The schema of the current data store and the schema of a table in a backup XML document do not match. +// +#define WU_E_DS_SCHEMAMISMATCH _HRESULT_TYPEDEF_(0x8024801BL) + +// +// MessageId: WU_E_DS_RESETREQUIRED +// +// MessageText: +// +// The data store requires a session reset; release the session and retry with a new session. +// +#define WU_E_DS_RESETREQUIRED _HRESULT_TYPEDEF_(0x8024801CL) + +// +// MessageId: WU_E_DS_IMPERSONATED +// +// MessageText: +// +// A data store operation did not complete because it was requested with an impersonated identity. +// +#define WU_E_DS_IMPERSONATED _HRESULT_TYPEDEF_(0x8024801DL) + +// +// MessageId: WU_E_DS_UNEXPECTED +// +// MessageText: +// +// A data store error not covered by another WU_E_DS_* code. +// +#define WU_E_DS_UNEXPECTED _HRESULT_TYPEDEF_(0x80248FFFL) + +///////////////////////////////////////////////////////////////////////////// +//Inventory Errors +///////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_INVENTORY_PARSEFAILED +// +// MessageText: +// +// Parsing of the rule file failed. +// +#define WU_E_INVENTORY_PARSEFAILED _HRESULT_TYPEDEF_(0x80249001L) + +// +// MessageId: WU_E_INVENTORY_GET_INVENTORY_TYPE_FAILED +// +// MessageText: +// +// Failed to get the requested inventory type from the server. +// +#define WU_E_INVENTORY_GET_INVENTORY_TYPE_FAILED _HRESULT_TYPEDEF_(0x80249002L) + +// +// MessageId: WU_E_INVENTORY_RESULT_UPLOAD_FAILED +// +// MessageText: +// +// Failed to upload inventory result to the server. +// +#define WU_E_INVENTORY_RESULT_UPLOAD_FAILED _HRESULT_TYPEDEF_(0x80249003L) + +// +// MessageId: WU_E_INVENTORY_UNEXPECTED +// +// MessageText: +// +// There was an inventory error not covered by another error code. +// +#define WU_E_INVENTORY_UNEXPECTED _HRESULT_TYPEDEF_(0x80249004L) + +// +// MessageId: WU_E_INVENTORY_WMI_ERROR +// +// MessageText: +// +// A WMI error occurred when enumerating the instances for a particular class. +// +#define WU_E_INVENTORY_WMI_ERROR _HRESULT_TYPEDEF_(0x80249005L) + +///////////////////////////////////////////////////////////////////////////// +//AU Errors +///////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_AU_NOSERVICE +// +// MessageText: +// +// Automatic Updates was unable to service incoming requests. +// +#define WU_E_AU_NOSERVICE _HRESULT_TYPEDEF_(0x8024A000L) + +// +// MessageId: WU_E_AU_NONLEGACYSERVER +// +// MessageText: +// +// The old version of the Automatic Updates client has stopped because the WSUS server has been upgraded. +// +#define WU_E_AU_NONLEGACYSERVER _HRESULT_TYPEDEF_(0x8024A002L) + +// +// MessageId: WU_E_AU_LEGACYCLIENTDISABLED +// +// MessageText: +// +// The old version of the Automatic Updates client was disabled. +// +#define WU_E_AU_LEGACYCLIENTDISABLED _HRESULT_TYPEDEF_(0x8024A003L) + +// +// MessageId: WU_E_AU_PAUSED +// +// MessageText: +// +// Automatic Updates was unable to process incoming requests because it was paused. +// +#define WU_E_AU_PAUSED _HRESULT_TYPEDEF_(0x8024A004L) + +// +// MessageId: WU_E_AU_NO_REGISTERED_SERVICE +// +// MessageText: +// +// No unmanaged service is registered with AU. +// +#define WU_E_AU_NO_REGISTERED_SERVICE _HRESULT_TYPEDEF_(0x8024A005L) + +// +// MessageId: WU_E_AU_UNEXPECTED +// +// MessageText: +// +// An Automatic Updates error not covered by another WU_E_AU * code. +// +#define WU_E_AU_UNEXPECTED _HRESULT_TYPEDEF_(0x8024AFFFL) + +////////////////////////////////////////////////////////////////////////////// +// update handler errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_UH_REMOTEUNAVAILABLE +// +// MessageText: +// +// A request for a remote update handler could not be completed because no remote process is available. +// +#define WU_E_UH_REMOTEUNAVAILABLE _HRESULT_TYPEDEF_(0x80242000L) + +// +// MessageId: WU_E_UH_LOCALONLY +// +// MessageText: +// +// A request for a remote update handler could not be completed because the handler is local only. +// +#define WU_E_UH_LOCALONLY _HRESULT_TYPEDEF_(0x80242001L) + +// +// MessageId: WU_E_UH_UNKNOWNHANDLER +// +// MessageText: +// +// A request for an update handler could not be completed because the handler could not be recognized. +// +#define WU_E_UH_UNKNOWNHANDLER _HRESULT_TYPEDEF_(0x80242002L) + +// +// MessageId: WU_E_UH_REMOTEALREADYACTIVE +// +// MessageText: +// +// A remote update handler could not be created because one already exists. +// +#define WU_E_UH_REMOTEALREADYACTIVE _HRESULT_TYPEDEF_(0x80242003L) + +// +// MessageId: WU_E_UH_DOESNOTSUPPORTACTION +// +// MessageText: +// +// A request for the handler to install (uninstall) an update could not be completed because the update does not support install (uninstall). +// +#define WU_E_UH_DOESNOTSUPPORTACTION _HRESULT_TYPEDEF_(0x80242004L) + +// +// MessageId: WU_E_UH_WRONGHANDLER +// +// MessageText: +// +// An operation did not complete because the wrong handler was specified. +// +#define WU_E_UH_WRONGHANDLER _HRESULT_TYPEDEF_(0x80242005L) + +// +// MessageId: WU_E_UH_INVALIDMETADATA +// +// MessageText: +// +// A handler operation could not be completed because the update contains invalid metadata. +// +#define WU_E_UH_INVALIDMETADATA _HRESULT_TYPEDEF_(0x80242006L) + +// +// MessageId: WU_E_UH_INSTALLERHUNG +// +// MessageText: +// +// An operation could not be completed because the installer exceeded the time limit. +// +#define WU_E_UH_INSTALLERHUNG _HRESULT_TYPEDEF_(0x80242007L) + +// +// MessageId: WU_E_UH_OPERATIONCANCELLED +// +// MessageText: +// +// An operation being done by the update handler was cancelled. +// +#define WU_E_UH_OPERATIONCANCELLED _HRESULT_TYPEDEF_(0x80242008L) + +// +// MessageId: WU_E_UH_BADHANDLERXML +// +// MessageText: +// +// An operation could not be completed because the handler-specific metadata is invalid. +// +#define WU_E_UH_BADHANDLERXML _HRESULT_TYPEDEF_(0x80242009L) + +// +// MessageId: WU_E_UH_CANREQUIREINPUT +// +// MessageText: +// +// A request to the handler to install an update could not be completed because the update requires user input. +// +#define WU_E_UH_CANREQUIREINPUT _HRESULT_TYPEDEF_(0x8024200AL) + +// +// MessageId: WU_E_UH_INSTALLERFAILURE +// +// MessageText: +// +// The installer failed to install (uninstall) one or more updates. +// +#define WU_E_UH_INSTALLERFAILURE _HRESULT_TYPEDEF_(0x8024200BL) + +// +// MessageId: WU_E_UH_FALLBACKTOSELFCONTAINED +// +// MessageText: +// +// The update handler should download self-contained content rather than delta-compressed content for the update. +// +#define WU_E_UH_FALLBACKTOSELFCONTAINED _HRESULT_TYPEDEF_(0x8024200CL) + +// +// MessageId: WU_E_UH_NEEDANOTHERDOWNLOAD +// +// MessageText: +// +// The update handler did not install the update because it needs to be downloaded again. +// +#define WU_E_UH_NEEDANOTHERDOWNLOAD _HRESULT_TYPEDEF_(0x8024200DL) + +// +// MessageId: WU_E_UH_NOTIFYFAILURE +// +// MessageText: +// +// The update handler failed to send notification of the status of the install (uninstall) operation. +// +#define WU_E_UH_NOTIFYFAILURE _HRESULT_TYPEDEF_(0x8024200EL) + +// +// MessageId: WU_E_UH_INCONSISTENT_FILE_NAMES +// +// MessageText: +// +// The file names contained in the update metadata and in the update package are inconsistent. +// +#define WU_E_UH_INCONSISTENT_FILE_NAMES _HRESULT_TYPEDEF_(0x8024200FL) + +// +// MessageId: WU_E_UH_FALLBACKERROR +// +// MessageText: +// +// The update handler failed to fall back to the self-contained content. +// +#define WU_E_UH_FALLBACKERROR _HRESULT_TYPEDEF_(0x80242010L) + +// +// MessageId: WU_E_UH_TOOMANYDOWNLOADREQUESTS +// +// MessageText: +// +// The update handler has exceeded the maximum number of download requests. +// +#define WU_E_UH_TOOMANYDOWNLOADREQUESTS _HRESULT_TYPEDEF_(0x80242011L) + +// +// MessageId: WU_E_UH_UNEXPECTEDCBSRESPONSE +// +// MessageText: +// +// The update handler has received an unexpected response from CBS. +// +#define WU_E_UH_UNEXPECTEDCBSRESPONSE _HRESULT_TYPEDEF_(0x80242012L) + +// +// MessageId: WU_E_UH_BADCBSPACKAGEID +// +// MessageText: +// +// The update metadata contains an invalid CBS package identifier. +// +#define WU_E_UH_BADCBSPACKAGEID _HRESULT_TYPEDEF_(0x80242013L) + +// +// MessageId: WU_E_UH_POSTREBOOTSTILLPENDING +// +// MessageText: +// +// The post-reboot operation for the update is still in progress. +// +#define WU_E_UH_POSTREBOOTSTILLPENDING _HRESULT_TYPEDEF_(0x80242014L) + +// +// MessageId: WU_E_UH_POSTREBOOTRESULTUNKNOWN +// +// MessageText: +// +// The result of the post-reboot operation for the update could not be determined. +// +#define WU_E_UH_POSTREBOOTRESULTUNKNOWN _HRESULT_TYPEDEF_(0x80242015L) + +// +// MessageId: WU_E_UH_POSTREBOOTUNEXPECTEDSTATE +// +// MessageText: +// +// The state of the update after its post-reboot operation has completed is unexpected. +// +#define WU_E_UH_POSTREBOOTUNEXPECTEDSTATE _HRESULT_TYPEDEF_(0x80242016L) + +// +// MessageId: WU_E_UH_NEW_SERVICING_STACK_REQUIRED +// +// MessageText: +// +// The OS servicing stack must be updated before this update is downloaded or installed. +// +#define WU_E_UH_NEW_SERVICING_STACK_REQUIRED _HRESULT_TYPEDEF_(0x80242017L) + +// +// MessageId: WU_E_UH_UNEXPECTED +// +// MessageText: +// +// An update handler error not covered by another WU_E_UH_* code. +// +#define WU_E_UH_UNEXPECTED _HRESULT_TYPEDEF_(0x80242FFFL) + +////////////////////////////////////////////////////////////////////////////// +// download manager errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_DM_URLNOTAVAILABLE +// +// MessageText: +// +// A download manager operation could not be completed because the requested file does not have a URL. +// +#define WU_E_DM_URLNOTAVAILABLE _HRESULT_TYPEDEF_(0x80246001L) + +// +// MessageId: WU_E_DM_INCORRECTFILEHASH +// +// MessageText: +// +// A download manager operation could not be completed because the file digest was not recognized. +// +#define WU_E_DM_INCORRECTFILEHASH _HRESULT_TYPEDEF_(0x80246002L) + +// +// MessageId: WU_E_DM_UNKNOWNALGORITHM +// +// MessageText: +// +// A download manager operation could not be completed because the file metadata requested an unrecognized hash algorithm. +// +#define WU_E_DM_UNKNOWNALGORITHM _HRESULT_TYPEDEF_(0x80246003L) + +// +// MessageId: WU_E_DM_NEEDDOWNLOADREQUEST +// +// MessageText: +// +// An operation could not be completed because a download request is required from the download handler. +// +#define WU_E_DM_NEEDDOWNLOADREQUEST _HRESULT_TYPEDEF_(0x80246004L) + +// +// MessageId: WU_E_DM_NONETWORK +// +// MessageText: +// +// A download manager operation could not be completed because the network connection was unavailable. +// +#define WU_E_DM_NONETWORK _HRESULT_TYPEDEF_(0x80246005L) + +// +// MessageId: WU_E_DM_WRONGBITSVERSION +// +// MessageText: +// +// A download manager operation could not be completed because the version of Background Intelligent Transfer Service (BITS) is incompatible. +// +#define WU_E_DM_WRONGBITSVERSION _HRESULT_TYPEDEF_(0x80246006L) + +// +// MessageId: WU_E_DM_NOTDOWNLOADED +// +// MessageText: +// +// The update has not been downloaded. +// +#define WU_E_DM_NOTDOWNLOADED _HRESULT_TYPEDEF_(0x80246007L) + +// +// MessageId: WU_E_DM_FAILTOCONNECTTOBITS +// +// MessageText: +// +// A download manager operation failed because the download manager was unable to connect the Background Intelligent Transfer Service (BITS). +// +#define WU_E_DM_FAILTOCONNECTTOBITS _HRESULT_TYPEDEF_(0x80246008L) + +// +// MessageId: WU_E_DM_BITSTRANSFERERROR +// +// MessageText: +// +// A download manager operation failed because there was an unspecified Background Intelligent Transfer Service (BITS) transfer error. +// +#define WU_E_DM_BITSTRANSFERERROR _HRESULT_TYPEDEF_(0x80246009L) + +// +// MessageId: WU_E_DM_DOWNLOADLOCATIONCHANGED +// +// MessageText: +// +// A download must be restarted because the location of the source of the download has changed. +// +#define WU_E_DM_DOWNLOADLOCATIONCHANGED _HRESULT_TYPEDEF_(0x8024600AL) + +// +// MessageId: WU_E_DM_CONTENTCHANGED +// +// MessageText: +// +// A download must be restarted because the update content changed in a new revision. +// +#define WU_E_DM_CONTENTCHANGED _HRESULT_TYPEDEF_(0x8024600BL) + +// +// MessageId: WU_E_DM_UNEXPECTED +// +// MessageText: +// +// There was a download manager error not covered by another WU_E_DM_* error code. +// +#define WU_E_DM_UNEXPECTED _HRESULT_TYPEDEF_(0x80246FFFL) + +////////////////////////////////////////////////////////////////////////////// +// Setup/SelfUpdate errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_SETUP_INVALID_INFDATA +// +// MessageText: +// +// Windows Update Agent could not be updated because an INF file contains invalid information. +// +#define WU_E_SETUP_INVALID_INFDATA _HRESULT_TYPEDEF_(0x8024D001L) + +// +// MessageId: WU_E_SETUP_INVALID_IDENTDATA +// +// MessageText: +// +// Windows Update Agent could not be updated because the wuident.cab file contains invalid information. +// +#define WU_E_SETUP_INVALID_IDENTDATA _HRESULT_TYPEDEF_(0x8024D002L) + +// +// MessageId: WU_E_SETUP_ALREADY_INITIALIZED +// +// MessageText: +// +// Windows Update Agent could not be updated because of an internal error that caused setup initialization to be performed twice. +// +#define WU_E_SETUP_ALREADY_INITIALIZED _HRESULT_TYPEDEF_(0x8024D003L) + +// +// MessageId: WU_E_SETUP_NOT_INITIALIZED +// +// MessageText: +// +// Windows Update Agent could not be updated because setup initialization never completed successfully. +// +#define WU_E_SETUP_NOT_INITIALIZED _HRESULT_TYPEDEF_(0x8024D004L) + +// +// MessageId: WU_E_SETUP_SOURCE_VERSION_MISMATCH +// +// MessageText: +// +// Windows Update Agent could not be updated because the versions specified in the INF do not match the actual source file versions. +// +#define WU_E_SETUP_SOURCE_VERSION_MISMATCH _HRESULT_TYPEDEF_(0x8024D005L) + +// +// MessageId: WU_E_SETUP_TARGET_VERSION_GREATER +// +// MessageText: +// +// Windows Update Agent could not be updated because a WUA file on the target system is newer than the corresponding source file. +// +#define WU_E_SETUP_TARGET_VERSION_GREATER _HRESULT_TYPEDEF_(0x8024D006L) + +// +// MessageId: WU_E_SETUP_REGISTRATION_FAILED +// +// MessageText: +// +// Windows Update Agent could not be updated because regsvr32.exe returned an error. +// +#define WU_E_SETUP_REGISTRATION_FAILED _HRESULT_TYPEDEF_(0x8024D007L) + +// +// MessageId: WU_E_SELFUPDATE_SKIP_ON_FAILURE +// +// MessageText: +// +// An update to the Windows Update Agent was skipped because previous attempts to update have failed. +// +#define WU_E_SELFUPDATE_SKIP_ON_FAILURE _HRESULT_TYPEDEF_(0x8024D008L) + +// +// MessageId: WU_E_SETUP_SKIP_UPDATE +// +// MessageText: +// +// An update to the Windows Update Agent was skipped due to a directive in the wuident.cab file. +// +#define WU_E_SETUP_SKIP_UPDATE _HRESULT_TYPEDEF_(0x8024D009L) + +// +// MessageId: WU_E_SETUP_UNSUPPORTED_CONFIGURATION +// +// MessageText: +// +// Windows Update Agent could not be updated because the current system configuration is not supported. +// +#define WU_E_SETUP_UNSUPPORTED_CONFIGURATION _HRESULT_TYPEDEF_(0x8024D00AL) + +// +// MessageId: WU_E_SETUP_BLOCKED_CONFIGURATION +// +// MessageText: +// +// Windows Update Agent could not be updated because the system is configured to block the update. +// +#define WU_E_SETUP_BLOCKED_CONFIGURATION _HRESULT_TYPEDEF_(0x8024D00BL) + +// +// MessageId: WU_E_SETUP_REBOOT_TO_FIX +// +// MessageText: +// +// Windows Update Agent could not be updated because a restart of the system is required. +// +#define WU_E_SETUP_REBOOT_TO_FIX _HRESULT_TYPEDEF_(0x8024D00CL) + +// +// MessageId: WU_E_SETUP_ALREADYRUNNING +// +// MessageText: +// +// Windows Update Agent setup is already running. +// +#define WU_E_SETUP_ALREADYRUNNING _HRESULT_TYPEDEF_(0x8024D00DL) + +// +// MessageId: WU_E_SETUP_REBOOTREQUIRED +// +// MessageText: +// +// Windows Update Agent setup package requires a reboot to complete installation. +// +#define WU_E_SETUP_REBOOTREQUIRED _HRESULT_TYPEDEF_(0x8024D00EL) + +// +// MessageId: WU_E_SETUP_HANDLER_EXEC_FAILURE +// +// MessageText: +// +// Windows Update Agent could not be updated because the setup handler failed during execution. +// +#define WU_E_SETUP_HANDLER_EXEC_FAILURE _HRESULT_TYPEDEF_(0x8024D00FL) + +// +// MessageId: WU_E_SETUP_INVALID_REGISTRY_DATA +// +// MessageText: +// +// Windows Update Agent could not be updated because the registry contains invalid information. +// +#define WU_E_SETUP_INVALID_REGISTRY_DATA _HRESULT_TYPEDEF_(0x8024D010L) + +// +// MessageId: WU_E_SELFUPDATE_REQUIRED +// +// MessageText: +// +// Windows Update Agent must be updated before search can continue. +// +#define WU_E_SELFUPDATE_REQUIRED _HRESULT_TYPEDEF_(0x8024D011L) + +// +// MessageId: WU_E_SELFUPDATE_REQUIRED_ADMIN +// +// MessageText: +// +// Windows Update Agent must be updated before search can continue. An administrator is required to perform the operation. +// +#define WU_E_SELFUPDATE_REQUIRED_ADMIN _HRESULT_TYPEDEF_(0x8024D012L) + +// +// MessageId: WU_E_SETUP_WRONG_SERVER_VERSION +// +// MessageText: +// +// Windows Update Agent could not be updated because the server does not contain update information for this version. +// +#define WU_E_SETUP_WRONG_SERVER_VERSION _HRESULT_TYPEDEF_(0x8024D013L) + +// +// MessageId: WU_E_SETUP_UNEXPECTED +// +// MessageText: +// +// Windows Update Agent could not be updated because of an error not covered by another WU_E_SETUP_* error code. +// +#define WU_E_SETUP_UNEXPECTED _HRESULT_TYPEDEF_(0x8024DFFFL) + +////////////////////////////////////////////////////////////////////////////// +// expression evaluator errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_EE_UNKNOWN_EXPRESSION +// +// MessageText: +// +// An expression evaluator operation could not be completed because an expression was unrecognized. +// +#define WU_E_EE_UNKNOWN_EXPRESSION _HRESULT_TYPEDEF_(0x8024E001L) + +// +// MessageId: WU_E_EE_INVALID_EXPRESSION +// +// MessageText: +// +// An expression evaluator operation could not be completed because an expression was invalid. +// +#define WU_E_EE_INVALID_EXPRESSION _HRESULT_TYPEDEF_(0x8024E002L) + +// +// MessageId: WU_E_EE_MISSING_METADATA +// +// MessageText: +// +// An expression evaluator operation could not be completed because an expression contains an incorrect number of metadata nodes. +// +#define WU_E_EE_MISSING_METADATA _HRESULT_TYPEDEF_(0x8024E003L) + +// +// MessageId: WU_E_EE_INVALID_VERSION +// +// MessageText: +// +// An expression evaluator operation could not be completed because the version of the serialized expression data is invalid. +// +#define WU_E_EE_INVALID_VERSION _HRESULT_TYPEDEF_(0x8024E004L) + +// +// MessageId: WU_E_EE_NOT_INITIALIZED +// +// MessageText: +// +// The expression evaluator could not be initialized. +// +#define WU_E_EE_NOT_INITIALIZED _HRESULT_TYPEDEF_(0x8024E005L) + +// +// MessageId: WU_E_EE_INVALID_ATTRIBUTEDATA +// +// MessageText: +// +// An expression evaluator operation could not be completed because there was an invalid attribute. +// +#define WU_E_EE_INVALID_ATTRIBUTEDATA _HRESULT_TYPEDEF_(0x8024E006L) + +// +// MessageId: WU_E_EE_CLUSTER_ERROR +// +// MessageText: +// +// An expression evaluator operation could not be completed because the cluster state of the computer could not be determined. +// +#define WU_E_EE_CLUSTER_ERROR _HRESULT_TYPEDEF_(0x8024E007L) + +// +// MessageId: WU_E_EE_UNEXPECTED +// +// MessageText: +// +// There was an expression evaluator error not covered by another WU_E_EE_* error code. +// +#define WU_E_EE_UNEXPECTED _HRESULT_TYPEDEF_(0x8024EFFFL) + +////////////////////////////////////////////////////////////////////////////// +// UI errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_INSTALLATION_RESULTS_UNKNOWN_VERSION +// +// MessageText: +// +// The results of download and installation could not be read from the registry due to an unrecognized data format version. +// +#define WU_E_INSTALLATION_RESULTS_UNKNOWN_VERSION _HRESULT_TYPEDEF_(0x80243001L) + +// +// MessageId: WU_E_INSTALLATION_RESULTS_INVALID_DATA +// +// MessageText: +// +// The results of download and installation could not be read from the registry due to an invalid data format. +// +#define WU_E_INSTALLATION_RESULTS_INVALID_DATA _HRESULT_TYPEDEF_(0x80243002L) + +// +// MessageId: WU_E_INSTALLATION_RESULTS_NOT_FOUND +// +// MessageText: +// +// The results of download and installation are not available; the operation may have failed to start. +// +#define WU_E_INSTALLATION_RESULTS_NOT_FOUND _HRESULT_TYPEDEF_(0x80243003L) + +// +// MessageId: WU_E_TRAYICON_FAILURE +// +// MessageText: +// +// A failure occurred when trying to create an icon in the taskbar notification area. +// +#define WU_E_TRAYICON_FAILURE _HRESULT_TYPEDEF_(0x80243004L) + +// +// MessageId: WU_E_NON_UI_MODE +// +// MessageText: +// +// Unable to show UI when in non-UI mode; WU client UI modules may not be installed. +// +#define WU_E_NON_UI_MODE _HRESULT_TYPEDEF_(0x80243FFDL) + +// +// MessageId: WU_E_WUCLTUI_UNSUPPORTED_VERSION +// +// MessageText: +// +// Unsupported version of WU client UI exported functions. +// +#define WU_E_WUCLTUI_UNSUPPORTED_VERSION _HRESULT_TYPEDEF_(0x80243FFEL) + +// +// MessageId: WU_E_AUCLIENT_UNEXPECTED +// +// MessageText: +// +// There was a user interface error not covered by another WU_E_AUCLIENT_* error code. +// +#define WU_E_AUCLIENT_UNEXPECTED _HRESULT_TYPEDEF_(0x80243FFFL) + +////////////////////////////////////////////////////////////////////////////// +// reporter errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_REPORTER_EVENTCACHECORRUPT +// +// MessageText: +// +// The event cache file was defective. +// +#define WU_E_REPORTER_EVENTCACHECORRUPT _HRESULT_TYPEDEF_(0x8024F001L) + +// +// MessageId: WU_E_REPORTER_EVENTNAMESPACEPARSEFAILED +// +// MessageText: +// +// The XML in the event namespace descriptor could not be parsed. +// +#define WU_E_REPORTER_EVENTNAMESPACEPARSEFAILED _HRESULT_TYPEDEF_(0x8024F002L) + +// +// MessageId: WU_E_INVALID_EVENT +// +// MessageText: +// +// The XML in the event namespace descriptor could not be parsed. +// +#define WU_E_INVALID_EVENT _HRESULT_TYPEDEF_(0x8024F003L) + +// +// MessageId: WU_E_SERVER_BUSY +// +// MessageText: +// +// The server rejected an event because the server was too busy. +// +#define WU_E_SERVER_BUSY _HRESULT_TYPEDEF_(0x8024F004L) + +// +// MessageId: WU_E_REPORTER_UNEXPECTED +// +// MessageText: +// +// There was a reporter error not covered by another error code. +// +#define WU_E_REPORTER_UNEXPECTED _HRESULT_TYPEDEF_(0x8024FFFFL) + +// +// MessageId: WU_E_OL_INVALID_SCANFILE +// +// MessageText: +// +// An operation could not be completed because the scan package was invalid. +// +#define WU_E_OL_INVALID_SCANFILE _HRESULT_TYPEDEF_(0x80247001L) + +// +// MessageId: WU_E_OL_NEWCLIENT_REQUIRED +// +// MessageText: +// +// An operation could not be completed because the scan package requires a greater version of the Windows Update Agent. +// +#define WU_E_OL_NEWCLIENT_REQUIRED _HRESULT_TYPEDEF_(0x80247002L) + +// +// MessageId: WU_E_OL_UNEXPECTED +// +// MessageText: +// +// Search using the scan package failed. +// +#define WU_E_OL_UNEXPECTED _HRESULT_TYPEDEF_(0x80247FFFL) + +#endif //_WUERROR_ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/iisca.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/iisca.wxs new file mode 100644 index 0000000000..5bf076f74d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/iisca.wxs @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLCA AND NOT( REMOVE="ALL" ) + NOT SKIPUNINSTALLCA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLWINDOWSHOTFIX + NOT SKIPREBOOTIFREQUIRED + + + + + + + + + + + + + + + + + NOT SKIPMAKESHORTCUTELEVATED + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPSETCONSOLEPROPERTIES + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLHTTPLISTENER + NOT SKIPUNINSTALLHTTPLISTENER + + + + + + + + + + + Installed And PATCH + Installed And PATCH + Installed And PATCH + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/setupstrings.wxl new file mode 100644 index 0000000000..ccb1a67cfb --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/setupstrings.wxl @@ -0,0 +1,255 @@ + + + + + + + 1033 + + + + Shared Config Install Options + Select option for installation to IIS shared configuration + Update shared configuration on install + You are installing this module onto an IIS server that is using shared configuration. If additional IIS servers are using this shared configuration then you will need to install this module onto all of these machines. To minimize disruption of the individual web servers you will need to install this module in the following steps: First, on all but the last of the machines you should install the module without updating shared config. Do this by not selecting the checkbox + below. This will install all binaries and files necessary for the module on each machine without making any changes to shared config. Second, on the last machine you will need to verify that the user idenity you are running under has read and write access to the applicationhost.config file on the UNC share. Then you should install the module and select the update shared config option below. + + + Initializing WebConfig custom action + Updating web.config + + + + IIS Advanced Logging + Enables advanced logging of IIS pipeline data. + IIS Advanced Logging + Enables creation of custom log files with extensible field selection. + Update for IIS Advanced Logging + + + + IIS Transform Manager + Beta + Enables the Transform Manager IIS Media Services. + IIS Transform Manager + Enables creation of media transforms. + IIS Transform Manager Host + Service host for [ProductName]. + IIS Transform Manager + Batch convert on-demand media files to alternate file and container formats. + An IIS Transform Manager 1.0 Expression Encoder SP Task package is installed on the computer. You must uninstall it before you can install [ProductName]. + + Microsoft .NET Framework 3.5 is required to install [ProductName]. Use the 'Add Features Wizard' in Server Manager to install .NET Framework 3.5.1 Features or use 'Turn Windows features on or off' to turn on Microsoft .NET Framework 3.5. + [ProductName] requires Microsoft Windows Vista Service Pack 1 or later. + [ProductName] cannot be installed on Vista Home Basic. + [ProductName] requires Microsoft Windows 7 Service Pack 1 or later. + + + Microsoft Web Management Service 2 + Microsoft Web Management Service + Installs the basic features of the [ProductName]. + Microsoft Web Management Service 2 + The Web Management Service enables remote and delegated management capabilities for administrators to manage for the Web server, sites and applications present on this machine. + + + Microsoft URL Rewrite Module 1.1 for IIS 7 + Update for URL Rewrite Module 1.1 for IIS 7 + URL Rewrite + Enables URL and content rewriting capabilities to IIS 7. + User Interface + Configures the URL Rewrite Module feature in IIS Manager. + + + IIS URL Rewrite Module 2 + Update for IIS URL Rewrite Module 2 + URL Rewrite + Enables URL and content rewriting capabilities to IIS 7. + User Interface + Configures the URL Rewrite Module feature in IIS Manager. + + + Administration Pack for IIS 7.0 + Installs the basic features of the [ProductName]. + 1252 + Administration Pack for IIS 7.0 + Microsoft Corporation + This version of the operating system is not supported. [ProductName] can be installed only on Windows Server 2008, or Windows Vista Service Pack 1, and higher. + ASP.Net Features + ASP.NET includes Authorization and Error Pages features, which let you manage your authorization and custom error settings. + Authentication + ASP.Net Authentication Description. + Authorization + ASP.NET Authorization lets you configure rules for authorizing users to access your Web sites and applications. + Error Pages + ASP.NET Error Pages lets you configure HTTP error responses to return when errors occur. + Modules + ASP.Net Modules Description. + Handlers + ASP.Net Handers Description. + Configuration Editor + Configuration Editor lets you manage your configuration files in IIS Manager by letting you edit sections, attributes, elements, and collections in your configuration files. + Request Filtering + Request Filtering lets you configure filtering rules for your Web site, and restrict protocol and content behavior. + Fast CGI + FastCGI lets you configure process pool settings for the FastCGI applications on your Web server. + + + Dynamic IP Restrictions for IIS 7 Setup + + + + + + + + + + + + + Dynamic IP Restrictions for IIS 7 - Beta + Dynamic IP Restrictions for IIS 7 - Beta 2 + Dynamic IP Restrictions for IIS 7 - Beta 3 + + Dynamic IP Restrictions for IIS 7 - Release Candidate + Dynamic IP Restrictions for IIS 7 - Release Candidate 2 + Dynamic IP Restrictions for IIS 7 - Release Candidate 3 + + Dynamic IP Restrictions for IIS 7 + + Dynamic IP Restrictions for IIS 7 + Dynamic IP Restrictions User Interface for IIS 7 + + Dynamic IP Restrictions for IIS 7 - Beta was found on this machine. Please uninstall it and try again + + + WebDAV 7.5 For IIS 7.0 + The IIS 7.0 CoreWebEngine and W3SVC features must be installed to use this product. + WebDAV Server Module + WebDAV Administration User Interface + + + IIS Search Engine Optimization Toolkit 1.0 + IIS Search Engine Optimization Toolkit 1.0 + Search Engine Optimization (SEO) Toolkit 1.0 + This installer database contains the logic and data required to install IIS Search Engine Optimization Toolkit 1.0. + + + IIS Editor + + + IIS Reports + Log Parser is not installed on this machine, Please install Log Parser 2.2 from http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 and then proceed with IIS Reports installation + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework is a requisite for installing Application Request Routing. Please install the Web Farm Framework. + Microsoft Application Request Routing 3.0 + Runtime + Adds the Application Request Routing capabilities to IIS. + User Interface + Configures the Application Request Routing feature in IIS Manager. + + + Microsoft CORS Module + IIS CORS Runtime + Adds the support of cross-origin resource sharing (CORS) to IIS. + + + Microsoft IIS Compression + IIS Compression + Adds the Zlib and Brotli compression schemes to IIS. + + + IIS Team Template Module + Template Module Runtime + An example of an IIS module. + + + Microsoft Windows PowerShell snap-in for IIS 7.0 + + + IIS Manager Publishing for IIS 7.0 + Publishing User Interface + + + Application Warm-Up 1.0 for IIS 7.5 + + + + An incompatible product, [CONFLICTING_PRODUCT_NAME], is on this computer. Installation of [ProductName] cannot continue. To install this product, use Add/Remove Programs on the Control Panel to remove [CONFLICTING_PRODUCT_NAME]. + Administrator privilege is required to install [ProductName]. + IIS Version 7.0 is required to use [ProductName]. + IIS Version 7.0 or greater is required to install [ProductName]. + IIS Version 7.5 or greater is required to install [ProductName]. + IIS Version 7 or 7.5 is required to install [ProductName]. + IIS Version 8.0 or greater is required to install [ProductName]. + The beta version of [ProductName] was found on this machine. + A newer version of [ProductName] was found on this machine. + Setup cannot continue because another instance of [ProductName] is already installed on this computer. Please uninstall it first and then re-launch this installation. + The IIS 7.0 CoreWebEngine and W3SVC features must be installed to use [ProductName]. + The IIS Management Console must be installed to use [ProductName]. + Please stop both services Windows Process Activation Service (WAS) and Web Management Service (WMSvc) before installing [ProductName]. You will need to start the services after installing [ProductName]. + IIS Metabase is required to install [ProductName]. + The 64-bit version of [ProductName] cannot be installed on a 32-bit edition of Microsoft Windows. + The 32-bit version of [ProductName] cannot be installed on a 64-bit edition of Microsoft Windows. + Microsoft .NET Framework Version 2.0 or greater is required to install [ProductName]. + Microsoft .NET Framework Version 3.5 or greater is required to install [ProductName]. Use 'Add Features' under the Server Manager to install Microsoft .Net Version 3.5. + Microsoft .NET Framework Version 4.0 or greater is required to install [ProductName]. + Please install Microsoft .NET Framework Version 2.0 Service Pack 1 (or a later service pack), before installing [ProductName]. + The Windows Update (wuauserv) service cannot be disabled, it is required to install [ProductName]. + The PowerShell snap-in is part of Windows Operating System. Please install it via 'Programs and Features' or 'Server Manager'. + Microsoft Web Platform Installer Version 3.0 or greater is required to install [ProductName]. + + Setup failed to detect shared configuration. + Shared configuration is enabled for IIS. Installing [ProductName] is not supported when using shared configuration. Please disable shared configuration before installing this feature. + + Please stop World Wide Web Publishing Service (W3SVC) before installing [ProductName]. You will need to start the service after installation. + IIS PowerShell Management Console + IIS PowerShell snap-in + IIS PowerShell snap-in requires PowerShell v1.0 or v2.0 installed + IIS PowerShell snap-in requires WAS and configuration installed + This is a bogus string. + + + Microsoft Web Farm Framework Version 2.2 + Microsoft Web Farm Agent Version 2.2 + Web Farm Service + Web Farm Service + Web Farm Controller Service + Web Farm Controller Service + Web Farm Agent Service + Web Farm Agent Service + Web Platform Installer is a pre-requisite for installing Web Farm Framework. Please install the Web Plaform Installer from http://www.microsoft.com/web/downloads/platform.aspx. + Web Deployment Tool is a pre-requisite for installing Web Farm Framework. Please install the Web Deployment Tool from http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Web Hosting roles and features. + Hosting Framework + Hosting Framework provides API's and PowerShell commands for managing the Web Hosting. + Web Role + Web Role installs Dynamic WAS service and URL Rewrite provider for Web Hosting. + Antares Express + Deploys a Control Panel configuration optimized for single machine setup. + Load Balancer Role + Load Balancer Role configures Application Request Router to route based on Web Hosting rules. + Hosting Controller + Hosting Controller extends the Web Farm Framework 2.0 to work with Web Hosting. + Publishing Role + Installs support for Web Deploy and FTP publishing. + This is a PowerShell snap-in that contains cmdlets for managing Microsoft Web Hosting infrastructure. + Dynamic WAS Service + Windows Process Activation service optimized for high density Web Hosting. + Resource Metering Service + Installs the Resource Metering service that enables collecting and publishing both runtime and health information. + Resource Metering + Enables collecting and publishing runtime and health information from Web Role. + Hosting Quota Enforcement + Monitors the web sites resource usage and executes custom actions when usage quota is exceeded. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ElevatedShortcut.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ElevatedShortcut.wxi new file mode 100644 index 0000000000..ee5e988a1b --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ElevatedShortcut.wxi @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + NOT SKIPMAKESHORTCUTELEVATED + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/FixPatchingBehavior.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/FixPatchingBehavior.wxi new file mode 100644 index 0000000000..ae6e3b76d5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/FixPatchingBehavior.wxi @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + Installed And PATCH + Installed And PATCH + Installed And PATCH + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/HttpListener.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/HttpListener.wxi new file mode 100644 index 0000000000..68db6852d1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/HttpListener.wxi @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLHTTPLISTENER + NOT SKIPUNINSTALLHTTPLISTENER + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ShortcutConsoleProperties.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ShortcutConsoleProperties.wxi new file mode 100644 index 0000000000..236e0f51ef --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ShortcutConsoleProperties.wxi @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPSETCONSOLEPROPERTIES + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/WindowsHotfix.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/WindowsHotfix.wxi new file mode 100644 index 0000000000..78b26d6404 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/WindowsHotfix.wxi @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLWINDOWSHOTFIX + NOT SKIPREBOOTIFREQUIRED + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/iisca.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/iisca.wxs new file mode 100644 index 0000000000..68324e1484 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/iisca.wxs @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLCA + (NOT SKIPUNINSTALLCA) AND (IISCOREWEBENGINEINSTALLED = "#1") AND (IISW3SVCINSTALLED = "#1") + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/include.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/include.wxi new file mode 100644 index 0000000000..e22cdce8a4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/include.wxi @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHS/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHS/misc/setupstrings.wxl new file mode 100644 index 0000000000..3acd415df3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHS/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 2052 + + + + 共享配置安装选项 + 选择用于安装到 IIS 共享配置的选项 + 安装时更新共享配置 + 您要将此模块安装到使用共享配置的 IIS 服务器上。如果其他 IIS 服务器正在使用此共享配置,则您需要将此模块安装到所有这些计算机上。为了尽可能减少对各个 Web 服务器的中断,您需要按以下步骤安装此模块: 首先,在除最后一台计算机外的所有其他计算机上,安装此模块但不更新共享配置。可通过不选中下面的复选框来执行 +此操作。这将在每台计算机上安装模块所需的所有二进制文件和其他文件,而不对共享配置进行任何更改。其次,在最后一台计算机上,您需要确保运行时使用的用户标识对 UNC 共享上的 applicationhost.config 文件具有读取和写入权限。然后,您应安装此模块并选中下面的更新共享配置选项。 + + + 正在初始化 WebConfig 自定义操作 + 正在更新 web.config + + + + IIS 高级日志 + 启用 IIS 管道数据高级日志。 + IIS 高级日志 + 允许通过选择可扩展的字段来创建自定义日志文件。 + 适用于 IIS 高级日志记录的更新 + + + + IIS Transform Manager + Beta + 启用 Transform Manager IIS 媒体服务。 + IIS Transform Manager + 允许创建媒体转换。 + IIS Transform Manager 主机 + [ProductName] 的服务主机。 + IIS Transform Manager + 根据需要将媒体文件批量转换为其他文件和容器格式。 + 计算机上安装了某个 IIS Transform Manager 1.0 表达式编码器 SP 任务包。您必须先将它卸载,然后才能安装 [ProductName]。 + + 安装 [ProductName] 需要 Microsoft .NET Framework 3.5。可在服务器管理器中使用“添加功能向导”来安装 .NET Framework 3.5.1 功能,或使用“打开或关闭 Windows 功能”来打开 Microsoft .NET Framework 3.5。 + + + + IIS 数字版权管理 + Beta + 启用平滑流式处理演示的数字版权管理。 + + + 未安装 ASP.NET + + + + + + + + + 此计算机上找到了 IIS 平滑流式处理 - Beta。无法继续安装 [ProductName]。若要安装此产品,请使用控制面板中的“添加/删除程序”将 IIS 平滑流式处理 - Beta 删除。 + 此计算机上装有 IIS Media Services 的不兼容版本。无法继续安装 [ProductName]。若要安装此产品,请使用控制面板中的“添加/删除程序”将 IIS Media Services 删除。 + 此计算机上已安装了该产品的新版本,或者可以在此计算机上安装该产品的新版本。无法继续安装 [ProductName]。若要安装该产品的新版本,请使用控制面板上的“添加/删除程序”更新 IIS Media Services。 + 需要进行播放列表文件转换 + + + + + 发现早期版本的 IIS Media Services 文件 + + + + + 发现 Beta IIS Media Services 文件 + + + + + + IIS Media Pack 1.0 + 适用于 IIS Media Pack 1.0 的更新 + IIS Media Services 2.0 + 适用于 IIS Media Services 2.0 的更新 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + 适用于 IIS Media Services 3.0 的更新 + IIS Media Services 功能和工具。 + IIS Media Services 5 Premium 功能和工具。 + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web 播放列表 + 对客户端播放在播放列表中引用的媒体资产的行为进行控制。 + 会话帮助程序 + 启用 ASP.NET 会话状态持续性。(需要适用于 Web 服务器(IIS)的 ASP.NET 角色服务)。 + 用户界面 + 在 IIS 管理器中配置 Web 播放列表功能。 + + 比特率限制 + 对客户端下载的文件的传送进行限制,从而节省带宽。 + 用户界面 + 在 IIS 管理器中配置比特率限制功能。 + + 资产 + 对客户端的按需资产启用 HTTP 自适应流式处理。 + 用户界面 + 在 IIS 管理器中配置平滑流式处理功能。 + + 频道 + 对客户端的频道广播启用 HTTP 自适应流式处理。 + 用户界面 + 在 IIS 管理器中配置实时平滑流式处理功能。 + + 数字版权管理 + 提供平滑流式处理媒体的加密和许可。 + 用户界面 + 配置 IIS 管理器中的数字版权管理功能。 + + [ProductName] 需要 Microsoft Windows Vista Service Pack 1 或更高版本。 + 无法在 Vista Home Basic 上安装 [ProductName]。 + [ProductName] 需要 Microsoft Windows 7 Service Pack 1 或更高版本。 + + + IIS 数据库管理器 + IIS 数据库管理器 + + + Microsoft Web 管理服务 2 + Microsoft Web 管理服务 + 安装 [ProductName] 的基本功能。 + Microsoft Web 管理服务 2 + Web 管理服务提供远程和委派管理功能,供管理员管理位于此计算机上的 Web 服务器、站点和应用程序。 + + + 用于 IIS 7 的 Microsoft URL 重写模块 1.1 + 对用于 IIS 7 的 URL 重写模块 1.1 的更新 + URL 重写 + 对 IIS 7 启用 URL 和内容重写功能。 + 用户界面 + 在 IIS 管理器中配置 URL 重写模块功能。 + + + IIS URL 重写模块 2 + 适用于 IIS URL 重写模块 2 的更新 + URL 重写 + 对 IIS 7 启用 URL 和内容重写功能。 + 用户界面 + 在 IIS 管理器中配置 URL 重写模块功能。 + + + Administration Pack for IIS 7.0 + 安装 [ProductName] 的基本功能。 + 1252 + Administration Pack for IIS 7.0 + Microsoft Corporation + 不支持此操作系统版本。[ProductName] 只能安装在 Windows Server 2008 或 Windows Vista Service Pack 1 及更高版本上。 + ASP.Net 功能 + ASP.NET 包括“授权”和“错误页”功能,利用这些功能,您可以管理您的授权和自定义错误设置。 + 身份验证 + ASP.Net 身份验证说明。 + 授权 + 利用 ASP.NET 授权,您可以配置规则,以便允许用户访问您的网站和应用程序。 + 错误页 + 利用 ASP.NET 错误页,您可以配置要在发生错误时返回的 HTTP 错误响应。 + 模块 + ASP.Net 模块说明。 + 处理程序 + ASP.Net 处理程序说明。 + 配置编辑器 + 利用配置编辑器,您可以编辑配置文件中的节、属性、元素和集合,从而在 IIS 管理器中管理配置文件。 + 请求筛选 + 利用请求筛选,您可以为您的网站配置筛选规则,并限制协议和内容行为。 + FastCGI + 利用 FastCGI,您可以在 Web 服务器上为 FastCGI 应用程序配置进程池设置。 + + + 安装 Dynamic IP Restrictions for IIS 7 + + + + + + + + + + + + + Dynamic IP Restrictions for IIS 7 - Beta + Dynamic IP Restrictions for IIS 7 - Beta 2 + Dynamic IP Restrictions for IIS 7 - Beta 3 + + Dynamic IP Restrictions for IIS 7 - 候选发布 + Dynamic IP Restrictions for IIS 7 - 候选发布 2 + Dynamic IP Restrictions for IIS 7 - 候选发布 3 + + Dynamic IP Restrictions for IIS 7 - RTW + + Dynamic IP Restrictions for IIS 7 + Dynamic IP Restrictions for IIS 7 用户界面 + + IIS 7 的动态 IP 限制 - 在此计算机上找到 Beta 版本。请卸载它,然后重试 + + + WebDAV 7.5 For IIS 7.0 + 若要使用此产品,必须安装 IIS 7.0 CoreWebEngine 和 W3SVC 功能。 + WebDAV 服务器模块 + WebDAV 管理用户界面 + + + IIS 搜索引擎优化工具包 1.0 + IIS 搜索引擎优化工具包 1.0 + 搜索引擎优化(SEO)工具包 1.0 + 此安装程序数据库包含安装 IIS 搜索引擎优化工具包 1.0 所需的逻辑和数据。 + + + IIS 编辑器 + + + IIS Reports + 未在此计算机上安装 Log Parser,请通过 http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 安装 Log Parser 2.2,然后继续安装 IIS Reports + + + 未找到系统必备包。请运行 setup.exe 以解析依赖关系并安装此程序。 + Microsoft SQL Server 2008 管理对象是安装 IIS 数据库管理器的必备组件。可以从 http://go.microsoft.com/fwlink/?LinkID=150946 安装 Micrsoft SQL Server 2008 管理对象。 + Microsoft SQL Server System CLR Types 是安装 IIS 数据库管理器的必备组件。可以从 http://go.microsoft.com/fwlink/?LinkID=150949 安装 Microsoft SQL Server System CLR Types。 + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework 是安装 Application Request Routing 的必备组件。请安装 Web Farm Framework。 + Microsoft Application Request Routing 2.5 + 运行时 + 向 IIS 7 添加 Application Request Routing 功能。 + 用户界面 + 在 IIS 管理器中配置应用程序请求路由功能。 + + + 用于 IIS 7.0 的 Microsoft Windows PowerShell 管理单元 + + + Microsoft Web 平台安装程序 4.0 + Microsoft Web 平台安装程序 + [ProductName] 需要 Windows XP SP2、Windows 2003 SP1、Windows Vista 或更高版本。 + [ProductName] 需要 Windows XP Service Pack 3、Windows Server 2003 Service Pack 2 或更高版本。 + + + Microsoft Windows Azure 服务安装程序 + Microsoft Windows Azure 服务安装程序 + + + Internet Information Services (IIS) 7+ 管理器 + IIS 管理器客户端 + 远程支持 + 此产品需要 Windows XP SP2、Windows 2003 SP1、Windows Vista SP1 或 Windows 7 或更高版本 + 未安装 IIS 管理控制台,但需要此控制台才能管理远程 IIS 服务器。在安装远程管理支持之前,请先安装 IIS 管理控制台,方法是打开“控制面板”->“程序”->“打开或关闭 Windows 功能”,然后在 Ineternet Information Services 功能中选择 IIS 管理控制台。 + 此产品在 Windows Server 2008、Windows Server 2008 R2 或更高版本中不是必需的。请打开服务器管理器并在 Web 服务器角色的角色服务中选择 IIS 管理控制台,从而安装 IIS 管理控制台。 + + + IIS Manager Publishing for IIS 7.0 + Publishing 用户界面 + + + Application Warm-Up 1.0 for IIS 7.5 + + + + 此计算机上安装了不兼容的产品 [CONFLICTING_PRODUCT_NAME]。无法继续安装 [ProductName]。要安装此产品,请使用控制面板上的“添加/删除程序”来删除 [CONFLICTING_PRODUCT_NAME]。 + 若要安装 [ProductName],需要管理员特权。 + 若要使用 [ProductName],需要 IIS 7.0 版。 + 若要安装 [ProductName],需要 IIS 7.0 版或更高版本。 + 安装 [ProductName] 必须具有 IIS 7.5 版或更高版本。 + 要安装 [产品名称],要求使用 IIS 版本 7 或 7.5。 + 已在此计算机上找到 [ProductName] 的 Beta 版本。 + 已在此计算机上找到 [ProductName] 的新版本。 + 安装程序无法继续,因为已在此计算机上安装了另一个 [ProductName] 实例。请先将其卸载,然后重新启动此安装。 + 若要使用 [ProductName],必须安装 IIS 7.0 CoreWebEngine 和 W3SVC 功能。 + 要使用 [ProductName],必须安装 IIS 管理控制台。 + 请先停止 Windows Process Activation Service (WAS)和 Web 管理服务(WMSvc),然后安装 [ProductName]。您将需要在安装 [ProductName] 后启动这两个服务。 + 若要安装 [ProductName],需要 IIS 元数据库。 + 无法在 32 位版本的 Microsoft Windows 上安装 64 位版本的 [ProductName]。 + 无法在 64 位版本的 Microsoft Windows 上安装 32 位版本的 [ProductName]。 + 若要安装 [ProductName],需要 Microsoft .NET Framework 2.0 版或更高版本。 + 需要有 Microsoft .NET Framework 3.5 版或更高版本才能安装 [ProductName]。使用“服务器管理器”下的“添加功能”可安装 Microsoft .Net 3.5 版。 + 需要有 Microsoft .NET Framework 4.0 版或更高版本才能安装 [ProductName]。 + 请先安装 Microsoft .NET Framework 2.0 Service Pack 1(或更高版本的 Service Pack),然后再安装 [ProductName]。 + 不能禁用 Windows Update (wuauserv)服务,安装 [ProductName] 需要此服务。 + PowerShell 管理单元是 Windows 操作系统的一部分。请通过“程序和功能”或“服务器管理器”来安装它。 + 需要有 Microsoft Web 平台安装程序 3.0 版或更高版本才能安装 [ProductName]。 + + 安装程序无法检测到共享配置。 + 已为 IIS 启用了共享配置。使用共享配置时,不支持安装 [ProductName]。请先禁用共享配置,然后再安装此功能。 + + 请在安装 [ProductName] 之前停止 World Wide Web 发布服务(W3SVC)。您将需要在安装后启动此服务。 + IIS PowerShell 管理控制台 + IIS PowerShell 管理单元 + IIS PowerShell 管理单元要求安装 PowerShell v1.0 或 v2.0 + IIS PowerShell 管理单元要求安装 WAS 和配置 + 这是一个假字符串。 + + + Microsoft Web Farm Framework 版本 2.2 + Microsoft Web 场代理版本 2.2 + Web 场服务 + Web 场服务 + Web 场控制器服务 + Web 场控制器服务 + Web 场代理服务 + Web 场代理服务 + Web 平台安装程序是安装 Web Farm Framework 的必备组件。请从 http://www.microsoft.com/web/downloads/platform.aspx 安装 Web 平台安装程序。 + Web 部署工具是安装 Web Farm Framework 的必备组件。请从 http://www.iis.net/download/WebDeploy 安装 Web 部署工具。 + + + Microsoft Web Hosting 框架 + Web Hosting 框架 + Web Hosting 角色和功能。 + Hosting 框架 + Hosting 框架提供用于管理 Web Hosting 的 API 和 PowerShell 命令。 + Web 角色 + Web 角色为 Web Hosting 安装动态 WAS 服务和 URL 重写提供程序。 + Antares Express + 部署已针对单一计算机设置优化的控制面板配置。 + 负载平衡器角色 + 负载平衡器将应用程序请求路由器配置为基于 Web Hosting 规则进行路由。 + Hosting 控制器 + Hosting 控制器扩展了 Web Farm Framework 2.0,使之能够与 Web Hosting 一起使用。 + 发布角色 + 安装针对 Web Deploy 和 FTP 发布功能的支持。 + 这是 PowerShell 管理单元,其中包含用于管理 Microsoft Web Hosting 基础架构的 cmdlet。 + 动态 WAS 服务 + 已为高密度 Web Hosting 优化了 Windows Process Activation Service。 + 资源计量服务 + 安装资源计量服务,该服务可以收集和发布运行时信息和运行状况信息。 + 资源计量 + 允许从 Web 角色收集和发布运行时信息与运行状况信息。 + 强制实施宿主配额 + 监视网站资源使用情况,并在超出使用配额时执行自定义操作。 + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHT/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHT/misc/setupstrings.wxl new file mode 100644 index 0000000000..fc4295abf7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHT/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1028 + + + + 共用設定安裝選項 + 請選取安裝 IIS 共用設定的選項 + 在安裝時更新共用設定 + 您正在將這個模組安裝到使用共用設定的 IIS 伺服器上。如果有其他 IIS 伺服器也使用這個共用設定,您必須將這個模組安裝到所有電腦。若要將個別網頁伺服器發生中斷的情形降至最低,您必須依照下列步驟安裝這個模組: 首先,在所有電腦上 (最後一部電腦例外) 安裝模組,而且不要更新共用設定。請不要選取下面的核取方塊。 +這將會為每部電腦上的模組安裝所有二進位檔和必要檔案,而不會對共用設定進行任何變更。第二,在最後一部電腦上,您必須確認執行作業所使用的使用者識別具有讀取和寫入 UNC 共用上 applicationhost.config 檔案的權限。然後,您應安裝模組並選取下面的更新共用設定選項。 + + + 正在初始化 WebConfig 自訂動作 + 正在更新 web.config + + + + IIS 進階記錄 + 啟用 IIS 管線資料的進階記錄。 + IIS 進階記錄 + 啟用以可延伸的欄位選擇建立自訂記錄檔。 + IIS Advanced Logging 的更新 + + + + IIS Transform Manager + Beta + 啟用 Transform Manager IIS Media Services。 + IIS Transform Manager + 啟用媒體轉換的建立。 + IIS Transform Manager 主機 + [ProductName] 的服務主機。 + IIS Transform Manager + 將隨選媒體檔案批次轉換為替代的檔案及容器格式。 + IIS Transform Manager 1.0 Expression Encoder SP Task 套件已安裝於電腦。您必須先將它解除安裝,才能安裝 [ProductName]。 + + 需要 Microsoft .NET Framework 3.5 才能安裝 [ProductName]。請使用 [\[]伺服器管理員[\]] 中的 [\[]新增功能精靈[\]] 安裝 .NET Framework 3.5.1 功能,或者使用 [\[]開啟或關閉 Windows 功能[\]] 開啟 Microsoft .NET Framework 3.5。 + + + + IIS 數位版權管理 + Beta + 啟用 Smooth Streaming 展示檔的數位版權管理。 + + + 未安裝 ASP.NET + + + + + + + + + 在這部電腦上找到 IIS Smooth Streaming - Beta。[ProductName] 的安裝無法繼續。若要安裝這個產品,請使用 [控制台] 中的 [新增/移除程式] 移除 IIS Smooth Streaming - Beta。 + 這部電腦已經安裝不相容版本的 IIS Media Services。[ProductName] 的安裝無法繼續。若要安裝這個產品,請使用 [控制台] 中的 [新增/移除程式] 移除 IIS Media Services。 + 這部電腦可能已安裝這個產品的新版本或有新版本可供安裝。[ProductName] 的安裝無法繼續。若要安裝這個產品的新版本,請使用 [控制台] 中的 [新增/移除程式] 更新 IIS Media Services。 + 需要播放清單檔案轉換 + + + + + 找到舊的 IIS Media Services 檔案 + + + + + 找到 Beta IIS Media Services 檔案 + + + + + + IIS Media Pack 1.0 + IIS Media Pack 1.0 的更新 + IIS Media Services 2.0 + IIS Media Services 2.0 的更新 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + IIS Media Services 3.0 的更新 + IIS Media Services 功能和工具。 + IIS Media Services 5 Premium 功能及工具。 + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web 播放清單 + 控制播放清單中參考之媒體資產的用戶端播放方式。 + Session Helper + 啟用 ASP.NET 工作階段狀態持續性 (需要網頁伺服器 (IIS) 的 ASP.NET 角色服務)。 + 使用者介面 + 設定 IIS 管理員中的 Web 播放清單功能。 + + 位元速度節流設定 + 藉由節流設定傳遞用戶端下載的檔案,以節省頻寬。 + 使用者介面 + 設定 IIS 管理員中的位元速度節流設定功能。 + + 資產 + 啟用對用戶端的隨選資產 HTTP 彈性資料流。 + 使用者介面 + 設定 IIS 管理員中的 Smooth Streaming 功能。 + + 通道 + 啟用對用戶端的通道廣播 HTTP 彈性資料流。 + 使用者介面 + 設定 IIS 管理員中的 Live Smooth Streaming 功能。 + + 數位版權管理 + 提供 Smooth Streaming 媒體的加密和授權。 + 使用者介面 + 設定 IIS 管理員中的數位版權管理功能。 + + [ProductName] 需要 Microsoft Windows Vista Service Pack 1 或更新版本。 + 無法將 [ProductName] 安裝在 Vista Home Basic 上。 + [ProductName] 需要 Microsoft Windows 7 Service Pack 1 或更新版本。 + + + IIS Database Manager + IIS Database Manager + + + Microsoft Web Management Service 2 + Microsoft Web Management Service + 安裝 [ProductName] 的基本功能。 + Microsoft Web Management Service 2 + Web Management Service 可啟用遠端及委派管理功能,讓系統管理員管理呈現在這部電腦上的網頁伺服器、站台及應用程式。 + + + Microsoft URL Rewrite Module 1.1 for IIS 7 + URL Rewrite Module 1.1 for IIS 7 的更新 + URL Rewrite + 啟用 IIS 7 的 URL 和內容重寫功能。 + 使用者介面 + 設定 IIS 管理員中的 URL Rewrite Module 功能。 + + + IIS URL Rewrite Module 2 + IIS URL Rewrite Module 2 的更新 + URL Rewrite + 啟用 IIS 7 的 URL 和內容重寫功能。 + 使用者介面 + 設定 IIS 管理員中的 URL Rewrite Module 功能。 + + + Administration Pack for IIS 7.0 + 安裝 [ProductName] 的基本功能。 + 1252 + Administration Pack for IIS 7.0 + Microsoft Corporation + 不支援這個版本的作業系統。[ProductName] 只能安裝在 Windows Server 2008 或 Windows Vista Service Pack 1 和更新版本上。 + ASP.NET 功能 + ASP.NET 包含授權和錯誤網頁功能,可讓您管理授權和自訂錯誤訊息。 + 驗證 + ASP.NET 驗證描述。 + 授權 + ASP.NET 授權可讓您設定規則,來授權使用者存取您的網站和應用程式。 + 錯誤網頁 + ASP.NET 錯誤網頁可讓您設定發生錯誤時要傳回的 HTTP 錯誤回應。 + 模組 + ASP.NET 模組描述。 + 處理常式 + ASP.NET 處理常式描述。 + 設定編輯器 + 設定編輯器可讓您管理 IIS 管理員中的設定檔案,讓您編輯設定檔案中的區段、屬性、元素和集合。 + 要求篩選 + 要求篩選可讓您為網站設定篩選規則,並限制通訊協定和內容的行為。 + Fast CGI + FastCGI 可讓您設定您的網頁伺服器上 FastCGI 應用程式的處理序集區設定。 + + + Dynamic IP Restrictions for IIS 7 安裝程式 + + + + + + + + + + + + + Dynamic IP Restrictions for IIS 7 - Beta + Dynamic IP Restrictions for IIS 7 - Beta 2 + Dynamic IP Restrictions for IIS 7 - Beta 3 + + Dynamic IP Restrictions for IIS 7 - 發行候選版本 + Dynamic IP Restrictions for IIS 7 - 發行候選版本 2 + Dynamic IP Restrictions for IIS 7 - 發行候選版本 3 + + Dynamic IP Restrictions for IIS 7 - RTW + + Dynamic IP Restrictions for IIS 7 + IIS 7 的動態 IP 限制使用者介面 + + 在這部電腦上發現 Dynamic IP Restrictions for IIS 7 - Beta 版。請解除安裝,然後再試一次 + + + WebDAV 7.5 For IIS 7.0 + 必須安裝 IIS 7.0 CoreWebEngine 和 W3SVC 功能才能使用這個產品。 + WebDAV 伺服器模組 + WebDAV Administration 使用者介面 + + + IIS Search Engine Optimization Toolkit 1.0 + IIS Search Engine Optimization Toolkit 1.0 + Search Engine Optimization (SEO) Toolkit 1.0 + 這個安裝程式資料庫內含安裝 IIS Search Engine Optimization Toolkit 1.0 所需的邏輯和資料。 + + + IIS 編輯器 + + + IIS 報告 + 這部電腦上未安裝記錄檔剖析器。請從 http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 安裝記錄檔剖析器 2.2,然後繼續安裝 IIS 報告 + + + 找不到必要條件封裝。請執行 setup.exe 解決相依性,然後再安裝這個程式。 + Microsoft SQL Server 2008 管理物件是安裝 IIS Database Manager 的必要條件。您可以從 http://go.microsoft.com/fwlink/?LinkID=150946 安裝 Micrsoft SQL Server 2008 管理物件。 + Microsoft SQL Server 系統 CLR 類型是安裝 IIS Database Manager 的必要條件。您可以從 http://go.microsoft.com/fwlink/?LinkID=150949 安裝 Microsoft SQL Server 系統 CLR 類型。 + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework 是安裝應用程式要求路由的必要條件。請安裝 Web Farm Framework。 + Microsoft Application Request Routing 2.5 + 執行階段 + 將應用程式要求路由功能新增至 IIS。 + 使用者介面 + 設定 IIS 管理員中的應用程式要求路由功能。 + + + IIS 7.0 的 Microsoft Windows PowerShell 嵌入式管理單元 + + + Microsoft Web Platform Installer 4.0 + Microsoft Web Platform Installer + [ProductName] 需要 Windows XP SP2、Windows 2003 SP1、Windows Vista 或更新版本。 + [ProductName] 需要 Windows XP Service Pack 3、Windows Server 2003 Service Pack 2 (含) 以上版本。 + + + Microsoft Windows Azure Services 安裝程式 + Microsoft Windows Azure Services 安裝程式 + + + Internet Information Services (IIS) 7+ 管理員 + IIS 管理員用戶端 + 遠端支援 + 這個產品需要 Windows XP SP2、Windows 2003 SP1、Windows Vista SP1、Windows 7 或更新版本 + 未安裝 IIS 管理主控台,但需要它才能管理遠端 IIS 伺服器。安裝遠端管理支援之前,請先安裝 IIS 管理主控台,安裝方式是開啟 [控制台]->[所有程式]->[開啟或關閉 Windows 功能],並在 Internet Information Services 功能中選取 [IIS 管理主控台]。 + 在 Windows Server 2008、Windows Server 2008 R2 或更新版本中不需要這個產品。請安裝 IIS 管理主控台,安裝方式是開啟伺服器管理員,然後在網頁伺服器角色的角色服務中選取 [IIS 管理主控台]。 + + + IIS Manager Publishing for IIS 7.0 + 發行使用者介面 + + + Application Warm-Up 1.0 for IIS 7.5 + + + + 不相容的產品 [CONFLICTING_PRODUCT_NAME] 出現在這部電腦上。無法繼續安裝 [ProductName]。若要安裝這個產品,請使用 [控制台] 的 [新增/移除程式移除 [CONFLICTING_PRODUCT_NAME]。 + 需要有系統管理員權限,才能安裝 [ProductName]。 + 需要 IIS 7.0 版才能使用 [ProductName]。 + 需要 IIS 7.0 版或更新版本,才能安裝 [ProductName]。 + 需要 IIS 7.5 版或更新版本,才能安裝 [ProductName]。 + 需要 IIS 第 7 版或第 7.5 版才能安裝 [ProductName]。 + 在這部電腦上發現 [ProductName] 的 Beta 版。 + 在這部電腦上發現 [ProductName] 較新的版本。 + 安裝程式無法繼續,因為這部電腦上已安裝另一份 [ProductName]。請先解除該安裝後,再重新啟動這個安裝。 + 必須安裝 IIS 7.0 CoreWebEngine 和 W3SVC 功能才能使用 [ProductName]。 + 必須安裝 IIS 管理主控台才能使用 [ProductName]。 + 安裝 [ProductName] 前,請先停止 Windows 處理序啟用服務 (WAS) 和 Web Management Service (WMSvc) 兩個服務。您必須在安裝 [ProductName] 後再啟動服務。 + 需要 IIS Metabase 才能安裝 [ProductName]。 + 無法將 64 位元版本的 [ProductName] 安裝在 32 位元版本的 Microsoft Windows 上。 + 無法將 32 位元版本的 [ProductName] 安裝在 64 位元版本的 Microsoft Windows 上。 + 需要 Microsoft .NET Framework 2.0 版本或更新版本,才能安裝 [ProductName]。 + 必須安裝 Microsoft .NET Framework 3.5 (含) 以上版本,才能安裝 [ProductName]。請使用伺服器管理員底下的「新增功能」安裝 Microsoft .NET 3.5 版。 + 需要 Microsoft .NET Framework 4 (含) 以上版本才能安裝 [ProductName]。 + 請先安裝 Microsoft .NET Framework 2.0 版 Service Pack 1 (或更新版的 Service Pack),再安裝 [ProductName]。 + 無法停用 Windows Update (wuauserv) 服務,需要它才能安裝 [ProductName]。 + PowerShell 嵌入式管理單元是 Windows 作業系統的一部分。請用 [程式和功能] 或 [伺服器管理員] 進行安裝。 + 需要 Microsoft Web Platform Installer 3.0 (含) 以上版本才能安裝 [ProductName]。 + + 安裝程式偵測不到共用設定。 + 已為 IIS 啟用共用設定。不支援在使用共用設定時安裝 [ProductName]。請先停用共用設定,再安裝這項功能。 + + 安裝 [ProductName] 前,請先停止 World Wide Web Publishing 服務 (W3SVC)。您必須在安裝後再啟動服務。 + IIS PowerShell 管理主控台 + IIS PowerShell 嵌入式管理單元 + IIS PowerShell 嵌入式管理單元要求必須已安裝 PowerShell v1.0 或 v2.0 + IIS PowerShell 嵌入式管理單元要求必須已安裝 WAS 和設定 + 這是假的字串。 + + + Microsoft Web Farm Framework 2.2版 + Microsoft Web Farm Agent 2.2 版 + Web 伺服陣列服務 + Web 伺服陣列服務 + Web 伺服陣列控制器服務 + Web 伺服陣列控制器服務 + Web 伺服陣列代理程式服務 + Web 伺服陣列代理程式服務 + Web Platform Installer 是安裝 Web Farm Framework 2.0 的必要元件。請從 http://www.microsoft.com/web/downloads/platform.aspx 安裝 Web Plaform Installer。 + Web Deployment Tool 是安裝 Web Farm Framework 的必要元件。請從 http://www.iis.net/download/WebDeploy 安裝 Web Deployment Tool。 + + + Microsoft Web Hosting Framework + Web Hosting Framework + Web Hosting 角色及功能。 + Hosting Framework + Hosting Framework 提供用於管理 Web Hosting 的 API 命令和 PowerShell 命令。 + Web 角色 + Web 角色會安裝 Web Hosting 的 Dynamic WAS 服務及 URL Rewrite 提供者。 + Antares Express + 部署已針對單一電腦環境最佳化的控制台設定。 + 負載平衡器角色 + 負載平衡器角色會將應用程式要求路由器設定為根據 Web Hosting 規則進行路由。 + 主機控制器 + 主機控制器會擴充 Web Farm Framework 2.0 以搭配 Web Hosting 運作。 + 發行角色 + 安裝 Web Deploy 及 FTP 發行的支援。 + 這是包含 Cmdlet 的 PowerShell 嵌入式管理單元,可用來管理 Microsoft Web Hosting 基礎結構。 + 動態 WAS 服務 + 針對高密度 Web Hosting 最佳化的 Windows Process Activation 服務。 + 資源計量服務 + 安裝資源計量服務,此服務可收集和發行執行階段和健康狀態資訊。 + 資源計量 + 可從 Web 角色收集及發行執行階段和健康狀態資訊。 + 主機配額強制 + 監視網站資源使用量,並且在超過使用量配額時執行自訂動作。 + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CSY/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CSY/misc/setupstrings.wxl new file mode 100644 index 0000000000..2e4fca8c5c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CSY/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1029 + + + + Možnosti instalace sdílené konfigurace + Vyberte možnosti instalace pro sdílenou konfiguraci služby IIS. + Při instalaci aktualizovat sdílenou konfiguraci + Tento modul instalujete na server služby IIS, který používá sdílenou konfiguraci. Používají-li tuto sdílenou konfiguraci další servery služby IIS, bude tento modul nainstalován na všechny tyto servery. Chcete-li co nejméně narušit jednotlivé webové servery, nainstalujte tento modul následovně: Nejprve na všechny servery kromě jednoho nainstalujte modul, aniž byste aktualizovali sdílenou konfiguraci. To provedete tak, že zrušíte zaškrtnutí následujícího + políčka. Tak nainstalujete všechny binární i ostatní soubory modulu na každý server, ale sdílená konfigurace zůstane beze změn. Následně na posledním serveru ověřte, zda má uživatelský účet, se kterým jste přihlášeni, dostatečná oprávnění ke čtení a zápisu do souboru applicationhost.config ve sdíleném úložišti UNC. Poté nainstalujte modul a vyberte níže uvedenou možnost aktualizace sdílené konfigurace. + + + Probíhá inicializace vlastní akce souboru web.config. + Probíhá aktualizace souboru web.config. + + + + Rozšířené protokolování Internetové informační služby + Umožňuje rozšířené protokolování dat kanálu IIS. + Rozšířené protokolování Internetové informační služby + Umožňuje vytváření vlastních souborů protokolu s rozšířeným výběrem polí. + Aktualizace pro rozšířené protokolování Internetové informační služby + + + + Správce transformace služby IIS + Beta + Povoluje správce transformace služby IIS Media Services. + Správce transformace služby IIS + Umožňuje tvorbu mediálních transformací. + Hostitel správce transformace služby IIS + Hostitel služby pro [ProductName]. + Správce transformace služby IIS + Dávkový převod souborů médií na vyžádání na jiné formáty souborů a kontejneru + V počítači je nainstalován balíček Expression Encoder SP Task Správce transformace služby IIS 1.0. Ten je třeba před instalací produktu [ProductName] odinstalovat. + + K instalaci produktu [ProductName] je vyžadováno rozhraní Microsoft .NET Framework 3.5. Můžete nainstalovat funkce rozhraní .NET Framework 3.5.1 pomocí Průvodce přidáním funkcí ve Správci serveru nebo zapnout rozhraní Microsoft .NET Framework 3.5 pomocí položky Zapnout nebo vypnout funkce systému Windows. + + + + Správa digitálních práv služby IIS + Beta + Povoluje správu digitálních práv pro prezentace Smooth Streaming. + + + Není nainstalována součást ASP.NET. + + + + + + + + + V tomto počítači byla nalezena beta verze rozšíření IIS Smooth Streaming. Instalace produktu [ProductName] nemůže pokračovat. Pokud chcete tento produkt nainstalovat, pomocí ovládacího panelu Přidat nebo odebrat programy odeberte položku IIS Smooth Streaming – Beta. + V tomto počítači je nekompatibilní verze služby IIS Media Services. Instalace produktu [ProductName] nemůže pokračovat. Pokud chcete tento produkt nainstalovat, pomocí ovládacího panelu Přidat nebo odebrat programy odeberte položku IIS Media Services. + V tomto počítači je již nainstalována nebo je k dispozici k instalaci novější verze tohoto produktu. Instalace produktu [ProductName] nemůže pokračovat. Pokud chcete nainstalovat novější verzi tohoto produktu, pomocí ovládacího panelu Přidat nebo odebrat programy aktualizujte položku IIS Media Services. + Je nutný převod souboru seznamu stop. + + + + + Byly nalezeny starší soubory služby IIS Media Services. + + + + + Byly nalezeny soubory beta verze služby IIS Media Services. + + + + + + IIS Media Pack 1.0 + Aktualizace pro sadu IIS Media Pack 1.0 + IIS Media Services 2.0 + Aktualizace pro službu IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Aktualizace pro službu IIS Media Services 3.0 + Součásti a nástroje služby IIS Media Services. + Funkce a nástroje služby IIS Media Services 5 Premium + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Webové seznamy stop + Řídí přehrávání mediálních materiálů odkazovaných v seznamech stop pro klienta. + Pomocník relace + Umožňuje trvalost stavu relace ASP.NET. (Je požadována služba role ASP.NET pro roli Webový server (IIS)). + Uživatelské rozhraní + Konfiguruje funkci Webové seznamy stop ve Správci služby IIS. + + Omezení přenosové rychlosti + Uspoří šířku pásma omezením doručování souborů stahovaných klienty. + Uživatelské rozhraní + Konfiguruje funkci Omezení přenosové rychlosti ve Správci služby IIS. + + Aktiva + Umožňuje vysílání adaptivních datových proudů protokolu HTTP aktiv na vyžádání pro klienty. + Uživatelské rozhraní + Konfiguruje funkci Smooth Streaming ve Správci služby IIS. + + Kanály + Umožňuje vysílání adaptivních datových proudů protokolu HTTP všesmerového vysílání kanálů pro klienty. + Uživatelské rozhraní + Konfiguruje funkci Live Smooth Streaming ve Správci služby IIS. + + Správa digitálních práv (DRM) + Zajišťuje šifrování a správu licencí médií Smooth Streaming. + Uživatelské rozhraní + Konfiguruje funkci správy digitálních práv ve správci služby IIS. + + [ProductName] požaduje systém Microsoft Windows Vista Service Pack 1 nebo novější. + [ProductName] nelze nainstalovat v systému Vista Home Basic. + [ProductName] požaduje systém Microsoft Windows 7 Service Pack 1 nebo novější. + + + Správce databáze služby IIS + Správce databáze služby IIS + + + Služba webové správy Microsoft 2 + Služba webové správy Microsoft + Nainstaluje základní součásti produktu [ProductName]. + Služba webové správy Microsoft 2 + Služba webové správy umožňuje vzdáleným a delegovaným funkcím správy pracovat s webovým serverem, weby a aplikacemi, které jsou uloženy v tomto počítači. + + + Microsoft URL Rewrite Module 1.1 for IIS 7 + Aktualizace pro produkt URL Rewrite Module 1.1 for IIS 7 + Přepisování adres URL + Dává službě IIS 7 možnost přepisovat adresy URL a obsah. + Uživatelské rozhraní + Konfiguruje funkci URL Rewrite Module ve Správci služby IIS. + + + IIS URL Rewrite Module 2 + Aktualizace pro produkt IIS URL Rewrite Module 2 + Přepisování adres URL + Dává službě IIS 7 možnost přepisovat adresy URL a obsah. + Uživatelské rozhraní + Konfiguruje funkci URL Rewrite Module ve Správci služby IIS. + + + Balíček pro správu služby IIS 7.0 + Nainstaluje základní součásti produktu [ProductName]. + 1250 + Balíček pro správu služby IIS 7.0 + Microsoft Corporation + Tato verze operačního systému není podporována. Produkt [ProductName] lze nainstalovat pouze v systémech Windows Server 2008 nebo Windows Vista Service Pack 1 a novějších. + Součásti ASP.NET + Technologie ASP.NET obsahuje součásti Autorizace a Chybové stránky, které umožňují spravovat nastavení autorizace a vlastních chyb. + Ověřování + Popis ověřování ASP.NET. + Autorizace + Autorizace ASP.NET umožňuje konfigurovat pravidla pro autorizaci uživatelů pro přístup k vašim webům a aplikacím. + Chybové stránky + Součást Chybové stránky ASP.NET umožňuje konfigurovat chybové odpovědi protokolu HTTP (stránky vrácené při chybě). + Moduly + Popis modulů ASP.NET. + Obslužné rutiny + Popis obslužných rutin ASP.NET. + Editor konfigurací + Editor konfigurací umožňuje spravovat konfigurační soubory ve Správci služby IIS. Umožňuje upravovat sekce, atributy, elementy a kolekce v konfiguračních souborech. + Filtrování požadavků + Funkce Filtrování žádostí umožňuje konfigurovat pravidla filtrování pro vaše weby a stanovit omezení pro protokol a chování obsahu. + FastCGI + Rozšíření FastCGI umožňuje konfigurovat nastavení fondu procesů pro aplikace FastCGI na vašem webovém serveru. + + + Dynamická omezení IP adres pro službu IIS 7 – instalace + + + + + + + + + + + + + Dynamická omezení IP adres pro službu IIS 7 – beta + Dynamická omezení IP adres pro službu IIS 7 – beta 2 + Dynamická omezení IP adres pro službu IIS 7 – beta 3 + + Dynamická omezení IP adres pro službu IIS 7 – Release Candidate + Dynamická omezení IP adres pro službu IIS 7 – Release Candidate 2 + Dynamická omezení IP adres pro službu IIS 7 – Release Candidate 3 + + Dynamická omezení IP adres pro službu IIS 7 – RTW + + Dynamická omezení IP adres pro službu IIS 7 + Uživatelské rozhraní pro dynamického omezení IP adres pro službu IIS 7 + + Na tomto serveru byla zjištěn dynamická omezení IP adres pro službu IIS 7 – Beta. Odinstalujte službu a opakujte akci. + + + WebDAV 7.5 pro službu IIS 7.0 + Tento produkt lze používat pouze tehdy, jsou-li nainstalovány součásti webového jádra a W3SVC služby IIS 7.0. + Modul serveru WebDAV + Uživatelské rozhraní pro správu protokolu WebDAV + + + Sada nástrojů optimalizace pro vyhledávací weby 1.0 + Sada nástrojů optimalizace pro vyhledávací weby 1.0 + Sada nástrojů optimalizace pro vyhledávací weby (SEO) 1.0 + Databáze instalačního programu obsahuje logiku a data vyžadovaná k instalaci sady nástrojů optimalizace pro vyhledávací weby služby IIS ve verzi 1.0. + + + Editor služby IIS + + + Sestavy služby IIS + V tomto počítači není nainstalován analyzátor protokolu Log Parser. Nainstalujte nástroj Log Parser 2.2 ze stránky http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 a pokračujte dále v instalaci součásti Sestavy služby IIS. + + + Nebyly nalezeny požadované balíčky. Spusťte soubor setup.exe, abyste vyřešili potíže se závislostmi, a potom nainstalujte tento program. + Microsoft SQL Server 2008 Management Objects je požadovaným produktem pro instalaci Správce databáze služby IIS. Produkt Microsoft SQL Server 2008 Management Objects lze nainstalovat ze stránky http://go.microsoft.com/fwlink/?LinkID=150946. + Microsoft SQL Server System CLR Types je požadovaným produktem pro instalaci Správce databáze služby IIS. Produkt Microsoft SQL Server System CLR Types lze nainstalovat ze stránky http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + Technologie Směrování žádostí na aplikace požaduje, aby byla nainstalováno rozhraní Web Farm Framework. Nainstalujte rozhraní Web Farm Framework. + Microsoft Application Request Routing 2.5 + Modul runtime + Přidá do služby IIS možnosti směrování žádostí na aplikace. + Uživatelské rozhraní + Konfiguruje funkci směrování žádostí na aplikace ve správci služby IIS. + + + Modul snap-in Microsoft Windows PowerShell pro službu IIS 7.0 + + + Instalace webové platformy Microsoft 4.0 + Instalační služba webové platformy Microsoft + Produkt [ProductName] požaduje systém Windows XP SP2, Windows 2003 SP1, Windows Vista nebo novější. + Produkt [ProductName] vyžaduje systém Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 nebo novější. + + + Instalační program služby Microsoft Windows Azure Services + Instalační program služby Microsoft Windows Azure Services + + + Správce Internetové informační služby (IIS) 7+ + Klient Správce služby IIS + Podpora vzdálené komunikace + Tento produkt vyžaduje systém Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 nebo novější. + Není nainstalována konzola pro správu služby IIS, která je nutná pro správu vzdálených serverů služby IIS. Před instalací podpory vzdálené správy nainstalujte konzolu pro správu služby IIS: Přejděte na Ovládací panely ->Programy-> Zapnout nebo vypnout funkce systému Windows a v součásti Internetová informační služba vyberte položku Konzola pro správu služby IIS. + Tento produkt není požadován v systémech Windows Server 2008 nebo Windows Server 2008 R2 nebo novějších. Nainstalujte konzolu pro správu služby IIS otevřením Správce serveru a výběrem položky Konzola pro správu služby IIS v uzlu Služby rolí pro roli Webový server. + + + Publikování Správce služby IIS pro službu IIS 7.0 + Uživatelské rozhraní publikování + + + Application Warm-Up 1.0 pro službu IIS 7.5 + + + + V tomto počítači je nekompatibilní produkt [CONFLICTING_PRODUCT_NAME]. Instalace produktu [ProductName] nemůže pokračovat. Chcete-li tento produkt nainstalovat, odeberte pomocí funkce Přidat nebo odebrat programy v Ovládacích panelech produkt [CONFLICTING_PRODUCT_NAME]. + K instalaci produktu [ProductName] jsou nutná oprávnění správce. + Produkt [ProductName] lze používat pouze ve verzi 7.0 služby IIS. + K instalaci produktu [ProductName] je požadována služba IIS verze 7.0 nebo vyšší. + K instalaci produktu [ProductName] je požadována služba IIS verze 7.5 nebo vyšší. + K instalaci produktu [ProductName] je vyžadována služba IIS verze 7 nebo 7.5. + V tomto počítači byla nalezena beta verze produktu [ProductName]. + V tomto počítači byla nalezena novější verze produktu [ProductName]. + Instalační program nemůže pokračovat, protože v tomto počítači je již nainstalována jiná instance produktu [ProductName]. Odinstalujte tuto instanci a poté znovu spusťte instalaci. + Produkt [ProductName] lze používat pouze tehdy, jsou-li nainstalovány součásti webového jádra a W3SVC služby IIS 7.0. + Produkt [ProductName] lze používat pouze v případě, že je nainstalována konzola pro správu služby IIS. + Před instalací produktu [ProductName] je třeba zastavit Aktivační službu procesů systému Windows (WAS) a Službu webové správy (WMSvc). Po instalaci produktu [ProductName] bude třeba tyto služby opět spustit. + K instalaci produktu [ProductName] je požadována metabáze služby IIS. + 64bitovou verzi produktu [ProductName] nelze nainstalovat do 32bitové edice systému Microsoft Windows. + 32bitovou verzi produktu [ProductName] nelze nainstalovat do 64bitové edice systému Microsoft Windows. + K instalaci produktu [ProductName] je požadováno rozhraní Microsoft .NET Framework 2.0 nebo vyšší. + K instalaci produktu [ProductName] je vyžadováno rozhraní Microsoft .NET Framework 3.5 nebo vyšší. Nainstalujte toto rozhraní pomocí tlačítka Přidat funkce ve správci serveru. + K instalaci produktu [ProductName] je vyžadováno rozhraní Microsoft .NET Framework 4.0 nebo vyšší. + Před instalací produktu [ProductName] nainstalujte rozhraní Microsoft .NET Framework verze 2.0 Service Pack 1 (nebo novější aktualizaci Service Pack). + Služba Windows Update (wuauserv) nemůže být zakázána. Je požadována pro instalaci produktu [ProductName]. + Modul snap-in PowerShell je součástí operačního systému Windows. Nainstalujte jej prostřednictvím ovládacího panelu Programy a funkce nebo prostřednictvím Správce serveru. + K instalaci produktu [ProductName] je vyžadována Instalace webové platformy společnosti Microsoft verze 3.0 nebo vyšší. + + Instalačnímu programu se nepodařilo zjistit sdílenou konfiguraci. + Pro službu IIS je povolena sdílená konfigurace. Instalace produktu [ProductName] není podporována při použití sdílené konfigurace. Před instalací této součásti je třeba sdílenou konfiguraci zakázat. + + Před instalací produktu [ProductName] zastavte Službu publikování na webu (W3SVC). Po instalaci bude třeba ji opět spustit. + Konzola pro správu prostředí PowerShell služby IIS + Modul snap-in PowerShell služby IIS + Modul snap-in PowerShell služby IIS požaduje, aby byl nainstalována součást PowerShell v1.0 nebo v2.0. + Modul snap-in PowerShell služby IIS požaduje, aby byl nainstalována služba WAS a konfigurace. + Toto je nepravý řetězec. + + + Rozhraní Microsoft Web Farm Framework verze 2.2 + Agent Microsoft Web Farm verze 2.2 + Služba Web Farm + Služba Web Farm + Služba řadiče Web Farm + Služba řadiče Web Farm + Služba agenta Web Farm + Služba agenta Web Farm + K instalaci rozhraní Web Farm Framework je vyžadován průvodce Instalace webové platformy. Nainstalujte jej z adresy http://www.microsoft.com/web/downloads/platform.aspx. + K instalaci rozhraní Web Farm Framework je vyžadován Nástroj pro nasazení webu. Nainstalujte jej z adresy http://www.iis.net/download/WebDeploy. + + + Architektura webových hostitelských služeb společnosti Microsoft + Architektura webových hostitelských služeb + Role a funkce webových hostitelských služeb + Architektura hostitelských služeb + Architektura hostitelských služeb poskytuje příkazy rozhraní API a prostředí PowerShell pro správu webových hostitelských služeb. + Webová role + Webová role nainstaluje Dynamickou službu WAS a zprostředkovatele pro přepis adresy URL pro webové hostitelské služby. + Antares Express + Nasadí konfiguraci ovládacích panelů optimalizovanou pro instalaci v jednom počítači. + Role nástroje pro vyrovnávání zatížení + Role nástroje pro vyrovnávání zatížení nakonfiguruje směrovač žádostí aplikace na směrování na základě pravidel webových hostitelských služeb. + Řadič hostingu + Řadič hostitelských služeb rozšiřuje rozhraní Web Farm Framework 2.0 na práci s webovými hostitelskými službami. + Role publikování + Nainstaluje podporu pro nasazení webu a publikování FTP. + Jde o modul snap-in prostředí PowerShell obsahující rutiny umožňující správu infrastruktury Microsoft Web Hosting. + Dynamická služba WAS + Aktivační služba procesů systému Windows optimalizovaná pro webové hostitelské služby s vysokou hustotou + Služba měření četnosti odesílání dat ze zdrojů + Nainstaluje službu měření četnosti odesílání dat ze zdrojů, která umožňuje shromažďovat a publikovat informace o běhu i o stavu. + Resource Metering + Povolí shromažďování a publikování informací o běhu a stavu z webové role. + Vynucení kvóty hostitelských služeb + Monitoruje využití prostředků na webech a v případě překročení kvóty použití spustí vlastní akce. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/DEU/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/DEU/misc/setupstrings.wxl new file mode 100644 index 0000000000..436243b9ad --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/DEU/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1031 + + + + Installationsoptionen für freigegebene Konfiguration + Wählen Sie eine Option für die Installation in der freigegebenen IIS-Konfiguration aus. + Freigegebene Konfiguration bei Installation aktualisieren + Die Installation des Moduls erfolgt auf einem IIS-Server, der eine freigegebene Konfiguration verwendet. Wenn weitere IIS-Server diese freigegebene Konfiguration verwenden, müssen Sie dieses Modul auf allen beteiligten Computern installieren. Um Unterbrechungen auf den einzelnen Webservern zu vermeiden, beachten Sie bei der Installation des Moduls die folgenden Schritte: Führen Sie die Modulinstallation auf allen bis auf dem letzten Computer durch, ohne die freigegebene Konfiguration zu aktualisieren. Deaktivieren Sie hierzu das folgende + Kontrollkästchen. Dadurch werden alle Binärdateien und andere für das Modul benötigten Dateien auf jedem Computer installiert, ohne Änderungen an der freigegebenen Konfiguration vorzunehmen. Anschließend müssen Sie auf dem letzten Computer sicherstellen, dass das verwendete Benutzerkonto über Lese- und Schreibzugriff auf die Datei "applicationhost.config" auf der UNC-Freigabe verfügt. Installieren Sie dann das Modul, und aktivieren Sie dabei die folgend gezeigte Option zum Aktualisieren der freigegebenen Konfiguration. + + + Die benutzerdefinierte WebConfig-Aktion wird initialisiert. + "web.config" wird aktualisiert. + + + + IIS Advanced Logging + Aktiviert die erweiterte Protokollierung von IIS-Pipelinedaten. + IIS Advanced Logging + Aktiviert die Erstellung von Protokolldateien mit umfangreicher Feldauswahl. + Update für IIS Advanced Logging + + + + IIS Transform Manager + Beta + Aktiviert die Transform Manager IIS Media Services. + IIS Transform Manager + Aktiviert die Erstellung von Medientransformationen. + IIS Transform Manager-Host + Diensthost für [ProductName]. + IIS Transform Manager + Bedarfsgesteuerte Batchkonvertierung von Mediendateien in andere Datei- und Containerformate. + Ein IIS Transform Manager 1.0 Expression Encoder SP-Aufgabenpaket ist auf dem Computer installiert. Sie müssen das Paket deinstallieren, bevor Sie [ProductName] installieren können. + + Microsoft .NET Framework 3.5 ist für die Installation von [ProductName] erforderlich. Verwenden Sie den Assistenten zum Hinzufügen von Features im Server-Manager, um .NET Framework 3.5.1-Features zu installieren, oder verwenden Sie die Option "Windows-Features ein- oder ausschalten" zum Aktivieren von Microsoft .NET Framework 3.5. + + + + IIS-Verwaltung digitaler Rechte (DRM) + Beta + Aktiviert die Verwaltung digitaler Rechte (DRM) für Smooth Streaming-Präsentationen. + + + ASP.NET ist nicht installiert. + + + + + + + + + IIS Smooth Streaming Beta wurde auf diesem Computer gefunden. Die Installation von [ProductName] kann nicht fortgesetzt werden. Um dieses Produkt zu installieren, können Sie IIS Smooth Streaming Beta über die Funktion "Software" in der Systemsteuerung entfernen. + Auf diesem Computer befindet sich eine inkompatible Version der IIS Media Services. Die Installation von [ProductName] kann nicht fortgesetzt werden. Um dieses Produkt zu installieren, können Sie IIS Media Services über die Funktion "Software" in der Systemsteuerung entfernen. + Eine neuere Version dieses Produkts ist entweder bereits installiert oder für die Installation auf diesem Computer verfügbar. Die Installation von [ProductName] kann nicht fortgesetzt werden. Zum Installieren einer neueren Version des Produkts rufen Sie die Systemsteuerung auf, wählen 'Software' und aktualisieren dann die IIS Media Services. + Die Konvertierung der Wiedergabelistendatei ist erforderlich. + + + + + Es wurden ältere IIS Media Services-Dateien gefunden. + + + + + Es wurden IIS Media Services-Dateien der Betaversion gefunden. + + + + + + IIS Media Pack 1.0 + Update für IIS Media Pack 1.0 + IIS Media Services 2.0 + Update für IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Update für IIS Media Services 3.0 + Features und Tools der IIS Media Services. + Features und Tools der IIS Media Services 5 Premium. + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Internet-Wiedergabelisten + Steuert die Clientwiedergabe von Medienobjekten, auf die in Wiedergabelisten verwiesen wird. + Session Helper + Aktiviert die Dauerhaftigkeit des ASP.NET-Sitzungszustands (erfordert den ASP.NET-Rollendienst für Webserver (IIS)). + Benutzeroberfläche + Konfiguriert das Feature 'Internet-Wiedergabelisten' im IIS-Manager. + + Bitratendrosselung + Spart Bandbreite durch Drosselung der Übermittlung von Dateien ein, die von Clients heruntergeladen wurden. + Benutzeroberfläche + Konfiguriert das Feature 'Bitratendrosselung' im IIS-Manager. + + Objekte + Aktiviert adaptives HTTP-Streaming von bedarfsgesteuerten Objekten an Clients. + Benutzeroberfläche + Konfiguriert das Feature 'Smooth Streaming' im IIS-Manager. + + Kanäle + Aktiviert adaptives HTTP-Streaming von Kanalübertragungen an Clients. + Benutzeroberfläche + Konfiguriert das Live Smooth Streaming-Feature im IIS-Manager. + + Verwaltung digitaler Rechte (DRM) + Stellt Verschlüsselung und Lizenzierung für Smooth Streaming-Medien bereit. + Benutzeroberfläche + Konfiguriert die Funktion zur Verwaltung digitaler Rechte (DRM) im IIS-Manager. + + [ProductName] erfordert Microsoft Windows Vista Service Pack 1 oder höher. + [ProductName] darf nicht unter Vista Home Basic installiert werden. + [ProductName] erfordert Microsoft Windows 7 Service Pack 1 oder höher. + + + IIS-Datenbank-Manager + IIS-Datenbank-Manager + + + Microsoft-Webverwaltungsdienst 2 + Microsoft-Webverwaltungsdienst + Installiert die grundlegenden Features von [ProductName]. + Microsoft-Webverwaltungsdienst 2 + Der Webverwaltungsdienst bietet Remote- und delegierte Verwaltungsfunktionen für Administratoren zur Verwaltung des Webservers, der Websites und der Anwendungen auf diesem Computer. + + + Microsoft URL Rewrite-Modul 1.1 für IIS 7 + Update für das URL Rewrite-Modul 1.1 für IIS 7 + URL Rewrite + Aktiviert URL- und Inhaltsumschreibfunktionen für IIS 7. + Benutzeroberfläche + Konfiguriert das Feature 'URL Rewrite-Modul' im IIS-Manager. + + + IIS-URL-Rewrite-Modul 2 + Update für IIS-URL-Rewrite-Modul 2 + URL Rewrite + Aktiviert URL- und Inhaltsumschreibfunktionen für IIS 7. + Benutzeroberfläche + Konfiguriert das Feature 'URL Rewrite-Modul' im IIS-Manager. + + + Administration Pack für IIS 7.0 + Installiert die grundlegenden Features von [ProductName]. + 1252 + Administration Pack für IIS 7.0 + Microsoft Corporation + Diese Version des Betriebssystems wird nicht unterstützt. [ProductName] kann nur unter Windows Server 2008 oder Windows Vista Service Pack 1 und höher installiert werden. + ASP.NET-Features + ASP.NET umfasst Features für Autorisierung und Fehlerseiten, mit denen Sie die Autorisierungs- und benutzerdefinierten Fehlereinstellungen verwalten können. + Authentifizierung + ASP.NET-Authentifizierungsbeschreibung. + Autorisierung + Mit der ASP.NET-Autorisierung können Sie Regeln für die Autorisierung von Benutzern für den Zugriff auf Websites und Anwendungen konfigurieren. + Fehlerseiten + Mit den ASP.NET-Fehlerseiten können Sie HTTP-Fehlerreaktionen konfigurieren. + Module + ASP.NET-Modulbeschreibung. + Handler + ASP.NET-Handlerbeschreibung. + Konfigurations-Editor + Mit dem Konfigurations-Editor können Sie Konfigurationsdateien im IIS-Manager verwalten, indem Sie Abschnitte, Attribute, Elemente und Sammlungen der Konfigurationsdateien bearbeiten. + Anforderungsfilterung + Bei der Anforderungsfilterung können Sie Filterregeln für Ihre Website konfigurieren und das Protokoll- und Inhaltsverhalten beschränken. + FastCGI + Mit 'FastCGI' können Sie Prozesspooleinstellungen für die FastCGI-Anwendungen auf Ihrem Webserver konfigurieren. + + + Dynamische IP-Einschränkungen für die IIS 7-Konfiguration + + + + + + + + + + + + + Dynamische IP-Einschränkungen für IIS 7 - Beta + Dynamische IP-Einschränkungen für IIS 7 - Beta 2 + Dynamische IP-Einschränkungen für IIS 7 - Beta 3 + + Dynamische IP-Einschränkungen für IIS 7 - Release Candidate + Dynamische IP-Einschränkungen für IIS 7 - Release Candidate 2 + Dynamische IP-Einschränkungen für IIS 7 - Release Candidate 3 + + Dynamische IP-Einschränkungen für IIS 7 - RTW + + Dynamische IP-Einschränkungen für IIS 7 + Dynamische IP-Einschränkungen - Benutzeroberfläche für IIS 7 + + Dynamische IP-Einschränkungen für IIS 7 - Beta wurde auf diesem Computer gefunden. Deinstallieren Sie diese Anwendung, und versuchen Sie es erneut. + + + WebDAV 7.5 für IIS 7.0 + Die IIS 7.0-Features CoreWebEngine und W3SVC müssen für die Verwendung dieses Produkts installiert sein. + WebDAV-Servermodul + WebDAV-Administrationsbenutzeroberfläche + + + IIS Search Engine Optimization Toolkit 1.0 + IIS Search Engine Optimization Toolkit 1.0 + Search Engine Optimization (SEO) Toolkit 1.0 + Diese Installer-Datenbank enthält die zum Installieren von IIS Search Engine Optimization Toolkit 1.0 erforderliche Logik. + + + IIS-Editor + + + IIS-Berichte + Der Protokollparser ist nicht auf diesem Computer installiert. Installieren Sie Log Parser 2.2 über http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, und setzen Sie dann die Installation der IIS-Berichte fort. + + + Erforderliche Pakete wurden nicht gefunden. Führen Sie 'setup.exe' aus, um Abhängigkeiten aufzulösen und dieses Programm zu installieren. + Microsoft SQL Server 2008 Management Objects ist eine Voraussetzung für die Installation von IIS-Datenbank-Manager. Sie können Microsoft SQL Server 2008 Management Objects über http://go.microsoft.com/fwlink/?LinkID=150946 installieren. + Microsoft SQL Server System CLR Types ist eine Voraussetzung für die Installation von IIS-Datenbank-Manager. Sie können Microsoft SQL Server System CLR Types über http://go.microsoft.com/fwlink/?LinkID=150949 installieren. + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework ist eine Voraussetzung für die Installation des Routings von Anwendungsanforderungen. Installieren Sie Web Farm Framework. + Microsoft Application Request Routing 2.5 + Laufzeit + Fügt die Funktionen des Routings von Anwendungsanforderungen zu IIS hinzu. + Benutzeroberfläche + Konfiguriert das Feature "Routing von Anwendungsanforderungen" im IIS-Manager. + + + Microsoft Windows PowerShell snap-in für IIS 7.0 + + + Microsoft-Webplattform-Installer 4.0 + Microsoft-Webplattform-Installer + [ProductName] erfordert Windows XP SP2, Windows 2003 SP1, Windows Vista oder höher. + [ProductName] benötigt Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 oder höher. + + + Microsoft Windows Azure Services Installer + Microsoft Windows Azure Services Installer + + + Internetinformationsdienste (IIS) 7+-Manager + IIS-Manager-Client + Remotesupport + Das Produkt erfordert Windows XP SP2, Windows 2003 SP1, Windows Vista SP1 oder Windows 7 oder höher. + Die IIS-Verwaltungskonsole ist nicht installiert, sie ist aber zur Verwaltung von Remote-IIS-Servern erforderlich. Installieren Sie die IIS-Verwaltungskonsole vor der Installation des Remoteverwaltungssupports durch Öffnen von 'Systemsteuerung->Programme->Windows-Funktionen ein- oder ausschalten' und Auswahl der IIS-Verwaltungskonsole im Feature 'Internetinformationsdienste'. + Dieses Produkt ist in Windows Server 2008 oder Windows Server 2008 R2 oder höher nicht erforderlich. Installieren Sie die IIS-Verwaltungskonsole durch Öffnen des Server-Managers und Auswahl der IIS-Verwaltungskonsole in den Rollendiensten für die Webserverrolle. + + + IIS-Manager-Publishing für IIS 7.0 + Publishing-Benutzeroberfläche + + + Application Warm-Up 1.0 für IIS 7.5 + + + + Ein inkompatibles Produkt ( [CONFLICTING_PRODUCT_NAME]) ist auf dem Computer. installiert. Die Installation von [ProductName] kann nicht fortgesetzt werden. Verwenden Sie zum Installieren dieses Produkts "Software" in der Systemsteuerung, um [CONFLICTING_PRODUCT_NAME] zu entfernen. + Administratorberechtigungen sind für die Installation von [ProductName] erforderlich. + IIS Version 7.0 ist für die Verwendung von [ProductName] erforderlich. + IIS Version 7.0 oder höher ist für die Installation von [ProductName] erforderlich. + IIS Version 7.5 oder höher ist für die Installation von [ProductName] erforderlich. + IIS Version 7.0 oder 7.5 ist für die Installation von [ProductName] erforderlich. + Eine Betaversion von [ProductName] wurde auf diesem Computer gefunden. + Eine neuere Version von [ProductName] wurde auf diesem Computer gefunden. + Die Installation kann nicht fortgesetzt werden, da eine andere Instanz von [ProductName] bereits auf diesem Computer installiert ist. Deinstallieren Sie diese zuerst, und starten Sie die Installation dann erneut. + Die IIS 7.0-Features CoreWebEngine und W3SVC müssen für die Verwendung von [ProductName] installiert sein. + Die IIS-Verwaltungskonsole muss für die Verwendung von [ProductName] installiert sein. + Halten Sie die den Windows-Prozessaktivierungsdienst (WAS) und den Webverwaltungsdienst (WMSvc) vor der Installation von [ProductName] an. Sie müssen die Dienste nach der Installation von [ProductName] wieder starten. + IIS-Metabasis ist für die Installation von [ProductName] erforderlich. + Die 64-Bit-Version von [ProductName] kann nicht in einer 32-Bit-Version von Microsoft Windows installiert werden. + Die 32-Bit-Version von [ProductName] kann nicht in einer 64-Bit-Version von Microsoft Windows installiert werden. + Microsoft .NET Framework Version 2.0 oder höher ist für die Installation von [ProductName] erforderlich. + Microsoft .NET Framework Version 3.5 oder höher ist für die Installation von [ProductName] erforderlich. Verwenden Sie die Option "Features hinzufügen" im Server-Manager, um Microsoft .Net Version 3.5 zu installieren. + Microsoft .NET Framework Version 4.0 oder höher ist für die Installation von [ProductName] erforderlich. + Installieren Sie Microsoft .NET Framework Version 2.0 Service Pack 1 (oder ein höheres Service Pack) vor der Installation von [ProductName]. + Der Windows Update (wuauserv)-Dienst kann nicht deaktiviert werden, er ist zur Installation von [ProductName] erforderlich. + Das PowerShell-Snap-In ist Teil des Windows-Betriebssystems. Installieren Sie es über 'Programme und Funktionen' oder 'Server-Manager'. + Microsoft-Webplattform-Installer Version 3.0 oder höher ist für die Installation von [ProductName] erforderlich. + + Die freigegebene Konfiguration konnte nicht ermittelt werden. + Die freigegebene Konfiguration ist für IIS aktiviert. Die Installation von [ProductName] wird bei Verwendung der freigegebenen Konfiguration nicht unterstützt. Deaktivieren Sie die freigegebene Konfiguration vor der Installation des Features. + + Halten Sie den WWW-Publishingdienst (W3SVC) vor der Installation von [ProductName] an. Sie müssen den Dienst nach der Installation wieder starten. + IIS-PowerShell-Verwaltungskonsole + IIS-PowerShell-Snap-In + Das IIS-PowerShell-Snap-In erfordert die Installation von PowerShell v1.0 oder v2.0. + Das IIS-PowerShell-Snap-In erfordert die Installation des Windows-Prozessaktivierungsdiensts und der Konfiguration. + Dies ist eine Platzhalter-Zeichenfolge. + + + Microsoft Web Farm Framework Version 2.2 + Microsoft Webfarm-Agent Version 2.2 + Webfarmdienst + Webfarmdienst + Webfarm-Controllerdienst + Webfarm-Controllerdienst + Webfarm-Agent-Dienst + Webfarm-Agent-Dienst + Webplattform-Installer ist eine Voraussetzung für die Installation von Web Farm Framework. Installieren Sie den Webplattform-Installer von "http://www.microsoft.com/web/downloads/platform.aspx". + Die Webbereitstellungstools sind eine Voraussetzung für die Installation von Web Farm Framework. Installieren Sie das Webbereitstellungstool von "http://www.iis.net/download/WebDeploy". + + + Microsoft Web Hosting Framework + Web Hosting Framework + Rollen und Funktionen für Web Hosting. + Hosting Framework + Hosting Framework stellt APIs und PowerShell-Befehle zum Verwalten von Web Hosting zur Verfügung. + Webrolle + Die Webrolle installiert den dynamischen WAS-Dienst und den URL-Rewrite-Anbieter für Web Hosting. + Antares Express + Stellt eine Systemsteuerungskonfiguration bereit, die für die Einrichtung eines einzelnen Computers optimiert ist. + Lastenausgleichsrolle + Die Lastenausgleichsrolle konfiguriert den Anwendungsanforderungsrouter für Routing basierend auf Web Hosting-Regeln. + Hostingcontroller + Der Hostingcontroller erweitert Web Farm Framework 2.0 für die Zusammenarbeit mit Web Hosting. + Veröffentlichungsrolle + Installiert Unterstützung für Web Deploy und FTP-Veröffentlichung. + Hierbei handelt es sich um ein PowerShell-Snap-In mit Cmdlets zur Verwaltung der Microsoft Web Hosting-Infrastruktur. + Dynamischer WAS-Dienst + Windows-Prozessaktivierungsdienst, der für HD-Web Hosting optimiert ist. + Resource Metering-Dienst + Installiert den Resource Metering-Dienst, der das Sammeln und Veröffentlichen von Laufzeit- und Systemintegritätsinformationen ermöglicht. + Resource Metering + Aktiviert das Sammeln und Veröffentlichen von Laufzeit- und Systemintegritätsinformationen aus der Webrolle. + Durchsetzung des Hostingkontingents + Überwacht den Website-Ressourceneinsatz und führt benutzerdefinierte Aktionen aus, wenn das Verwendungskontingent überschritten wurde. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ESN/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ESN/misc/setupstrings.wxl new file mode 100644 index 0000000000..ea1579e794 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ESN/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 3082 + + + + Opciones de instalación de la configuración compartida + Seleccionar la opción de instalación en la configuración compartida de IIS + Actualizar configuración compartida al instalar + Está instalando este módulo en un servidor IIS que usa una configuración compartida. Si otros servidores IIS usan esta configuración compartida, tendrá que instalar este módulo en todas estas máquinas. Para minimizar las interrupciones de los servidores web individuales, tendrá que instalar este módulo realizando los pasos siguientes. En primer lugar, en todas las máquinas, excepto en la última, debe instalar el módulo sin actualizar la configuración compartida. Hágalo sin activar la casilla + siguiente. Esto instalará todos los binarios y archivos necesarios para el módulo en cada máquina sin modificar la configuración compartida. En segundo lugar, en la última máquina tendrá que comprobar que la identidad del usuario con la que está trabajando tiene acceso de lectura y escritura al archivo applicationhost.config del recurso compartido UNC. Después, debe instalar el módulo y seleccionar la opción de actualización de configuración compartida que figura a continuación. + + + Inicialización de acción personalizada de WebConfig + Actualización de archivo web.config + + + + Registro avanzado de IIS + Permite el registro avanzado de datos de canalización de IIS. + Registro avanzado de IIS + Permite la creación de archivos de registro personalizados con selección de campos extensible. + Actualización de Advanced Logging de IIS + + + + Transform Manager para IIS + Beta + Habilita los Servicios multimedia de IIS para Transform Manager. + Transform Manager para IIS + Habilita la creación de transformaciones multimedia. + Host de Transform Manager para IIS + Host de servicios para [ProductName]. + Transform Manager para IIS + Permite convertir por lotes archivos multimedia a petición para alternar formatos de archivo y contenedor. + Existe un paquete de tareas de IIS Transform Manager 1.0 Expression Encoder SP instalado en el equipo. Deberá desinstalarlo antes de instalar [ProductName]. + + Se necesita Microsoft .NET Framework 3.5 para instalar [ProductName]. Use el 'Asistente para agregar características' del Administrador del servidor para instalar las características de .NET Framework 3.5.1 o la opción 'Activar o desactivar las características de Windows' para activar Microsoft .NET Framework 3.5. + + + + Administración de derechos digitales de IIS + Beta + Habilita la administración de derechos digitales de presentaciones de transmisión por secuencias suave. + + + ASP.NET no está instalado + + + + + + + + + Se encontró IIS Smooth Streaming - Beta en este equipo. La instalación de [ProductName] no puede continuar. Para instalar este producto, use Agregar o quitar programas en el Panel de control para quitar IIS Smooth Streaming - Beta. + Este equipo cuenta con una versión no compatible de Servicios multimedia de IIS. La instalación de [ProductName] no puede continuar. Para instalar este producto, use Agregar o quitar programas en el Panel de control para quitar Servicios multimedia de IIS. + Una versión más reciente de este producto está ya instalada o disponible para instalarla en este equipo. La instalación de [ProductName] no puede continuar. Para instalar la versión más reciente de este producto, use Agregar o quitar programas en el Panel de control para actualizar Servicios multimedia de IIS. + Conversión necesaria de archivo de lista de reproducción + + + + + Archivos de versiones anteriores de Servicios multimedia de IIS encontrados + + + + + Versión beta de los Servicios Multimedia de IIS encontrada + + + + + + IIS Media Pack 1.0 + Actualización de IIS Media Pack 1.0 + Servicios multimedia 2.0 de IIS + Actualización de Servicios multimedia 2.0 de IIS + Servicios multimedia 3.0 de IIS + Servicios multimedia 3.0 de IIS (TAP 2) + Actualización de Servicios multimedia 3.0 de IIS + Características y herramientas de Servicios multimedia de IIS. + Características y herramientas de Servicios multimedia de IIS 5 Premium. + Servicios multimedia 4.0 beta 1 de IIS + Servicios multimedia 4.0 de IIS + Servicios multimedia 4.5 beta 1 de IIS + Servicios multimedia de IIS 5 Premium + + Listas de reproducción en web + Controla la reproducción en clientes de recursos multimedia digitales a los que se hace referencia en listas de reproducción. + Aplicación auxiliar para sesiones + Habilita la persistencia de estado de sesión de ASP.NET. Requiere el servicio de rol ASP.NET para el rol Servidor web (IIS). + Interfaz de usuario + Configura la característica Listas de reproducción en web en el Administrador de IIS. + + Limitación de velocidad de bits + Ahorra ancho de banda limitando la entrega de archivos descargados por los clientes. + Interfaz de usuario + Configura la característica Limitación de velocidad de bits en el Administrador de IIS. + + Activos + Habilita la transmisión por secuencias adaptativa HTTP de archivos a petición a los clientes. + Interfaz de usuario + Configura la característica Transmisión por secuencias suave en el Administrador de IIS. + + Canales + Habilita la transmisión por secuencias adaptativa HTTP de las difusiones de canal a los clientes. + Interfaz de usuario + Configura la característica Live Smooth Streaming en el Administrador de IIS. + + Administración de derechos digitales + Proporciona cifrado y licencias de medios de transmisión por secuencias suave. + Interfaz de usuario + Configura la característica de administración de derechos digitales en el administrador de IIS. + + [ProductName] requiere Microsoft Windows Vista Service Pack 1 o posterior. + [ProductName] no se puede instalar en Vista Home Basic. + [ProductName] requiere Microsoft Windows 7 Service Pack 1 o posterior. + + + Administrador de bases de datos de IIS + Administrador de bases de datos de IIS + + + Servicio de administración web de Microsoft 2 + Servicio de administración web de Microsoft + Instala las características básicas de [ProductName]. + Servicio de administración web de Microsoft 2 + El Servicio de administración web habilita funciones de administración remota y delegada para quienes administren los sitios, las aplicaciones y el servidor web presentes en este equipo. + + + Módulo URL Rewrite 1.1 para IIS 7 + Actualización de Módulo URL Rewrite 1.1 para IIS 7 + URL Rewrite + Habilita la reescritura de direcciones URL y contenido en IIS 7. + Interfaz de usuario + Configura la característica Módulo URL Rewrite en el Administrador de IIS. + + + Módulo URL Rewrite 2 de IIS + Actualización de Módulo URL Rewrite 2 de IIS + URL Rewrite + Habilita la reescritura de direcciones URL y contenido en IIS 7. + Interfaz de usuario + Configura la característica Módulo URL Rewrite en el Administrador de IIS. + + + Administration Pack para IIS 7.0 + Instala las características básicas de [ProductName]. + 1252 + Administration Pack para IIS 7.0 + Microsoft Corporation + No se admite esta versión del sistema operativo. [ProductName] se puede instalar sólo en Windows Server 2008 o Windows Vista Service Pack 1 y posterior. + Características de ASP.NET + ASP.NET incluye las características Autorización y Páginas de errores, que permiten administrar la autorización y la configuración de errores personalizada. + Autenticación + Descripción de autenticación ASP.NET. + Autorización + Autorización de ASP.NET permite configurar reglas para autorizar a usuarios a obtener acceso a sitios y aplicaciones web. + Páginas de errores + Páginas de errores de ASP.NET permite configurar respuestas a errores HTTP para devolverlas cuando se producen errores. + Módulos + Descripción de módulos de ASP.NET. + Controladores + Descripción de controladores de ASP.NET. + Editor de configuración + El Editor de configuración permite administrar los archivos de configuración en el Administrador de IIS. Permite editar secciones, atributos, elementos y colecciones en los archivos de configuración. + Filtrado de solicitudes + Filtrado de solicitudes permite configurar reglas de filtrado para un sitio web y restringir el comportamiento de protocolo y contenido. + FastCGI + FastCGI permite configurar grupos de procesos para aplicaciones FastCGI del servidor web. + + + Programa de instalación de Restricciones de IP dinámicas para IIS 7 + + + + + + + + + + + + + Restricciones de IP dinámicas para IIS 7 - Beta + Restricciones de IP dinámicas para IIS 7 - Beta 2 + Restricciones de IP dinámicas para IIS 7 - Beta 3 + + Restricciones de IP dinámicas para IIS 7 - Release Candidate + Restricciones de IP dinámicas para IIS 7 - Release Candidate 2 + Restricciones de IP dinámicas para IIS 7 - Release Candidate 3 + + Restricciones de IP dinámicas para IIS 7 - RTW + + Restricciones de IP dinámicas para IIS 7 + Interfaz de usuario de Restricciones de IP dinámicas para IIS 7 + + Se encontraron restricciones de IP dinámicas para IIS 7 - Beta en esta máquina. Desinstálelo e inténtelo de nuevo. + + + WebDAV 7.5 para IIS 7.0 + Deben instalarse las características CoreWebEngine y W3SVC de IIS 7.0 para usar este producto. + Módulo de servidor de WebDAV + Interfaz de usuario de administración de WebDAV + + + Herramientas de optimización para el motor de búsqueda de IIS 1.0 + Herramientas de optimización para el motor de búsqueda de IIS 1.0 + Herramientas de optimización para el motor de búsqueda (SEO) de IIS 1.0 + Esta base de datos de instalador contiene la lógica y los datos necesarios para instalar las Herramientas de optimización para el motor de búsqueda de IIS 1.0. + + + Editor de IIS + + + Informes de IIS + Log Parser no está instalado en esta máquina. Instale Log Parser 2.2 desde http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 y después continúe con la instalación de Informes de IIS. + + + No se encontraron algunos paquetes de requisitos previos. Ejecute setup.exe para resolver las dependencias e instalar este programa. + Objetos de administración de Microsoft SQL Server 2008 es un requisito previo para instalar el Administrador de bases de datos de IIS. Puede instalar Objetos de administración de Microsoft SQL Server 2008 desde http://go.microsoft.com/fwlink/?LinkID=150946 . + Microsoft SQL Server System CLR Types es un requisito previo para instalar el Administrador de bases de datos de IIS. Puede instalar Microsoft SQL Server System CLR Types desde http://go.microsoft.com/fwlink/?LinkID=150949 . + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework es un requisito para instalar Enrutamiento de solicitud de aplicaciones. Instale Web Farm Framework. + Enrutamiento de solicitud de aplicaciones de Microsoft 2.5 + Runtime + Agrega las capacidades de Enrutamiento de solicitud de aplicaciones a IIS. + Interfaz de usuario + Configura la característica Enrutamiento de solicitud de aplicaciones en el Administrador de IIS. + + + Complemento PowerShell de Microsoft Windows para IIS 7.0 + + + Instalador de plataforma web 4.0 de Microsoft + Instalador de plataforma web de Microsoft + [ProductName] requiere Windows XP SP2, Windows 2003 SP1, Windows Vista o posterior. + [ProductName] requiere Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 o posterior. + + + Instalador de Microsoft Windows Azure Services + Instalador de Microsoft Windows Azure Services + + + Administrador de Internet Information Services (IIS) 7 o posterior + Cliente del Administrador de IIS + Compatibilidad con comunicación remota + Este producto requiere Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 o posterior. + La Consola de administración de IIS no está instalada, pero es necesaria para administrar servidores IIS remotos. Instale la Consola de administración de IIS antes de instalar la compatibilidad con administración remota. Para ello, abra 'Panel de control->Programas->Activar o desactivar las características de Windows' y seleccione Consola de administración de IIS en la característica Internet Information Services. + Este producto no es necesario en Windows Server 2008 ni Windows Server 2008 R2 o posterior. Para instalar la Consola de administración de IIS, abra el Administrador del servidor y seleccione Consola de administración de IIS en los servicios del rol Servidor web. + + + Servicio de publicación del Administrador de IIS para IIS 7.0 + Interfaz de usuario para publicación + + + Application Warm-Up 1.0 para IIS 7.5 + + + + El equipo tiene un producto no compatible, [CONFLICTING_PRODUCT_NAME]. No es posible continuar con la instalación de [ProductName]. Para instalar este producto, vaya a Panel de control > Agregar o quitar programas para quitar [CONFLICTING_PRODUCT_NAME]. + Es necesario el privilegio de administrador para instalar [ProductName]. + Es necesaria la versión 7.0 de IIS para usar [ProductName]. + Es necesaria la versión 7.0 o posterior de IIS para instalar [ProductName]. + Es necesaria la versión 7.5 o posterior de IIS para instalar [ProductName]. + Se requiere la versión 7 o 7.5 de IIS para instalar [ProductName]. + Se encontró la versión beta de [ProductName] en esta máquina. + Se encontró una versión más reciente de [ProductName] en esta máquina. + El programa de instalación no puede continuar porque ya hay instalada otra instancia de [ProductName] en esta máquina. Desinstale primero esa instancia y vuelva a iniciar esta instalación. + Deben estar instaladas las características CoreWebEngine y W3SVC de IIS 7.0 para usar [ProductName]. + Para usar [ProductName], debe estar instalada la Consola de administración de IIS. + Detenga los servicios WAS (Windows Process Activation) y WMSvc (Servicio de administración web) antes de instalar [ProductName]. Deberá iniciar los servicios después de instalar [ProductName]. + Es necesaria la metabase de IIS para instalar [ProductName]. + No se puede instalar la versión de 64 bits de [ProductName] en una edición de 32 bits de Microsoft Windows. + No se puede instalar la versión de 32 bits de [ProductName] en una edición de 64 bits de Microsoft Windows. + Es necesario Microsoft .NET Framework 2.0 o posterior para instalar [ProductName]. + Se requiere Microsoft .NET Framework, versión 3.5 o posterior, para instalar [ProductName]. Use la opción 'Agregar características' del Administrador del servidor para instalar Microsoft .Net, versión 3.5. + Se requiere Microsoft .NET Framework, versión 4.0 o posterior, para instalar [ProductName]. + Instale Microsoft .NET Framework 2.0 Service Pack 1 (o un Service Pack posterior) antes de instalar [ProductName]. + No se puede deshabilitar el servicio Windows Update (wuauserv), porque es necesario para instalar [ProductName]. + El complemento PowerShell forma parte del sistema operativo Windows. Instálelo desde 'Programas y características' o 'Administrador del servidor'. + Se requiere Instalador de plataforma web de Microsoft, versión 3.0 o posterior, para instalar [ProductName]. + + El programa de instalación no detectó ninguna configuración compartida. + Está habilitada la configuración compartida para IIS. No se admite la instalación de [ProductName] cuando se usa configuración compartida. Deshabilite la configuración compartida antes de instalar esta característica. + + Detenga el servicio de publicación World Wide Web (W3SVC) antes de instalar [ProductName]. Deberá iniciar el servicio después de la instalación. + Consola de administración de PowerShell para IIS + Complemento PowerShell para IIS + El complemento PowerShell para IIS requiere que esté instalado PowerShell v1.0 o v2.0. + El complemento PowerShell para IIS requiere que estén instalados el servicio WAS y la configuración. + This is a bogus string. + + + Microsoft Web Farm Framework versión 2.2 + Microsoft Web Farm Agent versión 2.2 + Servicio de Web Farm + Servicio de Web Farm + Servicio de controlador de Web Farm + Servicio de controlador de Web Farm + Servicio de agente de Web Farm + Servicio de agente de Web Farm + El Instalador de plataforma web es un requisito previo para instalar Web Farm Framework. Instale el Instalador de plataforma web desde http://www.microsoft.com/web/downloads/platform.aspx. + La Herramienta de implementación web es un requisito previo para instalar Web Farm Framework. Instale la Herramienta de implementación web desde http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Roles y características de Microsoft Web Hosting. + Hosting Framework + Hosting Framework ofrece comandos de las API y PowerShell para administrar Web Hosting. + Rol web + El rol web instala el servicio WAS dinámico y el proveedor de URL Rewrite para Web Hosting. + Antares Express + Implementa una configuración de Panel de control optimizada para la configuración de un único equipo. + Rol Equilibrador de carga + El rol Equilibrador de carga configura Application Request Router para enrutar en función de las reglas de Web Hosting. + Controlador de hospedaje + El controlador de hospedaje amplía Web Farm Framework 2.0 para que funcione con Web Hosting. + Rol de publicación + Instala el soporte para la publicación FTP y de Web Deploy. + Se trata de un complemento de PowerShell que contiene cmdlets para administrar la infraestructura de Microsoft Web Hosting. + Servicio WAS dinámico + Servicio WAS (Windows Process Activation) optimizado para hospedaje web de alta densidad. + Servicio de medición de recursos + Instala el servicio Medición de recursos que habilita la recopilación y la publicación de información de estado y en tiempo de ejecución. + Medición de recursos + Habilita la recopilación y publicación de información de estado y en tiempo de ejecución del rol web. + Cumplimiento de cuota de hospedaje + Supervisa el uso de recursos de los sitios web y ejecuta acciones personalizadas si se supera la cuota. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/FRA/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/FRA/misc/setupstrings.wxl new file mode 100644 index 0000000000..c00688e50c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/FRA/misc/setupstrings.wxl @@ -0,0 +1,352 @@ + + + + + + + 1036 + + + + Options d'installation pour la configuration partagée + Sélectionnez une option pour l'installation dans une partagée IIS + Mettre à jour la configuration partagée lors de l'installation + Vous installez ce module sur un serveur IIS qui utilise une configuration partagée. Si des serveurs IIS supplémentaires utilisent cette configuration partagée, vous devez installer ce module sur tous ces ordinateurs. Pour réduire le risque d'interruptions sur les différents serveurs Web, installez ce module en respectant les étapes suivantes : premièrement, sur tous les ordinateurs à l'exception du dernier, vous devez installer le module sans mettre à jour la configuration partagée. Pour ce faire, n'activez pas la case à cocher + ci-dessous. Cette opération installe l'ensemble des fichiers et ressources binaires requis pour le module sur chaque ordinateur sans apporter de modifications à la configuration partagée. Deuxièmement, sur le dernier ordinateur, vous devez vérifier que l'identité d'utilisateur que vous utilisez actuellement dispose d'un accès en lecture/écriture au fichier applicationhost.config du partage UNC. Vous devez ensuite installer le module et sélectionner l'option de mise à jour de la configuration partagée ci-dessous. + + + Initialisation de l'action personnalisée WebConfig + Mise à jour de web.config + + + + IIS Advanced Logging + Active la journalisation avancée des données de pipeline IIS. + IIS Advanced Logging + Permet la création de fichiers journaux personnalisés avec une sélection de champ extensible. + Mise à jour pour IIS Advanced Logging + + + + IIS Transform Manager + Bêta + Active IIS Services Multimédia pour Transform Manager. + IIS Transform Manager + Active la création de transformations multimédias. + Hôte IIS Transform Manager + Hôte de service pour [ProductName]. + IIS Transform Manager + Convertir sous forme de lot sur demande les fichiers multimédias en d'autres formats de fichier et de conteneur. + Un package IIS Transform Manager 1.0 Expression Encoder SP Task est installé sur l'ordinateur. Vous devez le désinstaller avant d'installer [ProductName]. + + Microsoft .NET Framework 3.5 est requis pour installer [ProductName]. Utilisez l'Assistant Ajout de fonctionnalités du Gestionnaire de serveur pour installer le composant Fonctionnalités du .NET Framework 3.5.1, ou utilisez l'option Activer ou désactiver des fonctionnalités Windows pour activer Microsoft .NET Framework 3.5. + + + + Gestion des droits numériques (DRM) IIS + Bêta + Active la gestion des droits numériques (DRM) des présentations de diffusion en continu lisse. + + + ASP.NET n'est pas installé + + + + + + + + + Diffusion en continu lisse IIS - Bêta a été détecté sur cet ordinateur. L'installation de [ProductName] ne peut pas continuer. Pour installer ce produit, utilisez Ajouter ou supprimer des programmes dans le Panneau de configuration afin de supprimer Diffusion en continu lisse IIS - Bêta. + Une version incompatible d'IIS Services Multimédia se trouve sur cet ordinateur. L'installation de [ProductName] ne peut pas continuer. Pour installer ce produit, utilisez Ajouter ou supprimer des programme dans le Panneau de configuration afin de supprimer IIS Services Multimédia. + Une version plus récente de ce produit est déjà installée ou disponible à l'installation sur cet ordinateur. L'installation de [ProductName] ne peut pas continuer. Pour installer la version la plus récente de ce produit, utilisez Ajouter ou supprimer des programme dans le Panneau de configuration pour mettre à jour IIS Services Multimédia. + Conversion du fichier de sélections requise + + + + + Anciens fichiers IIS Services Multimédia trouvés + + + + + Fichiers IIS Services Multimédia Bêta trouvés + + + + + + IIS Pack Multimédia 1.0 + Mise à jour pour IIS Pack Multimédia 1.0 + IIS Services Multimédia 2.0 + Mise à jour pour IIS Services Multimédia 2.0 + IIS Services Multimédia 3.0 + IIS Services Multimédia 3.0 TAP 2 + Mise à jour pour IIS Services Multimédia 3.0 + Fonctionnalités et outils IIS Services Multimédia. + Fonctionnalités et outils IIS Media Services 5. + IIS Services Multimédia 4.0 Bêta 1 + IIS Services Multimédia 4.0 + IIS Services Multimédia 4.5 Bêta 1 + IIS Media Services 5 Premium + + Sélections Web + Contrôle la lecture sur le client des fichiers multimédias référencés dans les sélections. + Session Helper + Active la persistance d'état de session ASP.NET. (Requiert le service de rôle ASP.NET pour le serveur Web (IIS)). + Interface utilisateur + Configure la fonctionnalité Sélections Web dans le Gestionnaire des services Internet. + + Bit Rate Throttling + Économise la bande passante en limitant la remise de fichiers téléchargés par les clients. + Interface utilisateur + Configure la fonctionnalité Bit Rate Throttling dans le Gestionnaire des services Internet. + + Éléments + Active la diffusion adaptive en continu HTTP d’éléments à la demande sur les clients. + Interface utilisateur + Configure la fonctionnalité de diffusion en continu lisse dans le Gestionnaire des services Internet. + + Canaux + Active la diffusion adaptive en continu HTTP de canaux sur les clients. + Interface utilisateur + Configure la fonctionnalité Live Smooth Streaming dans le Gestionnaire des services Internet. + + Gestion des droits numériques (DRM) + Fournit le chiffrement et la licence des médias de diffusion en continu lisse. + Interface utilisateur + Configure la fonctionnalité Gestion des droits numériques (DRM) dans le Gestionnaire des services Internet. + + [ProductName] requiert Microsoft Windows Vista Service Pack 1 ou version ultérieure. + [ProductName] ne peut pas être installé sur Vista Édition Familiale Basique. + [ProductName] requiert Microsoft Windows 7 Service Pack 1 ou version ultérieure. + + + Gestionnaire de bases de données IIS + Gestionnaire de bases de données IIS + + + Service de gestion Web Microsoft 2 + Service de gestion Web Microsoft + Installe les fonctionnalités de base de [ProductName]. + Service de gestion Web Microsoft 2 + Le service de gestion Web offre des fonctionnalités de gestion déléguée et à distance permettant aux administrateurs de gérer le serveur Web, les sites et les applications présents sur cet ordinateur. + + + Module de réécriture d'URL 1.1 Microsoft pour IIS 7 + Mise à jour pour le Module de réécriture d'URL 1.1 pour IIS 7 + Réécriture d'URL + Active des fonctionnalités de réécriture d'URL et de contenu pour IIS 7. + Interface utilisateur + Configure la fonctionnalité Module de réécriture d'URL dans le Gestionnaire des services Internet. + + + Module de réécriture d'URL 2 d'IIS + Mise à jour pour le Module de réécriture d'URL 2 d'IIS + Réécriture d'URL + Active des fonctionnalités de réécriture d'URL et de contenu pour IIS 7. + Interface utilisateur + Configure la fonctionnalité Module de réécriture d'URL dans le Gestionnaire des services Internet. + + + Pack d'administration IIS 7.0 + Installe les fonctionnalités de base de [ProductName]. + 1252 + Pack d'administration IIS 7.0 + Microsoft Corporation + Cette version du système d'exploitation n'est pas prise en charge. [ProductName] ne peut être installé que sur Windows Server 2008 ou Windows Vista Service Pack 1 et versions ultérieures. + Fonctionnalités ASP.Net + ASP.NET comprend les fonctionnalités d'autorisation et de pages d'erreurs, qui vous permettent de gérer les paramètres d'autorisations et d'erreurs personnalisées. + Authentification + Description de l'authentification ASP.Net. + Autorisation + L'autorisation ASP.NET vous permet de configurer des règles pour autoriser les utilisateurs à accéder à vos applications et sites Web. + Pages d'erreurs + Les pages d'erreurs ASP.NET vous permettent de configurer les réponses d'erreurs HTTP à retourner lorsque des erreurs se produisent. + Modules + Description des modules ASP.Net. + Gestionnaires + Description des gestionnaires ASP.Net. + Éditeur de configuration + L'éditeur de configuration vous permet de gérer vos fichiers de configuration dans le Gestionnaire des services Internet en vous permettant de modifier des sections, des attributs, des éléments et des collections dans vos fichiers de configuration. + Filtrage des demandes + Le filtrage des demandes vous permet de configurer les règles de filtrage pour votre site Web et de limiter le comportement du protocole et du contenu. + FastCGI + FastCGI vous permet de configurer les paramètres du pool de processus pour les applications FastCGI sur votre serveur Web. + + + Programme d'installation de Restrictions dynamiques d'adresse IP pour IIS 7 + + + + + + + + + + + + + Restrictions dynamiques d'adresse IP pour IIS 7 - Bêta + Restrictions dynamiques d'adresse IP pour IIS 7 - Bêta 2 + Restrictions dynamiques d'adresse IP pour IIS 7 - Bêta 3 + + Restrictions dynamiques d'adresse IP pour IIS 7 - version finale (RC) + Restrictions dynamiques d'adresse IP pour IIS 7 - version finale (RC) 2 + Restrictions dynamiques d'adresse IP pour IIS 7 - version finale (RC) 3 + + Restrictions dynamiques d'adresse IP pour IIS 7 - RTW + + Restrictions dynamiques d'adresse IP pour IIS 7 + Interface utilisateur de Restrictions dynamiques d'adresse IP pour IIS 7 + + Restrictions d'adressage IP dynamique pour IIS 7 - Une version bêta a été détectée sur cet ordinateur. Désinstallez-la, puis réessayez + + + WebDAV 7.5 pour IIS 7.0 + Les fonctionnalités IIS 7.0 CoreWebEngine et W3SVC doivent être installées pour utiliser ce produit. + Module serveur WebDAV + Interface utilisateur de l'administration WebDAV + + + Kit de ressources d'optimisation du référencement d'un site auprès d'un moteur de recherche IIS 1.0 + Kit de ressources d'optimisation du référencement d'un site auprès d'un moteur de recherche IIS 1.0 + Kit de ressources d'optimisation du référencement d'un site auprès d'un moteur de recherche (SEO) 1.0 + La base de données de ce programme d'installation contient la logique et les données requises pour installer le Kit de ressources d'optimisation du référencement d'un site auprès d'un moteur de recherche IIS 1.0. + + + Éditeur IIS + + + Rapports IIS + Log Parser n'est pas installé sur cet ordinateur. Installez Log Parser 2.2 à partir de http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, puis installez les rapports IIS + + + Les packages de composants requis sont introuvables. Exécutez setup.exe pour résoudre les dépendances et installer ce programme. + Microsoft SQL Server 2008 Management Objects doit être installé avant l'installation du Gestionnaire de bases de données IIS. Vous pouvez installer Microsoft SQL Server 2008 Management Objects à partir de http://go.microsoft.com/fwlink/?LinkID=150946 . + Microsoft SQL Server System CLR Types doit être installé avant l'installation du Gestionnaire de bases de données IIS. Vous pouvez installer Microsoft SQL Server System CLR Types à partir de http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework est un composant requis pour l'installation d'Application Request Routing. Installez Web Farm Framework. + Microsoft Application Request Routing 2.5 + Exécution + Ajoute les fonctionnalités d'Application Request Routing à IIS. + Interface utilisateur + Configure la fonctionnalité Application Request Routing dans le Gestionnaire des services Internet. + + + Composant logiciel enfichable Microsoft Windows PowerShell pour IIS 7.0 + + + Microsoft Web Platform Installer 4.0 + + Microsoft Web Platform Installer + [ProductName] requiert Windows XP SP2, Windows 2003 SP1, Windows Vista ou versions ultérieures. + [ProductName] requiert Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 ou versions ultérieures. + + + Programme d'installation des services Microsoft Windows Azure + Programme d'installation des services Microsoft Windows Azure + + + Gestionnaire des services Internet (IIS) 7+ + Client du Gestionnaire des services Internet + Support à distance + Ce produit requiert Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 ou une version supérieure + La console de gestion IIS n'est pas installée, mais est requise pour gérer les serveurs IIS distants. Installez la console de gestion IIS avant d'installer le support de gestion à distance en ouvrant 'Panneau de configuration->Programmes->Activer ou désactiver des fonctionnalités Windows' et en sélectionnant la console de gestion IIS dans la fonctionnalité Services Internet. + Ce produit n'est pas requis dans Windows Server 2008 ou Windows Server 2008 R2 ou une version ultérieure. Installez la console de gestion IIS en ouvrant le Gestionnaire de serveur et en sélectionnant la console de gestion IIS dans les services de rôle pour le rôle Serveur Web. + + + Gestionnaire de publication pour IIS 7.0 + Interface utilisateur de publication + + + Application Warm-Up 1.0 pour IIS 7.5 + + + + Un produit incompatible, [CONFLICTING_PRODUCT_NAME], se trouve sur cet ordinateur. Impossible de poursuivre l'installation de [ProductName]. Pour installer ce produit, utilisez Ajouter/Supprimer les programmes dans le Panneau de configuration pour supprimer [CONFLICTING_PRODUCT_NAME]. + Des privilèges administrateur sont requis pour installer [ProductName]. + IIS version 7.0 est requis pour utiliser [ProductName]. + IIS version 7.0 ou supérieure est requis pour installer [ProductName]. + IIS version 7.5 ou supérieure est requis pour installer [ProductName]. + IIS version 7 ou 7.5 est requis pour installer [ProductName]. + La version bêta de [ProductName] est installée sur cet ordinateur. + Une version plus récente de [ProductName] est installée sur cet ordinateur. + Le programme d'installation ne peut pas continuer car une autre instance de [ProductName] est déjà installée sur cet ordinateur. Désinstallez-la, puis relancez l'installation. + Les fonctionnalités IIS 7.0 CoreWebEngine et W3SVC doivent être installées pour utiliser [ProductName]. + Les fonctionnalités de la console de gestion IIS doivent être installées pour utiliser [ProductName]. + Arrêtez les services d'activation des processus Windows (WAS) et de gestion Web (WMSvc) avant d'installer [ProductName]. Vous devrez redémarrer les services après avoir installé [ProductName]. + La métabase IIS est requise pour installer [ProductName]. + La version 64 bits de [ProductName] ne peut pas être installée sur une édition 32 bits de Microsoft Windows. + La version 32 bits de [ProductName] ne peut pas être installée sur une édition 64 bits de Microsoft Windows. + Microsoft .NET Framework version 2.0 ou supérieure est requise pour installer [ProductName]. + Microsoft .NET Framework version 3.5 ou supérieure est requis pour installer [ProductName]. Utilisez l'option d'ajout de fonctionnalités du Gestionnaire de serveur pour installer Microsoft .NET Framework version 3.5. + Microsoft .NET Framework version 4.0 ou supérieure est requis pour installer [ProductName]. + Installez Microsoft .NET Framework version 2.0 Service Pack 1 (ou SP supérieur), avant d'installer [ProductName]. + Le service Windows Update (wuauserv) ne peut pas être désactivé, il est requis pour installer [ProductName]. + Le composant logiciel enfichable PowerShell fait partie du système d'exploitation Windows. Installez-le via 'Programmes et fonctionnalités' ou 'Gestionnaire de serveur'. + Microsoft Web Platform Installer version 3.0 ou supérieure est requis pour installer [ProductName]. + + Le programme d'installation n'a pas réussi à détecter la configuration partagée. + La configuration partagée est activée pour IIS. L'installation de [ProductName] n'est pas prise en charge lors de l'utilisation d'une configuration partagée. Désactivez la configuration partagée avant d'installer cette fonctionnalité. + + Arrêtez le service de publication World Wide Web (W3SVC) avant d'installer [ProductName]. Vous devrez le redémarrer après l'installation. + Console de gestion PowerShell IIS + Composant logiciel enfichable PowerShell IIS + Le composant logiciel enfichable PowerShell IIS requiert PowerShell v1.0 ou v2.0 + Le composant logiciel enfichable PowerShell IIS requiert WAS et une configuration + Chaîne d'exemple. + + + Microsoft Web Farm Framework Version 2.2 + Microsoft Web Farm Agent Version 2.2 + Service de batterie de serveurs Web + Service de batterie de serveurs Web + Service du contrôleur de batterie de serveurs Web + Service du contrôleur de batterie de serveurs Web + Service de l'agent de batterie de serveurs Web + Service de l'agent de batterie de serveurs Web + Web Platform Installer est un composant requis pour l'installation de Web Farm Framework 2.0. Installez Web Platform Installer à partir de http://www.microsoft.com/web/downloads/platform.aspx. + L'Outil de déploiement Web est un composant requis pour l'installation de Web Farm Framework. Installez l'Outil de déploiement Web à partir de http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Rôles et fonctionnalités de l'hébergement Web. + Hosting Framework + Hosting Framework fournit les commandes des API et de PowerShell pour la gestion de l'hébergement Web. + Rôle Web + Le rôle Web installe le service dynamique WAS et le fournisseur de réécriture d'URL pour l'hébergement Web. + Antares Express + Déploie une configuration du Panneau de configuration optimisée pour l'installation sur un seul ordinateur. + Rôle de l'équilibrage de charge + Le rôle de l'équilibrage de charge configure le routeur des requêtes d'applications pour diriger les règles d'hébergement Web. + Contrôleur d'hébergement + Le contrôleur d'hébergement étend Web Farm Framework 2.0 pour être utilisé avec l'hébergement Web. + Rôle de publication + Installe le support pour le déploiement Web et la publication FTP. + Il s'agit d'un composant logiciel enfichable PowerShell qui contient des applets de commande pour gérer l'infrastructure Microsoft Web Hosting. + Service WAS dynamique + Service d'activation de processus Windows optimisé pour l'hébergement Web grande densité. + Service Contrôle des ressources + Installe le service Contrôle des ressources qui permet de collecter et de publier des informations d'exécution et d'intégration. + Contrôle des ressources + Active la collecte et la publication des informations sur l'exécution et l'intégration à partir du rôle Web. + Hébergement de l'application des quotas + Surveille l'utilisation des ressources des sites Web et exécute des actions personnalisées lorsque le quota d'utilisation est dépassé. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ITA/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ITA/misc/setupstrings.wxl new file mode 100644 index 0000000000..238a9292f9 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ITA/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1040 + + + + Opzioni di installazione configurazione condivisa + Selezionare un'opzione per l'installazione nella configurazione condivisa di IIS + Aggiorna configurazione condivisa al momento dell'installazione + Questo modulo verrà installato su un server IIS che utilizza una configurazione condivisa. Se altri server IIS utilizzano la medesima configurazione condivisa, sarà necessario installare il modulo in ciascuno di essi. Per ridurre al minimo l'interruzione dei servizi dei singoli server Web, sarà necessario installare il modulo attenendosi alla procedura seguente: in tutti i computer tranne l'ultimo installare il modulo senza aggiornare la configurazione condivisa. A tale scopo, non selezionare la casella di controllo sotto. +In questo modo, verranno installati tutti i dati binari e i file necessari per il modulo in ogni computer senza apportare modifiche alla configurazione condivisa. A questo punto, nell'ultimo computer sarà necessario verificare che l'identità dell'utente in uso disponga di accesso in lettura e scrittura al file applicationhost.config nella condivisione UNC. Installare quindi il modulo e selezionare l'opzione di configurazione aggiornata sotto. + + + Inizializzazione dell'azione personalizzata WebConfig + Aggiornamento di web.config + + + + Registrazione avanzata IIS + Consente la registrazione avanzata dei della pipeline IIS. + Registrazione avanzata IIS + Consente la creazione di file di registro personalizzati con selezione campi estendibile. + Aggiornamento per IIS Advanced Logging + + + + IIS Transform Manager + Beta + Abilita IIS Media Services di Transform Manager. + IIS Transform Manager + Abilita la creazione di trasformazioni multimediali. + Host di IIS Transform Manager + Host del servizio per [ProductName]. + IIS Transform Manager + Esegue la conversione batch dei file multimediali su richiesta per alternare formati di file e contenitori. + Nel computer è installato un pacchetto IIS Transform Manager 1.0 Expression Encoder SP Task. È necessario disinstallarlo prima di eseguire l'installazione di [ProductName]. + + Per installare [ProductName] è necessario Microsoft .NET Framework 3.5. Utilizzare 'Aggiunta guidata funzionalità' in Server Manager per installare Funzionalità di .NET Framework 3.5.1 oppure utilizzare 'Attiva o disattiva le funzionalità Windows' per attivare Microsoft .NET Framework 3.5. + + + + IIS Digital Rights Management + Beta + Abilita Digital Rights Management di presentazioni Smooth Streaming. + + + ASP.NET non installato + + + + + + + + + IIS Smooth Streaming - Beta rilevato in questo computer. Impossibile continuare l'installazione di [ProductName]. Per installare il prodotto, utilizzare Installazione applicazioni nel Pannello di controllo per rimuovere IIS Smooth Streaming - Beta. + Una versione non compatibile di IIS Media Services è stata rilevata in questo computer. Impossibile continuare l'installazione di [ProductName]. Per installare il prodotto, utilizzare Installazione applicazioni nel Pannello di controllo per rimuovere IIS Media Services. + Nel computer in uso è già installata o disponibile per l'installazione una versione più recente del prodotto. Impossibile continuare l'installazione di [ProductName]. Per installare la versione più recente del prodotto, utilizzare Installazione applicazioni nel Pannello di controllo per aggiornare IIS Media Services. + Conversione file elenco di riproduzione obbligatoria + + + + + Rilevati file di una versione precedente di IIS Media Services + + + + + Rilevati file di una versione beta di IIS Media Services + + + + + + IIS Media Pack 1.0 + Aggiornamento per IIS Media Pack 1.0 + IIS Media Services 2.0 + Aggiornamento per IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Aggiornamento per IIS Media Services 3.0 + Funzionalità e strumenti di IIS Media Services. + Funzionalità e strumenti di IIS Media Services 5 Premium. + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web Playlists + Controlla la riproduzione del client di asset di file multimediali a cui si fa riferimento negli elenchi di riproduzione. + Session Helper + Consente la persistenza dello stato della sessione ASP.NET. Richiede il servizio ruolo ASP.NET per Server Web (IIS). + Interfaccia utente + Configura la funzionalità Web Playlists in Gestione IIS. + + Bit Rate Throttling + Riduce la larghezza di banda necessaria limitando il recapito dei file scaricati dai client. + Interfaccia utente + Configura la funzionalità Bit Rate Throttling in Gestione IIS. + + Asset + Consente il flusso adattivo HTTP degli asset su richiesta nei client. + Interfaccia utente + Configura la funzionalità Smooth Streaming in Gestione IIS. + + Canali + Consente il flusso adattivo HTTP delle trasmissioni di canale ai client. + Interfaccia utente + Configura la funzionalità Live Smooth Streaming in Gestione IIS. + + Digital Rights Management + Fornisce crittografia e licenze dei file multimediali Smooth Streaming. + Interfaccia utente + Configura la funzionalità Digital Rights Management in Gestione IIS. + + [ProductName] richiede Microsoft Windows Vista Service Pack 1 o versione successiva. + Impossibile installare [ProductName] in Vista Home Basic. + [ProductName] richiede Microsoft Windows 7 Service Pack 1 o versione successiva. + + + IIS Database Manager + IIS Database Manager + + + Servizio Gestione Web Microsoft 2 + Servizio Gestione Web Microsoft + Installa le funzionalità di base di [ProductName]. + Servizio Gestione Web Microsoft 2 + Il servizio Gestione Web offre agli amministratori funzionalità di gestione remota e delegata per il server Web, i siti e le applicazioni presenti nel computer. + + + Microsoft URL Rewrite Module 1.1 per IIS 7 + Aggiornamento per URL Rewrite Module 1.1 per IIS 7 + URL Rewrite + Abilita le funzionalità di riscrittura del contenuto e degli URL in IIS 7. + Interfaccia utente + Configura la funzionalità URL Rewrite Module in Gestione IIS. + + + IIS URL Rewrite Module 2 + Aggiornamento per IIS URL Rewrite Module 2 + URL Rewrite + Abilita le funzionalità di riscrittura del contenuto e degli URL in IIS 7. + Interfaccia utente + Configura la funzionalità URL Rewrite Module in Gestione IIS. + + + Administration Pack per IIS 7.0 + Installa le funzionalità di base di [ProductName]. + 1252 + Administration Pack per IIS 7.0 + Microsoft Corporation + Questa versione del sistema operativo non è supportata. [ProductName] può essere installato solo con Windows Server 2008 o Windows Vista Service Pack 1 e versioni successive. + Funzionalità ASP.Net + ASP.NET include le funzionalità Pagine errori e autorizzazione, che consentono di gestire le impostazioni di errori personalizzati e di autorizzazione. + Autenticazione + Descrizione dell'autenticazione ASP.Net. + Autorizzazione + L'autorizzazione ASP.NET consente di configurare le regole per autorizzare gli utenti ad accedere a siti Web e applicazioni. + Pagine errori + Le pagine errori ASP.NET consentono di configurare le risposte di errore HTTP da restituire in caso di errori. + Moduli + Descrizione dei moduli ASP.Net. + Gestori + Descrizione dei gestori ASP.Net. + Editor di configurazione + Editor di configurazione consente di gestire i file di configurazione in Gestione IIS offrendo la possibilità di modificare sezioni, attributi, elementi e raccolte all'interno dei file di configurazione. + Filtro richieste + Filtro richieste consente di configurare le regole di filtro per il sito Web e di limitare il comportamento di protocollo e contenuto. + FastCGI + FastCGI consente di configurare le impostazioni del pool di processi per le applicazioni FastCGI del server Web. + + + Restrizioni IP dinamico per l'installazione di IIS 7 + + + + + + + + + + + + + Restrizioni IP dinamico per IIS 7 - Beta + Restrizioni IP dinamico per IIS 7 - Beta 2 + Restrizioni IP dinamico per IIS 7 - Beta 3 + + Restrizioni IP dinamico per IIS 7 - Versione finale candidata + Restrizioni IP dinamico per IIS 7 - Versione finale candidata 2 + Restrizioni IP dinamico per IIS 7 - Versione finale candidata 3 + + Restrizioni IP dinamico per IIS 7 - RTW + + Restrizioni IP dinamico per IIS 7 + Interfaccia utente di Restrizioni IP dinamico per IIS 7 + + Restrizioni IP dinamico per IIS 7 - Beta rilevato nel computer. Disinstallarlo, quindi riprovare + + + WebDAV 7.5 per IIS 7.0 + Per utilizzare questo prodotto, è necessario installare le funzionalità CoreWebEngine e W3SVC di IIS 7.0. + Modulo server WebDAV + Interfaccia utente di amministrazione WebDAV + + + IIS Search Engine Optimization Toolkit 1.0 + IIS Search Engine Optimization Toolkit 1.0 + Search Engine Optimization (SEO) Toolkit 1.0 + Il database del programma di installazione contiene la logica e i dati necessari per l'installazione di IIS Search Engine Optimization Toolkit 1.0. + + + Editor IIS + + + Report IIS + Log Parser non installato nel computer in uso. Installare Log Parser 2.2 dal sito Web http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, quindi continuare con l'installazione di Report IIS. + + + Pacchetti dei prerequisiti non trovati. Eseguire setup.exe per risolvere le dipendenze e installare il programma. + Microsoft SQL Server 2008 Management Objects è un prerequisito per l'installazione di IIS Database Manager. È possibile installare Microsoft SQL Server 2008 Management Objects dal sito http://go.microsoft.com/fwlink/?LinkID=150946. + Microsoft SQL Server System CLR Types è un prerequisito per l'installazione di IIS Database Manager. È possibile installare Microsoft SQL Server System CLR Types dal sito http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework è un requisito per l'installazione di Application Request Routing. Installare Web Farm Framework. + Microsoft Application Request Routing 2.5 + Runtime + Aggiunge le funzionalità di Application Request Routing a IIS. + Interfaccia utente + Configura la funzionalità Application Request Routing in Gestione IIS. + + + Snap-in di Microsoft Windows PowerShell per IIS 7.0 + + + Installazione guidata piattaforma Web Microsoft 4.0 + Installazione guidata piattaforma Web Microsoft + [ProductName] richiede Windows XP SP2, Windows 2003 SP1, Windows Vista o versione successiva. + [ProductName] richiede Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 o versione successiva. + + + Programma di installazione servizi Microsoft Windows Azure + Programma di installazione servizi Microsoft Windows Azure + + + Gestione Internet Information Services (IIS) 7+ + Client Gestione IIS + Remoting Support + Per questo prodotto è necessario Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 o versione successiva + La Console di gestione IIS necessaria per la gestione dei server IIS remoti non è installata. Installare la Console di gestione IIS prima di installare il supporto di gestione remoto. A tale scopo, aprire "Pannello di controllo->Programmi->Attiva o disattiva le funzionalità Windows" e selezionare Console di gestione IIS nella funzionalità Internet Information Services. + Questo prodotto non è necessario in Windows Server 2008 o in Windows Server 2008 R2 o versione successiva. Per installare la Console di gestione IIS, aprire Gestione server e selezionare la Console di gestione IIS nei Servizi ruolo per il ruolo Server Web. + + + IIS Manager Publishing per IIS 7.0 + Interfaccia utente di pubblicazione + + + Application Warm-Up 1.0 per IIS 7.5 + + + + Nel computer è installato un prodotto incompatibile, [CONFLICTING_PRODUCT_NAME]. Non è possibile continuare l'installazione di [ProductName]. Per installare il prodotto, utilizzare Installazione applicazioni nel Pannello di controllo e rimuovere [CONFLICTING_PRODUCT_NAME]. + Per installare [ProductName], sono richiesti i privilegi di amministratore. + Per utilizzare [ProductName], è richiesto IIS versione 7.0. + Per installare [ProductName], è richiesto IIS versione 7.0 o versione successiva. + Per installare [ProductName] è necessario IIS 7.5 o versione successiva. + Per installare [ProductName] è necessario IIS versione 7 o 7.5. + Versione beta di [ProductName] rilevata nel computer in uso. + Nel computer in uso è stata rilevata una versione più recente di [ProductName]. + L'installazione non può continuare poiché un'altra istanza di [ProductName] è già installata nel computer in uso. Disinstallarla e quindi riavviare l'installazione. + Per utilizzare [ProductName], è necessario installare le funzionalità CoreWebEngine e W3SVC di IIS 7.0. + Per utilizzare [ProductName], è necessario installare la Console di gestione IIS. + Arrestare Servizio Attivazione processo Windows (WAS) e Servizio di gestione Web (WMSvc) prima di installare [ProductName]. Avviare i servizi dopo l'installazione di [ProductName]. + Per installare [ProductName], è richiesta la metabase IIS. + Impossibile installare la versione a 64 bit di [ProductName] in un'edizione a 32 bit di Microsoft Windows. + Impossibile installare la versione a 32 bit di [ProductName] in un'edizione a 64 bit di Microsoft Windows. + Per installare [ProductName], è richiesto Microsoft .NET Framework versione 2.0 o versione successiva. + Microsoft .NET Framework versione 3.5 o successiva necessario per installare [ProductName]. Utilizzare 'Aggiungi funzionalità' in Server Manager per installare Microsoft .NET versione 3.5. + Microsoft .NET Framework versione 4.0 o successiva necessario per installare [ProductName]. + Prima di installare [ProductName], installare Microsoft .NET Framework versione 2.0 Service Pack 1 o versione successiva. + Impossibile disabilitare il servizio Windows Update (wuauserv). È richiesto per installare [ProductName]. + Lo snap-in di PowerShell fa parte del sistema operativo Windows. Installarlo mediante 'Programmi e funzionalità' o 'Server Manager'. + Installazione guidata piattaforma Web di Microsoft versione 3.0 o successiva necessaria per installare [ProductName]. + + Impossibile rilevare la configurazione condivisa. + Configurazione condivisa abilitata per IIS. L'installazione di [ProductName] non è supportata quando si utilizza la configurazione condivisa. Disabilitare la configurazione condivisa prima di installare questa funzionalità. + + Arrestare il Servizio Pubblicazione sul Web (W3SVC) prima di installare [ProductName]. Avviare il servizio dopo l'installazione. + Console di gestione IIS PowerShell + Snap-in di IIS PowerShell + Lo snap-in di IIS PowerShell richiede l'installazione di PowerShell v1.0 o v2.0 + Lo snap-in di IIS PowerShell richiede l'installazione di WAS e della configurazione + Stringa non valida. + + + Microsoft Web Farm Framework versione 2.2 + Microsoft Web Farm Agent versione 2.2 + Servizio Web Farm + Servizio Web Farm + Servizio controller Web Farm + Servizio controller Web Farm + Servizio agente Web Farm + Servizio agente Web Farm + L'Installazione guidata piattaforma Web è un prerequisito per l'installazione di Web Farm Framework. Eseguire l'Installazione guidata piattaforma Web dall'indirizzo http://www.microsoft.com/web/downloads/platform.aspx. + Lo Strumento di distribuzione Web è un prerequisito per l'installazione di Web Farm Framework. Installare lo Strumento di distribuzione Web dall'indirizzo http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Ruoli e funzionalità di Web Hosting. + Framework di hosting + Framework di hosting fornisce le API e i comandi PowerShell per la gestione di Web Hosting. + Ruolo Web + Ruolo Web esegue l'installazione del Servizio Attivazione processo Windows dinamico e del provider di URL Rewrite per Web Hosting. + Antares Express + Esegue la distribuzione di una configurazione del Pannello di controllo ottimizzata per l'installazione su singolo computer. + Ruolo bilanciamento del carico + Ruolo bilanciamento del carico configura Application Request Router per il routing in base alle regole di Web Hosting. + Controller di hosting + Controller di hosting estende Web Farm Framework 2.0 per consentirne il funzionamento con Web Hosting. + Ruolo di pubblicazione + Installa il supporto per la pubblicazione mediante Distribuzione Web e FTP. + Lo snap-in di PowerShell contiene i cmdlet per gestire l'infrastruttura Microsoft Web Hosting. + Servizio Attivazione processo Windows dinamico + Servizio Attivazione processo Windows dinamico ottimizzato per Web Hosting ad alta densità. + Servizio Misurazione risorse + Installa il servizio Misurazione risorse che abilita la raccolta e la pubblicazione delle informazioni sul runtime e sull'integrità. + Misurazione risorse + Abilita la raccolta e la pubblicazione delle informazioni sul runtime e sull'integrità da parte di Ruolo Web. + Imposizione quota hosting + Esegue il monitoraggio dell'utilizzo delle risorse dei siti Web ed esegue azioni personalizzate quando la quota relativa all'utilizzo viene superata. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/JPN/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/JPN/misc/setupstrings.wxl new file mode 100644 index 0000000000..ac70825d59 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/JPN/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1041 + + + + 共有構成のインストール オプション + IIS 共有構成をインストールするためのオプションを選択します + インストール時に共有構成を更新する + 共有構成を使用する IIS サーバーに、このモジュールをインストールしようとしています。その他の IIS サーバーでこの共有構成を使用している場合は、これらすべてのコンピューターにこのモジュールをインストールする必要があります。個々の Web サーバーの障害を最小限に抑えるには、以下の手順でこのモジュールをインストールします。まず、最後の 1 台を除くすべてのコンピューターに、共有構成を更新せずにモジュールをインストールします。そのためには、下のチェック ボックスをオフにします。 +これにより、共有構成に変更を加えることなく、各コンピューターでモジュールに必要なバイナリとファイルがすべてインストールされます。次に、最後のコンピューターで、実行に使用しているユーザー ID が、UNC 共有にある applicationhost.config ファイルに対する読み取りと書き込みのアクセス権を持っていることを確認します。そのうえで、モジュールをインストールし、下にある [インストール時に共有構成を更新する] チェック ボックスをオンにします。 + + + WebConfig カスタム アクションを初期化しています + web.config を更新しています + + + + IIS 詳細ログ + IIS パイプライン データの詳細ログを有効にします。 + IIS 詳細ログ + 拡張可能なフィールド選択機能を備えたカスタム ログ ファイルの作成を有効にします。 + IIS 詳細ログの更新 + + + + IIS Transform Manager + Beta + Transform Manager の IIS Media Services を有効にします。 + IIS Transform Manager + メディア変換の作成を有効にします。 + IIS Transform Manager ホスト + [ProductName] 用のサービス ホスト。 + IIS Transform Manager + オンデマンド メディア ファイルを代替ファイルおよびコンテナー形式にバッチで変換します。 + IIS Transform Manager 1.0 Expression Encoder SP Task パッケージがコンピューターにインストールされています。[ProductName] をインストールする前にそのパッケージをアンインストールする必要があります。 + + [ProductName] をインストールするには、Microsoft .NET Framework 3.5 が必要です。サーバー マネージャーの機能の追加ウィザードを使用して .NET Framework 3.5.1 の各機能をインストールするか、[Windows の機能の有効化または無効化] を使用して Microsoft .NET Framework 3.5 を有効にします。 + + + + IIS デジタル著作権管理 + Beta + Smooth Streaming プレゼンテーションのデジタル著作権管理を有効にします。 + + + ASP.NET がインストールされていません + + + + + + + + + このコンピューターで、IIS Smooth Streaming - Beta が見つかりました。[ProductName] のインストールを続行できません。この製品をインストールするには、コントロール パネルの [プログラムの追加と削除] を使用して、IIS Smooth Streaming - Beta をアンインストールしてください。 + このコンピューターには、互換性のないバージョンの IIS Media Services が存在します。[ProductName] のインストールを続行できません。この製品をインストールするには、コントロール パネルの [プログラムの追加と削除] を使用して、IIS Media Services をアンインストールしてください。 + このコンピューターには、この製品の新しいバージョンが既にインストールされているか、新しいバージョンを入手してインストールすることができます。[ProductName] のインストールを続行できません。この製品のより新しいバージョンをインストールするには、コントロール パネルの [プログラムの追加と削除] を使用して、IIS Media Services を更新してください。 + プレイリスト ファイルの変換が必要 + + + + + 古い IIS Media Services ファイルが見つかりました + + + + + ベータ版の IIS Media Services ファイルが見つかりました + + + + + + IIS Media Pack 1.0 + IIS Media Pack 1.0 の更新 + IIS Media Services 2.0 + IIS Media Services 2.0 の更新 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + IIS Media Services 3.0 の更新 + IIS Media Services の機能とツール。 + IIS Media Services 5 Premium の機能およびツール。 + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web プレイリスト + プレイリストで参照されたメディア アセットに対するクライアントの再生を制御します。 + セッション ヘルパー + ASP.NET セッション状態保持を有効にします (Web サーバー (IIS) の ASP.NET 役割サービスが必要)。 + ユーザー インターフェイス + IIS マネージャーで Web プレイリスト機能を構成します。 + + ビット レート調整 + クライアントによってダウンロードされるファイルの配信を制限することによって帯域幅を節約します。 + ユーザー インターフェイス + IIS マネージャーでビット レート調整機能を構成します。 + + アセット + クライアントに対し、オンデマンド アセットの HTTP アダプティブ ストリーミングを有効にします。 + ユーザー インターフェイス + IIS マネージャーで Smooth Streaming 機能を構成します。 + + チャネル + クライアントに対し、チャネル ブロードキャストの HTTP アダプティブ ストリーミングを有効にします。 + ユーザー インターフェイス + IIS Manager で Live Smooth Streaming 機能を構成します。 + + デジタル著作権管理 + Smooth Streaming メディアの暗号化とライセンスを提供します。 + ユーザー インターフェイス + IIS マネージャーでデジタル著作権管理機能を構成します。 + + [ProductName] には Microsoft Windows Vista Service Pack 1 以降が必要です。 + [ProductName] を Vista Home Basic にインストールすることはできません。 + [ProductName] には Microsoft Windows 7 Service Pack 1 以降が必要です。 + + + IIS Database Manager + IIS Database Manager + + + Microsoft Web Management Service 2 + Microsoft Web Management Service + [ProductName] の基本的な機能をインストールします。 + Microsoft Web Management Service 2 + Web 管理サービスでは、管理者がこのコンピューターの Web サーバー、サイトおよびアプリケーションを管理する機能をリモートで操作したり、委任したりすることができます。 + + + Microsoft URL Rewrite Module 1.1 for IIS 7 + URL Rewrite Module 2 for IIS 7 の更新 + URL 書き換え + IIS 7 への URL およびコンテンツの書き換え機能を有効にします。 + ユーザー インターフェイス + URL 書き換えモジュール機能を IIS マネージャーで構成します。 + + + IIS URL Rewrite Module 2 + IIS URL Rewrite Module 2 の更新プログラム + URL 書き換え + IIS 7 への URL およびコンテンツの書き換え機能を有効にします。 + ユーザー インターフェイス + URL 書き換えモジュール機能を IIS マネージャーで構成します。 + + + Administration Pack for IIS 7.0 + [ProductName] の基本的な機能をインストールします。 + 1252 + Administration Pack for IIS 7.0 + Microsoft Corporation + このバージョンのオペレーティング システムはサポートされません。[ProductName] は、Windows Server 2008 か、または Windows Vista Service Pack 1 以降にのみインストールできます。 + ASP.Net の機能 + ASP.NET には、承認とエラー ページの機能があり、それを使って承認やカスタム エラーの設定を管理できます。 + 認証 + ASP.Net 認証の説明。 + 承認 + ASP.NET の承認では、Web サイトおよびアプリケーションへのユーザーのアクセスを承認するための規則を構成できます。 + エラー ページ + ASP.NET エラー ページでは、エラー発生時に返す HTTP エラー応答を構成できます。 + モジュール + ASP.Net モジュールの説明。 + ハンドラー + ASP.Net ハンドラーの説明。 + 構成エディター + 構成エディターを使用して、IIS マネージャー内の構成ファイルを管理できます。構成ファイル内のセクション、属性、要素、およびコレクションを編集することができます。 + 要求のフィルタリング + 要求のフィルタリングでは、Web サイトのフィルタリング規則を構成したり、プロトコルやコンテンツの動作を制限したりできます。 + Fast CGI + FastCGI では、Web サーバー上の FastCGI アプリケーション用のプロセス プール設定を構成できます。 + + + Dynamic IP Restrictions for IIS 7 セットアップ + + + + + + + + + + + + + Dynamic IP Restrictions for IIS 7 - Beta + Dynamic IP Restrictions for IIS 7 - Beta 2 + Dynamic IP Restrictions for IIS 7 - Beta 3 + + Dynamic IP Restrictions for IIS 7 - リリース候補 + Dynamic IP Restrictions for IIS 7 - リリース候補 2 + Dynamic IP Restrictions for IIS 7 - リリース候補 3 + + Dynamic IP Restrictions for IIS 7 - RTW + + Dynamic IP Restrictions for IIS 7 + Dynamic IP Restrictions for IIS 7 のユーザー インターフェイス + + このコンピューターに Dynamic IP Restrictions for IIS 7 - Beta が見つかりました。アンインストールしてからやり直してください + + + WebDAV 7.5 For IIS 7.0 + この製品を使用するには、IIS 7.0 の CoreWebEngine および W3SVC 機能をインストールする必要があります。 + WebDAV サーバー モジュール + WebDAV 管理ユーザー インターフェイス + + + IIS Search Engine Optimization ツールキット 1.0 + IIS Search Engine Optimization ツールキット 1.0 + Search Engine Optimization (SEO) ツールキット 1.0 + このインストーラー データベースには、IIS Search Engine Optimization ツールキット 1.0 のインストールに必要なロジックとデータが含まれています。 + + + IIS エディター + + + IIS レポート + このコンピューターには、Log Parser がインストールされていません。http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 から Log Parser 2.2 をインストールし、IIS レポートのインストールを続行してください。 + + + 前提条件のパッケージが見つかりませんでした。setup.exe を実行して依存関係を解決してから、このプログラムをインストールしてください。 + IIS Database Manager のインストールの前提条件として、Microsoft SQL Server 2008 管理オブジェクトが必要です。Micrsoft SQL Server 2008 管理オブジェクトは http://go.microsoft.com/fwlink/?LinkID=150946 からインストールできます。 + IIS Database Manager のインストールの前提要件として、Microsoft SQL Server System CLR Types が必要です。Microsoft SQL Server System CLR Types は、http://go.microsoft.com/fwlink/?LinkID=150949 からインストールできます。 + + + Microsoft Web Farm Framework + Microsoft External Cache + アプリケーション要求ルーティング処理の前提条件として、Web Farm Framework が必要です。Web Farm Framework をインストールしてください。 + Microsoft Application Request Routing 2.5 + ランタイム + アプリケーション要求ルーティング処理の機能を IIS に追加します。 + ユーザー インターフェイス + アプリケーション要求ルーティング処理の機能を IIS マネージャーで構成します。 + + + Microsoft Windows PowerShell snap-in for IIS 7.0 + + + Microsoft Web Platform Installer 4.0 + Microsoft Web Platform Installer + [ProductName] には、Windows XP SP2、Windows 2003 SP1、Windows Vista 以降が必要です。 + [ProductName] には、Windows XP Service Pack 3、Windows Server 2003 Service Pack 2 以降が必要です。 + + + Microsoft Windows Azure サービス インストーラー + Microsoft Windows Azure サービス インストーラー + + + インターネット インフォメーション サービス (IIS) 7 以上のマネージャー + IIS マネージャー クライアント + リモート処理サポート + この製品には、Windows XP SP2、Windows 2003 SP1、Windows Vista SP1、または Windows 7 以上が必要です。 + リモート IIS サーバーを管理するために必要な IIS 管理コンソールがインストールされていません。コントロール パネルの [プログラム] で、[Windows の機能の有効化または無効化] を開き、Ineternet Information Services 機能から [IIS 管理コンソール] を選択して、IIS 管理コンソールをインストールしてから、リモート管理サポートをインストールしてください。 + この製品は、Windows Server 2008 または Windows Server 2008 R2 以上では必須ではありません。サーバー マネージャーを開き、Web サーバーの役割の役割サービスで [IIS 管理コンソール] を選択して、IIS 管理コンソールをインストールしてください。 + + + IIS Manager Publishing for IIS 7.0 + Publishing のユーザー インターフェイス + + + Application Warm-Up 1.0 for IIS 7.5 + + + + 互換性のない製品 [CONFLICTING_PRODUCT_NAME] がこのコンピューター上にあります。[ProductName] のインストールを続行できません。この製品をインストールするには、[コントロール パネル] の [プログラムの追加と削除] を使用して、[CONFLICTING_PRODUCT_NAME] を削除してください。 + [ProductName] をインストールするには管理者特権が必要です。 + [ProductName] を使用するには、IIS Version 7.0 が必要です。 + [ProductName] をインストールするには、IIS Version 7.0 以降が必要です。 + [ProductName] をインストールするには、IIS Version 7.5 以降が必要です。 + [ProductName] をインストールするには、IIS Version 7 または 7.5 が必要です。 + このコンピューターに [ProductName] のベータ版が見つかりました。 + このコンピューターに、より新しいバージョンの [ProductName] が見つかりました。 + このコンピューターには、[ProductName] の別のインスタンスが既にインストールされているため、セットアップを続行できません。最初にアンインストールしてから、再度インストールを行ってください。 + [ProductName] を使用するには、IIS 7.0 の CoreWebEngine および W3SVC 機能をインストールする必要があります。 + [ProductName] を使用するには、IIS 管理コンソールをインストールする必要があります。 + Windows プロセス起動サービス (WAS) と Web 管理サービス (WMSvc) の両方のサービスを停止してから、[ProductName] をインストールしてください。[ProductName] のインストール後にサービスを起動する必要があります。 + [ProductName] をインストールするには、IIS メタベースが必要です。 + 64 ビット版の [ProductName] を 32 ビット版の Microsoft Windows にインストールすることはできません。 + 32 ビット版の [ProductName] を 64 ビット版の Microsoft Windows にインストールすることはできません。 + [ProductName] をインストールするには、Microsoft .NET Framework Version 2.0 以降が必要です。 + [ProductName] をインストールするには、Microsoft .NET Framework Version 3.5 以降が必要です。サーバー マネージャーの [機能の追加] を使用して、Microsoft .Net Version 3.5 をインストールしてください。 + [ProductName] をインストールするには、Microsoft .NET Framework Version 4.0 以降が必要です。 + [ProductName] をインストールする前に、Microsoft .NET Framework Version 2.0 Service Pack 1 (またはそれ以降の Service Pack) をインストールしてください。 + Windows Update (wuauserv) サービスを無効にすることはできません。[ProductName] をインストールする場合は必須です。 + PowerShell スナップインは、Windows オペレーティング システムに付属しています。[プログラムと機能] またはサーバー マネージャーからインストールしてください。 + [ProductName] をインストールするには、Microsoft Web Platform Installer Version 3.0 以降が必要です。 + + 共有構成を検出できませんでした。 + IIS に対して共有構成が有効になっています。共有構成を使用している場合、[ProductName] をインストールすることはサポートされません。この機能をインストールする場合は、あらかじめ共有構成を無効にしてください。 + + [ProductName] をインストールする前に、World Wide Web 発行サービス (W3SVC) を停止してください。インストール後は、このサービスを起動する必要があります。 + IIS PowerShell 管理コンソール + IIS PowerShell スナップイン + IIS PowerShell スナップインを使用するには、PowerShell v1.0 または v2.0 がインストールされている必要があります。 + IIS PowerShell スナップインを使用するには、WAS および構成がインストールされている必要があります。 + これは仮の文字列です。 + + + Microsoft Web Farm Framework Version 2.2 + Microsoft Web Farm Agent Version 2.2 + Web Farm サービス + Web Farm サービス + Web Farm コントローラー サービス + Web Farm コントローラー サービス + Web Farm エージェント サービス + Web Farm エージェント サービス + Web Farm Framework をインストールする前提条件として、Web Platform Installer が必要です。http://www.microsoft.com/web/downloads/platform.aspx から Web Platform Installer をインストールしてください。 + Web Farm Framework をインストールする前提条件として、Web 配置ツールが必要です。http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=c7ca4240-5427-42ba-bd46-29a755549e37 (x64) または、http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=f2b0fe35-15ae-4638-b72e-f96535c64591 (x86) から Web 配置ツールをインストールしてください。 + + + Microsoft Web Hosting Framework + Web Hosting Framework + Web ホスティングの役割と機能。 + Hosting Framework + Hosting Framework は、Web ホスティングを管理するための API と PowerShell コマンドを提供します。 + Web ロール + Web ロールは、Web ホスティングのための動的 WAS サービスおよび URL 書き換えプロバイダーをインストールします。 + Antares Express + シングル コンピューター セットアップ用に最適化されたコントロール パネルの構成を展開します。 + 負荷分散装置の役割 + 負荷分散装置の役割は、Web ホスティングの規則を基にしてルーティングするようにアプリケーション要求ルーターを構成します。 + ホスティング コントローラー + ホスティング コントローラーは、Web ホスティングと連携するように Web Farm Framework 2.0 を拡張します。 + Publishing ロール + Web 配置および FTP 発行のサポートをインストールします。 + これは、Microsoft Web Hosting インフラストラクチャを管理するためのコマンドレットを含む PowerShell スナップインです。 + 動的 WAS サービス + 高密度な Web ホスティング用に最適化された Windows プロセス アクティブ化サービス。 + リソース メータリング サービス + ランタイムおよび正常性情報の両方の収集と発行を有効にする、リソース メータリング サービスをインストールします。 + リソース メータリング + Web ロールからのランタイムおよび正常性情報の収集と発行を有効にします。 + ホスティング クォータの強制 + Web サイトのリソースの使用率を監視し、使用率のクォータを超えた場合にカスタム アクションを実行します。 + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/KOR/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/KOR/misc/setupstrings.wxl new file mode 100644 index 0000000000..f4cb5f3312 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/KOR/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1042 + + + + 공유 구성 설치 옵션 + IIS 공유 구성 설치 옵션을 선택합니다. + 설치 시 공유 구성 업데이트 + 공유 구성을 사용 중인 IIS 서버에 이 모듈을 설치하는 중입니다. 이 공유 구성을 사용하는 IIS 서버가 더 있는 경우 해당하는 모든 컴퓨터에 이 모듈을 설치해야 합니다. 각 웹 서버의 장애를 최소화하려면 다음 절차에 따라 이 모듈을 설치해야 합니다. 첫째, 마지막 컴퓨터를 제외한 모든 컴퓨터에서 공유 구성을 업데이트하지 않고 모듈을 설치합니다. 아래의 확인란을 선택하지 않고 이 작업을 실행하십시오. +이렇게 하면 공유 구성을 변경하지 않고 모듈에 필요한 모든 파일 및 이진 파일이 각 컴퓨터에 설치됩니다. 둘째, 마지막 컴퓨터에서 사용자가 실행 중인 사용자 ID에 UNC 공유의 applicationhost.config 파일에 대한 읽기 및 쓰기 권한이 있는지 확인합니다. 그런 다음 모듈을 설치하고 아래의 업데이트 공유 구성 옵션을 선택합니다. + + + WebConfig 사용자 지정 작업을 초기화하는 중 + web.config 업데이트 중 + + + + IIS 고급 로깅 + IIS 파이프라인 데이터의 고급 로깅을 사용합니다. + IIS 고급 로깅 + 확장 가능한 필드 선택으로 사용자 지정 로그 파일을 만들 수 있도록 설정합니다. + IIS 고급 로깅 업데이트 + + + + IIS Transform Manager + 베타 + Transform Manager IIS 미디어 서비스를 활성화합니다. + IIS Transform Manager + 미디어 변환을 만들 수 있도록 설정합니다. + IIS Transform Manager 호스트 + [ProductName]의 서비스 호스트입니다. + IIS Transform Manager + 요청 시 미디어 파일을 대체 파일 및 컨테이너 형식으로 일괄 변환합니다. + 컴퓨터에 IIS Transform Manager 1.0 Expression Encoder SP 작업 패키지가 설치되어 있습니다. [ProductName]을(를) 설치하기 전에 IIS Transform Manager 1.0 Expression Encoder SP 작업 패키지를 제거해야 합니다. + + [ProductName]을(를) 설치하려면 Microsoft .NET Framework 3.5가 필요합니다. 서버 관리자에서 '기능 추가 마법사'를 사용하여 .NET Framework 3.5.1 기능을 설치하거나 'Windows 기능 사용/사용 안 함'을 사용하여 Microsoft .NET Framework 3.5 기능을 활성화합니다. + + + + IIS 디지털 권한 관리 + 베타 + 부드러운 스트리밍 프레젠테이션의 디지털 권한 관리를 활성화합니다. + + + ASP.NET이 설치되어 있지 않습니다. + + + + + + + + + 이 컴퓨터에 IIS 부드러운 스트리밍 - 베타가 있으므로 [ProductName] 설치를 계속할 수 없습니다. 이 제품을 설치하려면 제어판의 [프로그램 추가/제거]를 사용하여 IIS 부드러운 스트리밍 - 베타를 제거하십시오. + 이 컴퓨터에 IIS 미디어 서비스의 비호환 버전이 있으므로 [ProductName] 설치를 계속할 수 없습니다. 이 제품을 설치하려면 제어판의 [프로그램 추가/제거]를 사용하여 IIS 미디어 서비스를 제거하십시오. + 컴퓨터에 이 제품의 최신 버전이 이미 설치되어 있거나 설치에 사용할 수 있으므로 [ProductName] 설치를 계속할 수 없습니다. 이 제품의 최신 버전을 설치하려면 [제어판]에서 [프로그램 추가/제거]를 사용하여 IIS Media Services를 업데이트하십시오. + 재생 목록 파일 변환이 필요합니다. + + + + + 이전 IIS 미디어 서비스 파일이 있습니다. + + + + + 베타 IIS 미디어 서비스 파일이 있습니다. + + + + + + IIS Media Pack 1.0 + IIS Media Pack 1.0에 대한 업데이트 + IIS Media Services 2.0 + IIS Media Services 2.0에 대한 업데이트 + IIS Media Services 3.0 + IIS 미디어 서비스 3.0 TAP 2 + IIS Media Services 3.0에 대한 업데이트 + IIS Media Services 기능 및 도구입니다. + IIS Media Services 5 Premium 기능 및 도구입니다. + IIS 미디어 서비스 4.0 베타 1 + IIS 미디어 서비스 4.0 + IIS 미디어 서비스 4.5 베타 1 + IIS Media Services 5 Premium + + 웹 재생 목록 + 재생 목록에 참조된 미디어 자산의 클라이언트 재생을 제어합니다. + Session Helper + ASP.NET 세션 상태가 지속되도록 설정합니다(웹 서버(IIS)에 대한 ASP.NET 역할 서비스 필요). + 사용자 인터페이스 + IIS 관리자에서 웹 재생 목록 기능을 구성합니다. + + 비트 전송률 제한 + 클라이언트가 다운로드하는 파일 전달을 제한하여 대역폭을 절약합니다. + 사용자 인터페이스 + IIS 관리자에서 비트 전송률 제한 기능을 구성합니다. + + 자산 + 클라이언트에 대한 주문형 자산의 HTTP 적응 스트리밍을 사용하도록 설정합니다. + 사용자 인터페이스 + IIS 관리자에서 부드러운 스트리밍 기능을 구성합니다. + + 채널 + 클라이언트에 대한 채널 브로드캐스트의 HTTP 적응 스트리밍을 사용하도록 설정합니다. + 사용자 인터페이스 + IIS 관리자에서 Live Smooth Streaming 기능을 구성합니다. + + 디지털 권한 관리 + 부드러운 스트리밍 미디어의 암호화 및 라이선스를 제공합니다. + 사용자 인터페이스 + IIS 관리자의 디지털 권한 관리 기능을 구성합니다. + + [ProductName]에는 Microsoft Windows Vista 서비스 팩 1 이상이 필요합니다. + [ProductName]은(는) Vista Home Basic에 설치할 수 없습니다. + [ProductName]에는 Microsoft Windows 7 서비스 팩 1 이상이 필요합니다. + + + IIS 데이터베이스 관리자 + IIS 데이터베이스 관리자 + + + Microsoft Web Management Service 2 + Microsoft Web Management Service + [ProductName]의 기본 기능을 설치합니다. + Microsoft Web Management Service 2 + Web Management Service를 사용하면 관리자가 원격 및 위임된 관리 기능을 사용하여 이 컴퓨터에 있는 웹 서버, 사이트 및 응용 프로그램을 관리할 수 있습니다. + + + IIS 7용 Microsoft URL 재작성 모듈 1.1 + IIS 7용 URL 재작성 모듈 1.1에 대한 업데이트 + URL 재작성 + IIS 7에 대한 URL 및 콘텐츠 재작성 기능을 활성화합니다. + 사용자 인터페이스 + IIS 관리자에서 URL 재작성 모듈 기능을 구성합니다. + + + IIS URL 재작성 모듈 2 + IIS URL 재작성 모듈 2에 대한 업데이트 + URL 재작성 + IIS 7에 대한 URL 및 콘텐츠 재작성 기능을 활성화합니다. + 사용자 인터페이스 + IIS 관리자에서 URL 재작성 모듈 기능을 구성합니다. + + + IIS 7.0 관리 팩 + [ProductName]의 기본 기능을 설치합니다. + 1252 + IIS 7.0 관리 팩 + Microsoft Corporation + 이 운영 체제 버전은 지원되지 않습니다. [ProductName]은(는) Windows Server 2008 또는 Windows Vista 서비스 팩 1 이상에만 설치할 수 있습니다. + ASP.NET 기능 + ASP.NET에는 권한 부여 및 사용자 지정 오류 설정을 관리하는 데 사용할 수 있는 권한 부여 및 오류 페이지 기능이 있습니다. + 인증 + ASP.NET 인증에 대한 설명입니다. + 권한 부여 + ASP.NET 권한 부여를 사용하여 사용자에게 웹 사이트 및 응용 프로그램에 액세스할 수 있는 권한을 부여하는 규칙을 구성할 수 있습니다. + 오류 페이지 + ASP.NET 오류 페이지를 사용하여 오류가 발생했을 때 반환할 HTTP 오류 응답을 구성할 수 있습니다. + 모듈 + ASP.NET 모듈에 대한 설명입니다. + 처리기 + ASP.NET 처리기에 대한 설명입니다. + 구성 편집기 + 구성 편집기를 통해 구성 파일의 섹션, 특성, 요소 및 컬렉션을 편집하여 IIS 관리자의 구성 파일을 관리할 수 있습니다. + 요청 필터링 + 요청 필터링을 사용하여 웹 사이트에 대한 필터링 규칙을 구성하고 프로토콜 및 콘텐츠 동작을 제한할 수 있습니다. + Fast CGI + FastCGI를 사용하여 웹 서버의 FastCGI 응용 프로그램에 대한 프로세스 풀 설정을 구성할 수 있습니다. + + + IIS 7 설치에 대한 동적 IP 제한 + + + + + + + + + + + + + IIS 7용 동적 IP 제한 - 베타 + IIS 7용 동적 IP 제한 - 베타 2 + IIS 7용 동적 IP 제한 - 베타 3 + + IIS 7용 동적 IP 제한 - 릴리스 후보 + IIS 7용 동적 IP 제한 - 릴리스 후보 2 + IIS 7용 동적 IP 제한 - 릴리스 후보 3 + + IIS 7용 동적 IP 제한 - RTW + + IIS 7용 동적 IP 제한 + IIS 7용 동적 IP 제한 사용자 인터페이스 + + 이 시스템에서 IIS 7 - 베타에 대한 동적 IP 제한 사항이 발견되었습니다. 이 제한 사항을 제거한 후 다시 시도하십시오. + + + IIS 7.0용 WebDAV 7.5 + 이 제품을 사용하려면 IIS 7.0 CoreWebEngine 및 W3SVC 기능이 설치되어 있어야 합니다. + WebDAV 서버 모듈 + WebDAV 관리 사용자 인터페이스 + + + IIS 검색 엔진 최적화 도구 키트 1.0 + IIS 검색 엔진 최적화 도구 키트 1.0 + 검색 엔진 최적화(SEO) 도구 키트 1.0 + 이 설치 프로그램 데이터베이스에는 IIS 검색 엔진 최적화 도구 키트 1.0을 설치하는 데 필요한 논리 및 데이터가 들어 있습니다. + + + IIS 편집기 + + + IIS 보고서 + 이 컴퓨터에 Log Parser가 설치되어 있지 않습니다. http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07에서 Log Parser 2.2를 설치한 다음 IIS 보고서 설치를 계속하십시오. + + + 필수 구성 요소 패키지가 없습니다. setup.exe를 실행하여 종속성을 해결한 다음 이 프로그램을 설치하십시오. + IIS 데이터베이스 관리자를 설치하려면 Microsoft SQL Server 2008 관리 개체가 설치되어 있어야 합니다. http://go.microsoft.com/fwlink/?LinkID=150946에서 Microsoft SQL Server 2008 관리 개체를 설치할 수 있습니다. + IIS 데이터베이스 관리자를 설치하려면 Microsoft SQL Server System CLR Types가 설치되어 있어야 합니다. http://go.microsoft.com/fwlink/?LinkID=150949에서 Microsoft SQL Server System CLR Types를 설치할 수 있습니다. + + + Microsoft Web Farm Framework + Microsoft External Cache + 응용 프로그램 요청 라우팅을 설치하려면 Web Farm Framework가 설치되어 있어야 합니다. Web Farm Framework를 설치하십시오. + Microsoft 응용 프로그램 요청 라우팅 버전 2.5 + 런타임 + IIS에 응용 프로그램 요청 라우팅 기능을 추가합니다. + 사용자 인터페이스 + IIS 관리자에서 응용 프로그램 요청 라우팅 기능을 구성합니다. + + + IIS 7.0용 Microsoft Windows PowerShell 스냅인 + + + Microsoft 웹 플랫폼 설치 관리자 4.0 + Microsoft 웹 플랫폼 설치 관리자 + [ProductName]에는 Windows XP SP2, Windows 2003 SP1, Windows Vista 이상이 필요합니다. + [ProductName]을(를) 사용하려면 Windows XP 서비스 팩 3, Windows Server 2003 서비스 팩 2 이상이 필요합니다. + + + Microsoft Windows Azure Services 설치 관리자 + Microsoft Windows Azure Services 설치 관리자 + + + IIS(인터넷 정보 서비스) 7+ 관리자 + IIS 관리자 클라이언트 + 원격 지원 + 이 제품에는 Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 이상이 있어야 합니다. + 원격 IIS 서버 관리에 필요한 IIS 관리 콘솔이 설치되어 있지 않습니다. 원격 관리 지원을 설치하기 전에 '제어판->프로그램->Windows 기능 사용/사용 안 함'을 열고 인터넷 정보 서비스 기능에서 IIS 관리 콘솔을 선택하여 IIS 관리 콘솔을 설치하십시오. + 이 제품은 Windows Server 2008 또는 Windows Server 2008 R2 이상에서 필수 사항이 아닙니다. 서버 관리자를 열고 웹 서버 역할에 대한 역할 서비스에서 IIS 관리 콘솔을 선택하여 IIS 관리 콘솔을 설치하십시오. + + + IIS 7.0용 IIS 관리자 게시 + 게시 사용자 인터페이스 + + + IIS 7.5용 응용 프로그램 웜업 + + + + 이 컴퓨터에 호환되지 않는 제품 [CONFLICTING_PRODUCT_NAME]이(가) 있습니다. [ProductName]의 설치를 계속할 수 없습니다. 이 제품을 설치하려면 제어판에서 프로그램 추가/제거를 사용하여 [CONFLICTING_PRODUCT_NAME]을(를) 제거하십시오. + [ProductName]을(를) 설치하려면 관리자 권한이 있어야 합니다. + [ProductName]을(를) 사용하려면 IIS 버전 7.0이 있어야 합니다. + [ProductName]을(를) 설치하려면 IIS 버전 7.0 이상이 있어야 합니다. + [ProductName]을(를) 설치하려면 IIS 버전 7.5 이상이 있어야 합니다. + [ProductName]을(를) 설치하려면 IIS 버전 7 또는 7.5가 있어야 합니다. + 이 컴퓨터에 [ProductName]의 베타 버전이 설치되어 있습니다. + 이 컴퓨터에 [ProductName]의 상위 버전이 설치되어 있습니다. + 컴퓨터에 [ProductName]의 다른 인스턴스가 이미 설치되어 있어서 설치를 계속할 수 없습니다. 먼저 해당 인스턴스를 제거한 다음 설치 프로그램을 다시 시작하십시오. + [ProductName]을(를) 사용하려면 IIS 7.0 CoreWebEngine 및 W3SVC 기능이 설치되어 있어야 합니다. + [ProductName]을(를) 사용하려면 IIS 관리 콘솔이 설치되어 있어야 합니다. + [ProductName]을(를) 설치하기 전에 WAS(Windows Process Activation Service) 및 WMSvc(Web Management Service)를 모두 중지하십시오. [ProductName]을(를) 설치한 후에 해당 서비스를 시작해야 합니다. + [ProductName]을(를) 설치하려면 IIS 메타베이스가 있어야 합니다. + [ProductName] 64비트 버전은 Microsoft Windows 32비트 버전에 설치할 수 없습니다. + [ProductName] 32비트 버전은 Microsoft Windows 64비트 버전에 설치할 수 없습니다. + [ProductName]을(를) 설치하려면 Microsoft .NET Framework 버전 2.0 이상이 설치되어 있어야 합니다. + [ProductName]을(를) 설치하려면 Microsoft .NET Framework 버전 3.5 이상이 필요합니다. 서버 관리자에서 '기능 추가'를 사용하여 Microsoft .Net 버전 3.5를 설치하십시오. + [ProductName]을(를) 설치하려면 Microsoft .NET Framework 버전 4.0 이상이 필요합니다. + [ProductName]을(를) 설치하기 전에 Microsoft .NET Framework 버전 2.0 서비스 팩 1 이상을 설치하십시오. + [ProductName]을(를) 설치하는 데 필요하므로 Windows Update(wuauserv) 서비스를 비활성화할 수 없습니다. + PowerShell 스냅인은 Windows 운영 체제에 포함되어 있습니다. '프로그램 및 기능' 또는 '서버 관리자'를 사용하여 설치하십시오. + [ProductName]을(를) 설치하려면 Microsoft 웹 플랫폼 설치 관리자 버전 3.0 이상이 필요합니다. + + 설치 프로그램이 공유 구성을 검색하지 못했습니다. + IIS에 대해 공유 구성이 활성화되어 있습니다. 공유 구성을 사용하는 경우 [ProductName]을(를) 설치할 수 없습니다. 이 기능을 설치하려면 공유 구성을 비활성화하십시오. + + [ProductName]을(를) 설치하려면 먼저 W3SVC(World Wide Web Publishing Service)를 중지하십시오. 설치 후 해당 서비스를 다시 시작해야 합니다. + IIS PowerShell 관리 콘솔 + IIS PowerShell 스냅인 + IIS PowerShell 스냅인을 사용하려면 PowerShell v1.0 또는 v2.0이 설치되어 있어야 합니다. + IIS PowerShell 스냅인을 사용하려면 WAS 및 구성이 설치되어 있어야 합니다. + 임시 문자열입니다. + + + Microsoft Web Farm Framework 버전 2.2 + Microsoft 웹 팜 에이전트 버전 2.2 + 웹 팜 서비스 + 웹 팜 서비스 + 웹 팜 컨트롤러 서비스 + 웹 팜 컨트롤러 서비스 + 웹 팜 에이전트 서비스 + 웹 팜 에이전트 서비스 + Web Farm Framework를 설치하려면 웹 플랫폼 설치 관리자가 설치되어 있어야 합니다. 웹 플랫폼 설치 관리자는 http://www.microsoft.com/web/downloads/platform.aspx에서 설치하십시오. + Web Farm Framework를 설치하려면 웹 배포 도구가 설치되어 있어야 합니다. 웹 배포 도구는 http://www.iis.net/download/WebDeploy에서 설치하십시오. + + + Microsoft Web Hosting Framework + Web Hosting Framework + 웹 호스팅 역할 및 기능입니다. + Hosting Framework + Hosting Framework는 웹 호스팅을 관리하기 위한 API 및 PowerShell 명령을 제공합니다. + 웹 역할 + 웹 역할은 웹 호스팅용 동적 WAS 서비스 및 URL 재작성 공급자를 설치합니다. + Antares Express + 단일 컴퓨터 설치에 대해 최적화된 제어판 구성을 배포합니다. + 부하 분산 장치 역할 + 부하 분산 장치 역할은 웹 호스팅 규칙을 기반으로 라우팅하기 위한 응용 프로그램 요청 라우터를 구성합니다. + 호스팅 컨트롤러 + 호스팅 컨트롤러는 웹 호스팅과 작동하도록 Web Farm Framework 2.0을 확장합니다. + 게시 역할 + 웹 배포 및 FTP 게시에 대한 지원을 설치합니다. + Microsoft Web Hosting 인프라 관리를 위한 cmdlets가 포함된 PowerShell 스냅인입니다. + 동적 WAS 서비스 + 고밀도 웹 호스팅에 대해 최적화된 Windows Process Activation Service입니다. + 리소스 계량 서비스 + 런타임 및 상태 정보를 둘 다 수집하고 게시하는 리소스 계량 서비스를 설치합니다. + 리소스 계량 + 웹 역할의 런타임 및 상태 정보를 수집하고 게시할 수 있습니다. + 호스팅 할당량 적용 + 웹 사이트 리소스 사용을 모니터링하고 사용 할당량을 초과하면 사용자 지정 작업을 실행합니다. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PLK/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PLK/misc/setupstrings.wxl new file mode 100644 index 0000000000..fccd7b5d05 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PLK/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1045 + + + + Opcje instalacji w konfiguracji udostępnionej + Wybierz opcję instalacji w konfiguracji udostępnionej usług IIS + Aktualizuj konfigurację udostępnioną podczas instalacji + Ten moduł zostanie zainstalowany na serwerze usług IIS korzystającym z konfiguracji udostępnionej. Jeśli z tej konfiguracji udostępnionej korzysta więcej serwerów usług IIS, należy zainstalować ten moduł na wszystkich tych komputerach. Aby zminimalizować zakłócenia pracy poszczególnych serwerów sieci Web, najlepiej jest zainstalować ten moduł w następujący sposób: Najpierw zainstaluj moduł na wszystkich komputerach z wyjątkiem ostatniego bez aktualizowania konfiguracji udostępnionej. W tym celu nie zaznaczaj poniższego pola wyboru. + Wtedy na wszystkich komputerach zostaną zainstalowane wszystkie pliki binarne i inne wymagane przez moduł, ale nie zostaną wprowadzone żadne zmiany w konfiguracji udostępnionej. Następnie na ostatnim komputerze sprawdź, czy używana tożsamość użytkownika ma dostęp z prawem do zapisu i odczytu do pliku applicationhost.config w udziale UNC. Jeśli ma, zainstaluj moduł i wybierz poniższą opcję aktualizacji konfiguracji udostępnionej. + + + Inicjowanie akcji niestandardowej WebConfig + Aktualizowanie pliku web.config + + + + Zaawansowane rejestrowanie usług IIS + Włącza zaawansowane rejestrowanie danych potoku usług IIS. + Zaawansowane rejestrowanie usług IIS + Umożliwia tworzenie niestandardowych plików dziennika przy użyciu rozszerzalnego wyboru pól. + Aktualizacja zaawansowanego rejestrowania usług IIS + + + + Menedżer transformat usług IIS + Beta + Włącza menedżera transformat usług IIS Media. + Menedżer transformat usług IIS + Włącza tworzenie transformat plików multimedialnych. + Host menedżera transformat usług IIS + Host usługi programu [ProductName]. + Menedżer transformat usług IIS + Konwersja wsadowa plików multimedialnych na żądnie w celu zmiany formatów kontenerów i plików. + Na komputerze zainstalowano pakiet „IIS Transform Manager 1.0 Expression Encoder SP Task”. Należy go odinstalować przed zainstalowaniem produktu [ProductName]. + + Do zainstalowania produktu [ProductName] jest wymagany program Microsoft .NET Framework w wersji 3.5. Aby zainstalować funkcje programu .NET Framework 3.5.1, należy użyć Kreatora dodawania funkcji w Menedżerze serwerów. Aby włączyć program Microsoft .NET Framework 3.5, należy użyć apletu Włącz lub wyłącz funkcje systemu Windows. + + + + Zarządzanie prawami cyfrowymi w usługach IIS + Beta + Włącza zarządzanie prawami cyfrowymi prezentacji w formacie Smooth Streaming. + + + Niezainstalowany program ASP.NET + + + + + + + + + Na tym komputerze wykryto funkcję Płynne przesyłanie strumieniowe w wersji beta. Nie można kontynuować instalacji produktu [ProductName]. Aby zainstalować ten produkt, usuń funkcję Płynne przesyłanie strumieniowe w wersji beta, używając apletu Dodaj/Usuń programy w Panelu sterowania. + Na tym komputerze znajduje się niezgodna wersja usług IIS Media Services. Nie można kontynuować instalacji produktu [ProductName]. Aby zainstalować ten produkt, usuń usługi IIS Media Services, używając apletu Dodaj/Usuń programy w Panelu sterowania. + Nowsza wersja tego produktu jest już zainstalowana lub dostępna do zainstalowania na tym komputerze. Nie można kontynuować instalacji produktu [ProductName]. Aby zainstalować nowszą wersję tego produktu, używaj apletu Dodaj/Usuń programy w Panelu sterowania w celu zaktualizowania usług IIS Media Services. + Wymagana konwersja pliku listy odtwarzania + + + + + Odnaleziono starsze pliki usług IIS Media Services + + + + + Odnaleziono pliki usług IIS Media Services w wersji beta + + + + + + IIS Media Pack 1.0 + Aktualizacja pakietu IIS Media Pack 1.0 + IIS Media Services 2.0 + Aktualizacja usług IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Aktualizacja usług IIS Media Services 3.0 + Funkcje i narzędzia usług IIS Media Services. + Funkcje i narzędzia usług IIS Media Services 5 Premium. + Usługi IIS Media 4.0 w wersji beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 w wersji beta 1 + IIS Media Services 5 Premium + + Listy odtwarzania w sieci Web + Steruje odtwarzaniem przez klienta zasobów multimedialnych wymienionych na listach odtwarzania. + Pomocnik sesji + Umożliwia utrwalanie stanu sesji programu ASP.NET. (Wymaga usługi roli programu ASP.NET dla serwera sieci Web [IIS]). + Interfejs użytkownika + Konfiguruje funkcję Listy odtwarzania w sieci Web w Menedżerze usług IIS. + + Ograniczanie szybkości transmisji bitów + Oszczędza przepustowość, ograniczając dostarczanie plików pobieranych przez klientów. + Interfejs użytkownika + Konfiguruje funkcję Ograniczanie szybkości transmisji bitów w Menedżerze usług IIS. + + Zasoby + Włącza adaptacyjne przesyłanie strumieniowe zasobów na żądanie przez protokół HTTP do klientów. + Interfejs użytkownika + Konfiguruje funkcję Płynne przesyłanie strumieniowe w Menedżerze usług IIS. + + Kanały + Włącza adaptacyjne przesyłanie strumieniowe emisji kanałów przez protokół HTTP do klientów. + Interfejs użytkownika + Konfiguruje funkcję Płynne przesyłanie strumieniowe na żywo w Menedżerze usług IIS. + + Zarządzanie prawami cyfrowymi + Realizuje szyfrowanie i licencjonowanie plików multimedialnych w formacie Smooth Streaming. + Interfejs użytkownika + Konfiguruje funkcję zarządzania prawami cyfrowymi w module Menedżer usług IIS. + + Produkt [ProductName] wymaga systemu Microsoft Windows Vista z dodatkiem Service Pack 1 lub nowszym. + Produktu [ProductName] nie można zainstalować w systemie Vista Home Basic. + Produkt [ProductName] wymaga systemu Microsoft Windows 7 z dodatkiem Service Pack 1 lub nowszym. + + + Menedżer baz danych usług IIS + Menedżer baz danych usług IIS + + + Usługa zarządzania siecią Web firmy Microsoft 2 + Usługa zarządzania siecią Web firmy Microsoft + Instaluje podstawowe funkcje produktu [ProductName]. + Usługa zarządzania siecią Web firmy Microsoft 2 + Usługa zarządzania siecią Web zawiera mechanizmy zarządzania zdalnego i delegowanego, dzięki którym administratorzy mogą skutecznie zarządzać serwerem sieci Web, witrynami i aplikacjami obecnymi na komputerze. + + + Moduł ponownego zapisywania adresów URL firmy Microsoft w wersji 1.1 dla usług IIS 7 + Aktualizacja Modułu ponownego zapisywania adresów URL firmy Microsoft w wersji 1.1 dla usług IIS 7 + Ponowne zapisywanie adresów URL + Włącza funkcje ponownego zapisywania adresów URL i zawartości w usługach IIS 7. + Interfejs użytkownika + Konfiguruje funkcję Moduł ponownego zapisywania adresów URL w Menedżerze usług IIS. + + + Moduł ponownego zapisywania adresów URL usług IIS w wersji 2 + Aktualizacja modułu ponownego zapisywania adresów URL usług IIS w wersji 2 + Ponowne zapisywanie adresów URL + Włącza funkcje ponownego zapisywania adresów URL i zawartości w usługach IIS 7. + Interfejs użytkownika + Konfiguruje funkcję Moduł ponownego zapisywania adresów URL w Menedżerze usług IIS. + + + Pakiet administracyjny dla usług IIS 7.0 + Instaluje podstawowe funkcje produktu [ProductName]. + 1252 + Pakiet administracyjny dla usług IIS 7.0 + Microsoft Corporation + Ta wersja systemu operacyjnego jest nieobsługiwana. Produkt [ProductName] można zainstalować tylko w systemie Windows Server 2008 lub Windows Vista z dodatkiem Service Pack 1 lub nowszym. + Funkcje programu ASP.NET + Program ASP.NET zawiera funkcje Autoryzacja i Strony błędów, które umożliwiają zarządzanie ustawieniami autoryzacji i błędów niestandardowych. + Uwierzytelnianie + Opis funkcji Uwierzytelnianie programu ASP.NET. + Autoryzacja + Funkcja Autoryzacja programu ASP.NET umożliwia konfigurowanie reguł dotyczących autoryzacji użytkowników uzyskujących dostęp do witryn i aplikacji sieci Web. + Strony błędów + Funkcja Strony błędów programu ASP.NET umożliwia konfigurowanie odpowiedzi na błędy protokołu HTTP, które będą zwracane w przypadku wystąpienia błędów. + Moduły + Opis funkcji Moduły programu ASP.NET. + Obsługa + Opis funkcji Obsługa programu ASP.NET. + Edytor konfiguracji + Edytor konfiguracji służy do zarządzania plikami konfiguracji w Menedżerze usług IIS, umożliwiając edytowanie sekcji, atrybutów, elementów i kolekcji w plikach konfiguracji. + Filtrowanie żądań + Filtrowanie żądań umożliwia konfigurowania reguł filtrowania dla witryny sieci Web oraz ograniczanie zachowania protokołu i zawartości. + FastCGI + Funkcja FastCGI umożliwia konfigurowanie ustawień puli procesów dla aplikacji FastCGI na serwerze sieci Web. + + + Dynamiczne ograniczenia adresów IP dla Instalatora usług IIS 7 + + + + + + + + + + + + + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Beta + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Beta 2 + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Beta 3 + + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Release Candidate + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Release Candidate 2 + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Release Candidate 3 + + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja RTW + + Dynamiczne ograniczenia adresów IP dla usług IIS 7 + Interfejs użytkownika funkcji Dynamiczne ograniczenia adresów IP dla usług IIS 7 + + Dynamiczne ograniczenia adresu IP w usługach IIS 7 — na komputerze znaleziono wersję beta. Odinstaluj ją i spróbuj ponownie + + + WebDAV 7.5 dla usług IIS 7.0 + Aby można było używać tego produktu, muszą być zainstalowane funkcje CoreWebEngine i W3SVC usług IIS 7.0. + Moduł serwera WebDAV + Interfejs użytkownika administracji funkcją WebDAV + + + Zestaw narzędzi do optymalizacji aparatu wyszukiwania usług IIS w wersji 1.0 + Zestaw narzędzi do optymalizacji aparatu wyszukiwania usług IIS w wersji 1.0 + Zestaw narzędzi do optymalizacji aparatu wyszukiwania (SEO) w wersji 1.0 + Ta baza danych instalatora zawiera logikę i dane wymagane do zainstalowania narzędzia do optymalizacji aparatu wyszukiwania usług IIS w wersji 1.0. + + + Edytor usług IIS + + + Raporty usług IIS + Analizator dzienników nie jest zainstalowany na tym komputerze; zainstaluj funkcję Analizator dzienników w wersji 2.2 spod adresu http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, a następnie kontynuuj instalowanie funkcji Raporty usług IIS. + + + Nie można odnaleźć wstępnie wymaganych pakietów. Uruchom plik setup.exe, aby rozpoznać zależności i zainstalować ten program. + Program Microsoft SQL Server 2008 Management Objects jest wstępnie wymaganym składnikiem instalacji Menedżera baz danych usług IIS. Program Microsoft SQL Server 2008 Management Objects można zainstalować spod adresu http://go.microsoft.com/fwlink/?LinkID=150946. + Program Microsoft SQL Server System CLR Types jest wstępnie wymaganym składnikiem instalacji Menedżera baz danych usług IIS. Program Microsoft SQL Server System CLR Types można zainstalować spod adresu http://go.microsoft.com/fwlink/?LinkID=150946. + + + Microsoft Web Farm Framework + Zewnętrzna pamięć podręczna firmy Microsoft + Struktura farmy sieci Web jest wymaganym składnikiem instalacji funkcji Routing żądań aplikacji. Zainstaluj strukturę farmy sieci Web. + Routing żądań aplikacji firmy Microsoft 2.5 + Wersja wykonawcza + Dodaje funkcje routingu żądań aplikacji do usług IIS. + Interfejs użytkownika + Konfiguruje funkcję routingu żądań aplikacji w module Menedżer usług IIS. + + + Przystawka środowiska Microsoft Windows PowerShell dla usług IIS 7.0 + + + Instalator platformy Microsoft Web 4.0 + Instalator platformy sieci Web firmy Microsoft + Produkt [ProductName] wymaga systemu Windows XP z dodatkiem SP2, Windows 2003 z dodatkiem SP1, Windows Vista lub nowszego. + Program [ProductName] wymaga systemu Windows XP z dodatkiem Service Pack 3, Windows Server 2003 z dodatkiem Service Pack 2 lub nowszego. + + + Instalator usług Microsoft Windows Azure + Instalator usług Microsoft Windows Azure + + + Menedżer internetowych usług informacyjnych (IIS) 7+ + Klient Menedżera usług IIS + Obsługa operacji zdalnych + Ten produkt wymaga systemu Windows XP z dodatkiem SP2, Windows 2003 z dodatkiem SP1, Windows Vista z dodatkiem SP1, Windows 7 lub nowszego + Konsola zarządzania usługami IIS nie jest zainstalowana, ale jest wymagana do zarządzania zdalnymi serwerami usług IIS. Zainstaluj Konsolę zarządzania usługami IIS przed zainstalowaniem obsługi operacji zdalnych, klikając polecenia Panel sterowania -> Programy -> Włącz lub wyłącz funkcje systemu Windows i wybierając opcję Konsola zarządzania usługami IIS w funkcji Internetowe usługi informacyjne. + Ten produkt nie jest wymagany w systemach Windows Server 2008 i Windows Server 2008 R2 ani w nowszych. Zainstaluj Konsolę zarządzania usługami IIS, otwierając Menedżera serwera i wybierając pozycję Konsola zarządzania usługami IIS z usług roli dla roli Serwer sieci Web. + + + Publikowanie Menedżera usług IIS dla usług IIS 7.0 + Interfejs użytkownika funkcji Publikowanie + + + Zwiększanie gotowości aplikacji w wersji 1.0 dla usług IIS 7.5 + + + + Na tym komputerze znajduje się niezgodny produkt: [CONFLICTING_PRODUCT_NAME]. Nie można kontynuować instalowania produktu [ProductName]. Aby zainstalować ten produkt, usuń produkt [CONFLICTING_PRODUCT_NAME] za pomocą apletu Dodaj/Usuń programy w Panelu sterowania. + Do zainstalowania produktu [ProductName] jest wymagane uprawnienie administratora. + Do używania produktu [ProductName] są wymagane usługi IIS w wersji 7.0. + Do używania produktu [ProductName] są wymagane usługi IIS w wersji 7.0 lub nowsze. + Do używania produktu [ProductName] są wymagane usługi IIS w wersji 7.5 lub nowsze. + Do zainstalowania produktu [ProductName] wymagany jest program IIS 7 lub 7.5. + Odnaleziono wersję beta produktu [ProductName] na tym komputerze. + Odnaleziono nowszą wersję produktu [ProductName] na tym komputerze. + Instalator nie może kontynuować, ponieważ na tym komputerze jest już zainstalowane inne wystąpienie produktu [ProductName]. Odinstaluj je, a następnie ponownie rozpocznij tę instalację. + Aby można było używać produktu [ProductName], muszą być zainstalowane funkcje CoreWebEngine i W3SVC usług IIS 7.0. + Aby można było używać produktu [ProductName], musi być zainstalowana Konsola zarządzania usługami IIS. + Przed zainstalowaniem produktu [ProductName] zatrzymaj usługę aktywacji procesów systemu Windows (WAS) i usługę zarządzania siecią Web (WMSvc). Te usługi trzeba będzie uruchomić po zainstalowaniu produktu [ProductName]. + Do zainstalowania produktu [ProductName] jest wymagana metabaza usług IIS. + Nie można zainstalować 64-bitowej wersji produktu [ProductName] w 32-bitowej wersji systemu Microsoft Windows. + Nie można zainstalować 32-bitowej wersji produktu [ProductName] w 64-bitowej wersji systemu Microsoft Windows. + Do zainstalowania produktu [ProductName] jest wymagany program .NET Framework w wersji 2.0 lub nowszy. + Do zainstalowania programu [ProductName] jest potrzebny program Microsoft .NET Framework w wersji 3.5 lub nowszej. Naciśnij przycisk „Dodaj funkcje” w sekcji Menedżer serwera, aby zainstalować program Microsoft .Net w wersji 3.5. + Do zainstalowania programu [ProductName] jest wymagany program Microsoft .NET Framework w wersji 4.0 lub nowszej. + Przed zainstalowaniem produktu [ProductName] zainstaluj dodatek Service Pack 1 (lub nowszy) dla programu Microsoft .NET Framework w wersji 2.0. + Nie można wyłączyć usługi Windows Update (wuauserv), ponieważ jest ona wymagana do zainstalowania produktu [ProductName]. + Przystawka PowerShell stanowi część systemu operacyjnego Windows. Zainstaluj ją za pomocą menu Programy i funkcje lub narzędzia Menedżer serwera. + Do zainstalowania programu [ProductName] jest wymagany instalator platformy sieci Web firmy Microsoft w wersji 3.0 lub nowszej. + + Instalator nie może wykryć konfiguracji udostępnionej. + Konfiguracja udostępniona jest włączona dla usług IIS. Instalowanie produktu [ProductName] jest nieobsługiwane, gdy jest używana konfiguracja udostępniona. Wyłącz konfigurację udostępnioną przed zainstalowaniem tej funkcji. + + Zatrzymaj usługę publikowania w sieci World Wide Web (W3SVC) przed zainstalowaniem produktu [ProductName]. Tę usługę trzeba będzie uruchomić po instalacji. + Konsola zarządzania środowiskiem IIS PowerShell + Przystawka IIS PowerShell + Przystawka IIS PowerShell wymaga zainstalowanego środowiska PowerShell w wersji 1.0 lub 2.0. + Przystawka IIS PowerShell wymaga zainstalowanej usługi WAS oraz konfiguracji. + To jest nieprawdziwy ciąg. + + + Microsoft Web Farm Framework 2.2 + Microsoft Web Farm Agent 2.2 + Usługa kolektywu serwerów sieci Web + Usługa kolektywu serwerów sieci Web + Usługa kontrolera kolektywu serwerów sieci Web + Usługa kontrolera kolektywu serwerów sieci Web + Usługa agenta kolektywu serwerów sieci Web + Usługa agenta kolektywu serwerów sieci Web + Do zainstalowania składnika Web Farm Framework jest wymagany instalator platformy sieci Web. Zainstaluj instalatora platformy sieci Web ze strony http://www.microsoft.com/web/downloads/platform.aspx. + Do zainstalowania składnika Web Farm Framework jest wymagane narzędzie Web Deployment. Zainstaluj narzędzie Web Deployment ze strony http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Role i funkcje obsługi hostingu sieci Web. + Hosting Framework + Składnik Hosting Framework udostępnia interfejsy API i polecenia programu PowerShell do zarządzania hostingiem sieci Web. + Rola sieci Web + Rola sieci Web instaluje usługę Dynamiczna usługa WAS i dostawcę Moduł ponownego zapisywania adresów URL na potrzeby hostingu sieci Web. + Antares Express + Wdraża konfigurację Panelu sterowania zoptymalizowaną pod kątem konfiguracji jednego komputera. + Rola Usługa równoważenia obciążenia + Rola Usługa równoważenia obciążenia konfiguruje router żądań aplikacji do routingu na podstawie reguł hostingu sieci Web. + Kontroler hostingu + Kontroler hostingu rozszerza funkcje składnika Web Farm Framework 2.0 o współdziałanie z hostingiem sieci Web. + Rola publikowania + Instaluje obsługę narzędzia Web Deploy i publikowana FTP. + To jest przystawka PowerShell zawierająca aplety poleceń służące do zarządzania infrastrukturą Microsoft Web Hosting. + Dynamiczna usługa WAS + Usługa aktywacji procesów systemu Windows zoptymalizowana pod kątem hostingu sieci Web o dużej gęstości. + Usługa pomiaru użycia zasobów + Instaluje usługę pomiaru użycia zasobów, która umożliwia gromadzenie i publikowanie informacji na temat środowiska wykonawczego i kondycji. + Miernik zasobów + Umożliwia gromadzenie i publikowanie informacji na temat środowiska wykonawczego i kondycji pochodzących z roli sieci Web. + Wymuszanie przydziału hostingu + Monitoruje użycie zasobów witryn sieci Web i w razie przekroczenia przydziału użycia wykonuje akcje niestandardowe. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PTB/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PTB/misc/setupstrings.wxl new file mode 100644 index 0000000000..4fdfeffca5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PTB/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1046 + + + + Opções de Instalação da Configuração Compartilhada + Selecionar a opção de instalação na configuração compartilhada do IIS + Atualizar configuração compartilhada na instalação + Você está instalando este módulo em um servidor do IIS que usa a configuração compartilhada. Se outros servidores do IIS estiverem usando essa configuração compartilhada, você precisará instalar este módulo em todos os computadores. Para minimizar interrupções de servidores Web individuais, será preciso instalar este módulo de acordo com as seguintes etapas: primeiro, em todos os computadores, com exceção do último, você deverá instalar o módulo sem atualizar a configuração compartilhada. Para isso, não marque a caixa de seleção + a seguir. Isso instalará todos os binários e arquivos necessários para o módulo em cada computador sem fazer alterações na configuração compartilhada. Em segundo lugar, no último computador, será preciso verificar se a identidade do usuário usada por você na execução tem acesso de leitura e gravação ao arquivo applicationhost.config no compartilhamento UNC. Em seguida, instale o módulo e selecione a opção abaixo de atualização da configuração compartilhada. + + + Inicializando a ação personalizada do WebConfig + Atualizando o web.config + + + + Registro em Log Avançado do IIS + Habilita o registro em log avançado dos dados de pipeline do IIS. + Registro em Log Avançado do IIS + Habilita a criação de arquivos de log personalizados com seleção de campo extensível. + Atualização para o Registro em Log Avançado do IIS + + + + IIS Transform Manager + Beta + Habilita o IIS Media Services do Transform Manager. + IIS Transform Manager + Habilita a criação de transformações de mídia. + Host do IIS Transform Manager + Host de serviço de [ProductName]. + IIS Transform Manager + Conversão em lote de arquivos de mídia por demanda para formatos de arquivo e de contêiner alternativos. + Um pacote de Tarefa do Expression Encoder SP do IIS Transform Manager 1.0 está instalado no computador. Desinstale-o para que possa instalar o [ProductName]. + + O Microsoft .NET Framework 3.5 é exigido para instalar o produto [ProductName]. Use o "Assistente Adicionar Recursos" no Gerenciador do Servidor para instalar os Recursos do .NET Framework 3.5.1 ou use a opção "Ativar ou desativar os recursos do Windows" para ativar o Microsoft .NET Framework 3.5. + + + + Gerenciamento de Direitos Digitais do IIS + Beta + Habilita o Gerenciamento de Direitos Digitais de apresentações de Smooth Streaming. + + + O ASP.NET Não Está Instalado + + + + + + + + + O IIS Smooth Streaming - Beta foi encontrado no computador. Não é possível continuar a instalação do [ProductName]. Para instalar o produto, use Adicionar/Remover Programas no Painel de Controle para remover o IIS Smooth Streaming - Beta. + Uma versão incompatível do IIS Media Services está no computador. Não é possível continuar a instalação do [ProductName]. Para instalar o produto, use Adicionar/Remover Programas no Painel de Controle para remover o IIS Media Services. + Uma versão mais recente do produto já está instalada ou disponível para instalação neste computador. Não é possível continuar a instalação do [ProductName]. Para instalar a versão mais recente do produto, use Adicionar/Remover Programas no Painel de Controle para atualizar o IIS Media Services. + Conversão do Arquivo da Lista de Reprodução Necessária + + + + + Arquivos Antigos do IIS Media Services Encontrados + + + + + Arquivos do IIS Media Services Beta Encontrados + + + + + + IIS Media Pack 1.0 + Atualização para o IIS Media Pack 1.0 + IIS Media Services 2.0 + Atualização para o IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Atualização para o IIS Media Services 3.0 + Recursos e ferramentas do IIS Media Services. + Recursos e ferramentas do IIS Media Services 5 Premium. + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web Playlists + Controla a reprodução no cliente de ativos de mídia referenciados em listas de reprodução. + Auxiliar de Sessão + Habilita a persistência do estado de sessão do ASP.NET. (Requer o serviço de função do ASP.NET para o Servidor Web (IIS)). + Interface do Usuário + Configura o recurso Web Playlists no Gerenciador do IIS. + + Limitação da Taxa de Bits + Economiza largura de banda limitando a entrega de arquivos baixados por clientes. + Interface do Usuário + Configura o recurso Limitação da Taxa de Bits no Gerenciador do IIS. + + Ativos + Habilita o streaming HTTP adaptável de ativos por demanda para clientes. + Interface do Usuário + Configura o recurso Smooth Streaming no Gerenciador do IIS. + + Canais + Habilita o streaming HTTP adaptável de difusões de canais para clientes. + Interface do Usuário + Configura o recurso Live Smooth Streaming no Gerenciador do IIS. + + Gerenciamento de Direitos Digitais + Fornece criptografia e licenciamento de mídia Smooth Streaming. + Interface do Usuário + Configura o recurso de Gerenciamento de Direitos Digitais no Gerenciador do IIS. + + O [ProductName] requer o Microsoft Windows Vista Service Pack 1 ou posterior. + Não é possível instalar o [ProductName] no Vista Home Basic. + O [ProductName] requer o Microsoft Windows 7 Service Pack 1 ou posterior. + + + Gerenciador de Banco de Dados do IIS + Gerenciador de Banco de Dados do IIS + + + Serviço de Gerenciamento da Web 2 da Microsoft + Serviço de Gerenciamento da Web da Microsoft + Instala os recursos básicos do [ProductName]. + Serviço de Gerenciamento da Web 2 da Microsoft + O Serviço de Gerenciamento da Web habilita recursos de gerenciamento remotos e delegados para que os administradores gerenciem o servidor Web, os sites e os aplicativos presentes neste computador. + + + Módulo 1.1 de Reescrita de URL da Microsoft para IIS 7 + Atualização do Módulo 1.1 de Reescrita de URL para IIS 7 + Reescrita de URL + Habilita os recursos de reescrita de conteúdo e URL do IIS 7. + Interface do Usuário + Configura o recurso do Módulo de Reescrita de URL no Gerenciador do IIS. + + + Módulo 2 de Reescrita de URL do IIS + Atualização do Módulo 2 de Reescrita de URL do IIS + Reescrita de URL + Habilita os recursos de reescrita de conteúdo e URL do IIS 7. + Interface do Usuário + Configura o recurso do Módulo de Reescrita de URL no Gerenciador do IIS. + + + Administration Pack para IIS 7.0 + Instala os recursos básicos do [ProductName]. + 1252 + Administration Pack para IIS 7.0 + Microsoft Corporation + Não há suporte a esta versão do sistema operacional. Só é possível instalar o [ProductName] no Windows Server 2008 ou no Windows Vista Service Pack 1 ou posterior. + Recursos do ASP.Net + O ASP.NET inclui os recursos Páginas de Erro e Autorização, que permitem o gerenciamento das configurações de erro personalizadas e de autorizações. + Autenticação + Descrição da Autenticação do ASP.Net. + Autorização + A Autorização do ASP.NET permite a configuração de regras para autorizar usuários a acessar seus sites e aplicativos. + Páginas de Erro + As Páginas de Erro do ASP.NET permitem a configuração de respostas de erro de HTTP retornadas quando um erro ocorre. + Módulos + Descrição dos Módulos do ASP.Net. + Manipuladores + Descrição dos Manipuladores do ASP.Net. + Editor de Configurações + O Editor de Configurações permite o gerenciamento de arquivos de configuração no Gerenciador do IIS por meio da edição de seções, atributos, elementos e coleções nos arquivos de configuração. + Filtragem de Solicitações + A Filtragem de Solicitações permite a configuração de regras de filtragem para o seu site, protocolo restrito e comportamento de conteúdo. + FastCGI + O FastCGI permite a definição de configurações do pool de processos para os aplicativos FastCGI no servidor Web. + + + Instalação de Restrições de IP Dinâmico para IIS 7 + + + + + + + + + + + + + Restrições de IP Dinâmico para IIS 7 - Beta + Restrições de IP Dinâmico para IIS 7 - Beta 2 + Restrições de IP Dinâmico para IIS 7 - Beta 3 + + Restrições de IP Dinâmico para IIS 7 - Versão Release Candidate + Restrições de IP Dinâmico para IIS 7 - Versão Release Candidate 2 + Restrições de IP Dinâmico para IIS 7 - Versão Release Candidate 3 + + Restrições de IP Dinâmico para IIS 7 - RTW + + Restrições de IP Dinâmico para IIS 7 + Interface do Usuário de Restrições de IP Dinâmico para IIS 7 + + Restrições de IP Dinâmico para IIS 7 - Beta encontradas neste computador. Desinstale-as e tente novamente + + + WebDAV 7.5 para IIS 7.0 + Os recursos CoreWebEngine e W3SVC do IIS 7.0 devem ser instalados para usar este produto. + Módulo do Servidor WebDAV + Interface do Usuário de Administração do WebDAV + + + Toolkit de Otimização do Mecanismo de Pesquisa do IIS 1.0 + Toolkit de Otimização do Mecanismo de Pesquisa do IIS 1.0 + Toolkit de SEO (Otimização do Mecanismo de Pesquisa) 1.0 + Este banco de dados de instalador contém a lógica e os dados necessários para instalar o Kit de Ferramentas de Otimização do Mecanismo de Pesquisa do IIS 1.0. + + + Editor do IIS + + + Relatórios do IIS + O Analisador de Log não foi instalado neste computador. Instale o Analisador de Log 2.2 de http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 e continue a instalação dos Relatórios do IIS + + + Os pacotes de pré-requisito não foram encontrados. Execute setup.exe para resolver as dependências e instalar o programa. + O Microsoft SQL Server 2008 Management Objects é um pré-requisito para a instalação do Gerenciador de Banco de Dados do IIS. É possível instalar o Microsoft SQL Server 2008 Management Objects de http://go.microsoft.com/fwlink/?LinkID=150946. + Os Microsoft SQL Server System CLR Types são um pré-requisito para a instalação do Gerenciador de Banco de Dados do IIS. É possível instalar os Microsoft SQL Server System CLR Types de http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + O Web Farm Framework é um requisito para a instalação do Application Request Routing. Instale o Web Farm Framework. + Microsoft Application Request Routing 2.5 + Tempo de Execução + Adiciona os recursos de Roteamento de Solicitações de Aplicativo no IIS. + Interface do Usuário + Configura o recurso de Roteamento de Solicitações de Aplicativo no Gerenciador do IIS. + + + Snap-in do Microsoft Windows PowerShell para o IIS 7.0 + + + Microsoft Web Platform Installer 4.0 + Microsoft Web Platform Installer + O [ProductName] requer o Windows XP SP2, o Windows 2003 SP1, o Windows Vista ou posterior. + O [ProductName] exige o Windows XP Service Pack 3, o Windows Server 2003 Service Pack 2 ou versão posterior. + + + Instalador de Serviços do Microsoft Windows Azure + Instalador de Serviços do Microsoft Windows Azure + + + Gerenciador do IIS (Serviços de Informações da Internet) 7+ + Cliente do Gerenciador do IIS + Suporte Remoto + Este produto requer o Windows XP SP2, o Windows 2003 SP1, o Windows Vista SP1, o Windows 7 ou mais recente + O Console de Gerenciamento do IIS não foi instalado, mas é necessário para o gerenciamento de servidores remotos do IIS. Para instalar o Console de Gerenciamento do IIS antes de instalar o suporte de gerenciamento remoto, abra o 'Painel de Controle->Programas->Ativar ou Desativar Recursos do Windows' e selecione o Console de Gerenciamento do IIS no recurso Serviços de Informações da Internet. + Este produto não é necessário no Windows Server 2008 ou no Windows Server 2008 R2 ou mais recente. Para instalar o Console de Gerenciamento do IIS, abra o Gerenciador do Servidor e selecione o Console de Gerenciamento do IIS em Serviços de Função para a Função de Servidor Web. + + + IIS Manager Publishing para IIS 7.0 + Interface do Usuário de Publicação + + + Application Warm-Up 1.0 para IIS 7.5 + + + + Este computador contém um produto incompatível, [CONFLICTING_PRODUCT_NAME]. A instalação do [ProductName] não pode continuar. Para instalar esse produto, use Adicionar/Remover Programas no Painel de Controle para remover o [CONFLICTING_PRODUCT_NAME]. + São necessários privilégios de Administrador para instalar o [ProductName]. + É necessário o IIS Versão 7.0 para usar o [ProductName]. + É necessário o IIS Versão 7.0 ou posterior para instalar o [ProductName]. + É necessário o IIS Versão 7.5 ou posterior para instalar o [ProductName]. + É necessário o IIS versão 7 ou 7.5 para instalar o [ProductName]. + A versão beta do [ProductName] foi encontrada no computador. + Uma versão mais recente do [ProductName] foi encontrada no computador. + Não é possível continuar a instalação, pois outra instância do [ProductName] já está instalada no computador. Desinstale a versão antiga e reinicie a instalação. + Os recursos CoreWebEngine e W3SVC do IIS 7.0 devem estar instalados para usar o [ProductName]. + O Console de Gerenciamento do IIS deve estar instalado para usar o [ProductName]. + Interrompa o WAS (Serviço de Ativação de Processos do Windows) e o WMSvc (Serviço de Gerenciamento da Web) antes de instalar o [ProductName]. Será necessário instalar os serviços após a instalação do [ProductName]. + É necessária a Metabase do IIS para instalar o [ProductName]. + Não é possível instalar a versão de 64 bits do [ProductName] em uma edição de 32 bits do Microsoft Windows. + Não é possível instalar a versão de 32 bits do [ProductName] em uma edição de 64 bits do Microsoft Windows. + É necessário o Microsoft .NET Framework Versão 2.0 ou posterior para instalar o [ProductName]. + O Microsoft .NET Framework Versão 3.5 ou posterior é necessário para instalar o [ProductName]. Use 'Adicionar Recursos' no Gerenciador do Servidor para instalar o Microsoft .Net Versão 3.5. + O Microsoft .NET Framework Versão 4.0 ou posterior é necessário para instalar o [ProductName]. + Instale o Microsoft .NET Framework Service Pack 1 Versão 2.0, ou um service pack posterior, antes de instalar o [ProductName]. + Não é possível desabilitar o serviço Windows Update (wuauserv), pois ele é necessário para instalar o [ProductName]. + O snap-in do PowerShell é parte o Sistema Operacional Windows. Instale o snap-in por meio dos 'Programas e Recursos' ou 'Gerenciador do Servidor'. + O Microsoft Web Platform Installer Versão 3.0 ou posterior é necessário para instalar o [ProductName]. + + A instalação não detectou configurações compartilhadas. + A configuração compartilhada está habilitada para o IIS. Não há suporte à instalação do [ProductName] quando é usada uma configuração compartilhada. Desabilite a configuração compartilhada antes de instalar este recurso. + + Interrompa o Serviço de Publicação na World Wide Web (W3SVC) antes de instalar o [ProductName]. Será necessário iniciar o serviço após a instalação. + Console de Gerenciamento do PowerShell do IIS + Snap-in do PowerShell do IIS + O snap-in do PowerShell do IIS requer o PowerShell versão 1.0 ou 2.0 instalado + O snap-in do PowerShell do IIS requer WAS e configuração instalados + Cadeia de caracteres inválida. + + + Estrutura do Microsoft Web Farm Versão 2.2 + Agente do Microsoft Web Farm Versão 2.2 + Serviço de Web Farm + Serviço de Web Farm + Serviço Controlador de Web Farm + Serviço Controlador de Web Farm + Serviço de Agente de Web Farm + Serviço de Agente de Web Farm + O Web Plaform Installer é um pré-requisito para instalar a Estrutura do Web Farm. Instale o Web Plaform Installer a partir de http://www.microsoft.com/web/downloads/platform.aspx. + A Ferramenta de Implantação da Web é um pré-requisito para instalar a Estrutura do Web Farm. Instale a Ferramenta de Implantação da Web a partir de http://www.iis.net/download/WebDeploy. + + + Estrutura de Hospedagem na Web da Microsoft + Estrutura de Hospedagem na Web + Funções e recursos de Hospedagem na Web. + Estrutura de Hospedagem + A Estrutura de Hospedagem oferece comandos de API e PowerShell para gerenciamento de Hospedagem na Web. + Função da Web + A Função Web instala o serviço WAS Dinâmico e o provedor de Reescrita de URL de Hospedagem na Web. + Antares Express + Implanta uma configuração do Painel de Controle otimizada para configuração de máquina única. + Função do Balanceador de Carga + A Função do Balanceador de Carga configura o Roteador de Solicitação de Aplicativo para rotear com base nas regras de Hospedagem na Web. + Controlador de Hospedagem + O Controlador de Hospedagem estende a Estrutura do Web Farm 2.0 para trabalhar com Hospedagem na Web. + Função de Publicação + Instala suporte para Implantação da Web e publicação em FTP. + Este é um snap-in do PowerShellque contém cmdlets para gerenciar a infraestrutura de Hospedagem na Web da Microsoft. + Serviço WAS Dinâmico + Serviço de Ativação de Processos do Windows otimizado para Hospedagem na Web de alta densidade. + Serviço de Medição de Recursos + Instala o serviço de Medição de Recursos que habilita a coleta e a publicação de informações de integridade e tempo de execução. + Medição de Recursos + Habilita a coleta e a publicação de informações de tempo de execução e integridade a partir da Função Web. + Imposição de Cota de Hospedagem + Monitora o uso de recursos de sites e executa ações personalizadas quando a cota de uso é excedida. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/RUS/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/RUS/misc/setupstrings.wxl new file mode 100644 index 0000000000..e9613c04ec --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/RUS/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1049 + + + + Параметры установки общей конфигурации + Выбор параметров установки общей конфигурации IIS + Обновить общую конфигурацию при установке + Вы устанавливаете этот модуль на сервер IIS, использующий общую конфигурацию. Если дополнительные серверы IIS используют эту общую конфигурацию, вам необходимо установить этот модуль на все эти компьютеры. Чтобы минимизировать нарушение работы отдельных веб-серверов, вам потребуется устанавливать этот модуль в соответствии с шагами, описанными ниже. Сначала следует установить модуль на все компьютеры, кроме последнего, не обновляя при этом общую конфигурацию. Для этого не устанавливайте флажок ниже. +При этом на каждый компьютер будут установлены все файлы, необходимые для модуля, но не будет изменена общая конфигурация. Затем на последнем компьютере следует убедиться в том, что у используемой для работы учетной записи есть права чтения и записи файла applicationhost.config, расположенного на общем ресурсе UNC. Затем следует установить модуль и установить флажок "Обновить общую конфигурацию" ниже. + + + Инициализируется настраиваемое действие WebConfig + Обновляется файл web.config + + + + Расширенное ведение журнала IIS + Обеспечивает расширенные возможности ведения журнала данных конвейера IIS. + Расширенное ведение журнала IIS + Позволяет создавать настраиваемые файлы журналов с расширяемым набором полей. + Обновление для расширенного ведения журнала + + + + IIS Transform Manager + Бета-версия + Включает диспетчер Transform Manager IIS Media Services. + IIS Transform Manager + Включает создание преобразований мультимедиа. + Узел диспетчера IIS Transform Manager + Узел службы для [ProductName]. + IIS Transform Manager + Пакетное преобразование файлов мультимедиа в альтернативные форматы файлов и контейнеров по запросу. + На компьютере установлен пакет задач IIS Transform Manager 1.0 Expression Encoder SP. Его следует удалить перед установкой [ProductName]. + + Microsoft .NET Framework 3.5 требуется для установки [ProductName]. Используйте мастер добавления компонентов в диспетчере сервера, чтобы установить компоненты .NET Framework 3.5.1, или используйте параметр "Включение или отключение компонентов Windows", чтобы включить Microsoft .NET Framework 3.5. + + + + IIS: управление цифровыми правами + Бета-версия + Включает управление цифровыми правами для презентаций Smooth Streaming. + + + ASP.NET не установлен + + + + + + + + + На компьютере обнаружена бета-версия IIS Smooth Streaming. Установка [ProductName] не будет продолжена. Чтобы установить этот продукт, используйте компонент "Установка и удаление программ" панели управления для удаления бета-версии IIS Smooth Streaming. + На компьютере имеется несовместимая версия служб IIS Media Services. Установка [ProductName] не будет продолжена. Чтобы установить этот продукт, используйте компонент "Установка и удаление программ" панели управления для удаления служб IIS Media Services. + Более новая версия этого продукта уже установлена или доступна для установки на этом компьютере. Установка [ProductName] не будет продолжена. Чтобы установить более новую версию этой программы, используйте элемент панели управления "Установка и удаление программ" для обновления служб мультимедиа IIS. + Необходимо преобразовать файл списка воспроизведения + + + + + Обнаружены старые файлы служб IIS Media + + + + + Обнаружены старые файлы бета-версии служб IIS Media + + + + + + IIS Media Pack 1.0 + Обновление для IIS Media Pack 1.0 + IIS Media Services 2.0 + Обновление для IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Обновление для IIS Media Services 3.0 + Средства и компоненты IIS Media Services. + Средства и компоненты IIS Media Services 5 Premium. + Бета-версия 1 служб IIS Media Services 4.0 + Службы IIS Media Services 4.0 + Бета-версия 1 служб IIS Media Services 4.5 + IIS Media Services 5 Premium + + Веб-списки воспроизведения + Управляет воспроизведением клиентами данных мультимедиа, на которые есть ссылки в списках воспроизведения. + Модуль поддержки сеансов + Поддерживает сохранение сеансов ASP.NET. (Требуется служба роли ASP.NET ля веб-сервера (IIS)). + Пользовательский интерфейс + Настройка компонента веб-списков воспроизведения в диспетчере IIS. + + Регулирование скорости + Экономия полосы пропускания путем регулирования доставки файлов, загружаемых клиентами. + Пользовательский интерфейс + Настройка функции регулирования скорости в диспетчере IIS. + + Файлы + Поддерживает адаптивную потоковую передачу файлов по запросу клиентам. + Пользовательский интерфейс + Настройка Smooth Streaming в диспетчере IIS. + + Каналы + Поддерживает адаптивную потоковую передачу при канальной широковещательной трансляции клиентам. + Пользовательский интерфейс + Настраивает компонент Live Smooth Streaming в диспетчере IIS. + + Управление цифровыми правами + Обеспечивает шифрование и лицензирование содержимого Smooth Streaming. + Пользовательский интерфейс + Настройка функции управления цифровыми правами в диспетчере IIS. + + Для [ProductName] требуется Microsoft Windows Vista с пакетом обновления 1 (SP1) или более поздней версии. + Невозможно установить [ProductName] в операционной системе Vista Home Basic. + Для [ProductName] требуется Microsoft Windows 7 с пакетом обновления 1 (SP1) или более поздней версии. + + + Диспетчер баз данных IIS + Диспетчер баз данных IIS + + + Служба веб-управления 2 (Майкрософт) + Служба веб-управления (Майкрософт) + Установка основных компонентов [ProductName]. + Служба веб-управления 2 (Майкрософт) + Служба управления сетью предоставляет для администраторов удаленные и делегированные возможности управления веб-сервером, сайтами и приложениями, существующими на данном компьютере. + + + Модуль 1.1 видоизменения URL-адресов (Майкрософт) для IIS 7 + Обновление для модуля 1.1 видоизменения URL-адресов для IIS 7 + Видоизменение URL-адресов + Включает функции, отвечающие за видоизменение URL-адресов и содержимого в IIS 7. + Пользовательский интерфейс + Настраивает компонент "модуль видоизменения URL-адресов" в диспетчере служб IIS. + + + Модуль переопределения URL-адресов 2 для IIS + Обновление для модуля 2 переопределения URL-адресов для IIS + Видоизменение URL-адресов + Включает функции, отвечающие за видоизменение URL-адресов и содержимого в IIS 7. + Пользовательский интерфейс + Настраивает компонент "модуль видоизменения URL-адресов" в диспетчере служб IIS. + + + Пакет администрирования IIS 7.0 + Установка основных компонентов [ProductName]. + 1251 + Пакет администрирования IIS 7.0 + Корпорация Майкрософт + Эта версия операционной системы не поддерживается. [ProductName] можно установить только в Windows Server 2008 или Windows Vista с пакетом обновления 1 (SP1) или более поздних версий. + Компоненты ASP.Net + В ASP.NET содержатся компоненты авторизации и страниц ошибок, позволяющие управлять параметрами авторизации и настраиваемых сообщений об ошибках. + Проверка подлинности + Описание проверки подлинности ASP.Net. + Авторизация + Модуль проверки подлинности ASP.NET позволяет настраивать правила проверки подлинности пользователей для доступа к веб-сайтам и приложениям. + Страницы ошибок + Страницы ошибок ASP.NET позволяют настраивать отклики на ошибки HTTP, отображаемые при возникновении таких ошибок. + Модули + Описание модулей ASP.Net. + Обработчики + Описание обработчиков ASP.Net. + Редактор конфигураций + Редактор конфигурации позволяет управлять файлами конфигурации в диспетчере IIS, обеспечивая возможность изменять разделы, атрибуты, элементы и семейства в файлах конфигурации. + Фильтрация запросов + Фильтрация запросов позволяет настраивать правила фильтрации для веб-сайта, ограничивать поведение протоколов и содержимого. + Fast CGI + FastCGI позволяет настраивать параметры пула процессов для приложений FastCGI на веб-сервере. + + + Программа установки ограничения динамических IP-адресов для IIS 7 + + + + + + + + + + + + + Ограничения динамических IP-адресов для IIS 7 - бета-версия + Ограничения динамических IP-адресов для IIS 7 - бета-версия 2 + Ограничения динамических IP-адресов для IIS 7 - бета-версия 3 + + Ограничения динамических IP-адресов для IIS 7 - версия-кандидат + Ограничения динамических IP-адресов для IIS 7 - версия-кандидат 2 + Ограничения динамических IP-адресов для IIS 7 - версия-кандидат 3 + + Ограничения динамических IP-адресов для IIS 7 - рабочий выпуск + + Ограничения динамических IP-адресов для IIS 7 + Пользовательский интерфейс ограничения динамических IP-адресов для IIS 7 + + Ограничения динамического IP-адреса для IIS 7 - на компьютере обнаружена бета-версия. Удалите ее и повторите попытку + + + WebDAV 7.5 для IIS 7.0 + Для использования этого продукта необходимо установить компоненты IIS 7.0 CoreWebEngine и W3SVC. + Серверный модуль WebDAV + Пользовательский интерфейс администрирования WebDAV + + + Инструменты оптимизации IIS Search Engine 1.0 + Инструменты оптимизации IIS Search Engine 1.0 + Инструменты оптимизации Search Engine (SEO) 1.0 + Эта база данных установщика содержит логику и данные, необходимые для установки инструментов оптимизации IIS Search Engine 1.0. + + + Редактор IIS + + + Отчеты IIS + Программа Log Parser не установлена на этом компьютере. Установите программу Log Parser 2.2 с сайта http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, затем установите отчеты IIS. + + + Необходимые компоненты не найдены. Запустите setup.exe, чтобы установить необходимые зависимые компоненты и установить эту программу. + Управляющие объекты Microsoft SQL Server 2008 являются необходимым условием для установки диспетчера базы данных IIS. Управляющие объекты Micrsoft SQL Server 2008 можно установить на странице http://go.microsoft.com/fwlink/?LinkID=150946. + Системные типы Microsoft SQL Server System CLR Types являются необходимым условием для установки диспетчера базы данных IIS. Системные типы Microsoft SQL Server System CLR Types можно установить на странице http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + Для установки маршрутизации запросов приложений требуется установить платформу веб-фермы. Установите платформу веб-фермы. + Microsoft Application Request Routing 2.5 + Среда выполнения + Добавляет функции маршрутизации запросов приложений в IIS. + Пользовательский интерфейс + Настраивает функцию маршрутизации запросов приложений в диспетчере IIS. + + + Оснастка Microsoft Windows PowerShell для IIS 7.0 + + + Установщик веб-платформы Майкрософт 4.0 + Установщик веб-платформы Майкрософт + Для [ProductName] требуется Windows XP SP2, Windows 2003 SP1, Windows Vista или более поздняя версия. + Для [ProductName] требуется Windows XP с пакетом обновления 3, Windows Server 2003 с пакетом обновления 2, или более поздние версии. + + + Установщик служб Microsoft Windows Azure + Установщик служб Microsoft Windows Azure + + + Диспетчер служб IIS 7+ + Клиент диспетчера IIS + Поддержка удаленной работы + Для этого продукта требуется Windows XP с пакетом обновления 2 (SP2), Windows 2003 с пакетом обновления 1 (SP1), Windows Vista с пакетом обновления 1 (SP1), Windows 7 или более новая система + Консоль управления IIS не установлена, но она необходима для управления удаленными серверами IIS. Установите консоль управления IIS перед установкой поддержки удаленного управления. Для этого в панели управления откройте "Программы", "Включение или отключение компонентов Windows", и выберите консоль управления IIS среди компонентов IIS. + Этот продукт не требуется при использовании Windows Server 2008, Windows Server 2008 R2 и более новых систем. Установите консоль управления IIS, открыв диспетчер сервера и выбрав консоль управления IIS в службах ролей для роли веб-сервера. + + + Публикация диспетчера IIS 7.0 + Пользовательский интерфейс публикации + + + Application Warm-Up 1.0 для IIS 7.5 + + + + На компьютере установлен несовместимый продукт: [CONFLICTING_PRODUCT_NAME]. Установку [ProductName] продолжить невозможно. Чтобы установить этот продукт, удалите CONFLICTING_PRODUCT_NAME] в разделе "Добавление и удаление программ" в панели управления. + Для установки [ProductName] требуются права администратора. + Для использования [ProductName] требуется IIS версии 7.0. + Для установки [ProductName] требуется IIS версии 7.0 или более поздней. + Для установки [ProductName] требуется IIS версии 7.5 или более поздней. + Для установки [ProductName] требуется IIS версии 7 или 7.5. + На компьютере обнаружена бета-версия [ProductName]. + На компьютере обнаружена более поздняя версия [ProductName]. + Программа установки не может продолжить работу, поскольку на компьютере уже установлен другой экземпляр [ProductName]. Удалите его, затем заново запустите эту установку. + Для использования [ProductName] необходимо установить компоненты IIS 7.0 CoreWebEngine и W3SVC. + Для использования [ProductName] требуется установить консоль управления IIS. + Перед установкой [ProductName] остановите службу активации Windows (WAS) и службу веб-управления (WMSvc). Эти службы нужно будет запустить после установки [ProductName]. + Для установки [ProductName] требуется метабаза IIS. + 64-разрядную версию [ProductName] нельзя установить на 32-разрядный выпуск Microsoft Windows. + 32-разрядную версию [ProductName] нельзя установить на 64-разрядный выпуск Microsoft Windows. + Для установки [ProductName] требуется Microsoft .NET Framework версии 2.0 или более поздней. + Для установки [ProductName] требуется Microsoft .NET Framework версии 3.5 или более поздней. Воспользуйтесь функцией диспетчера сервера "Добавить функции", чтобы установить Microsoft .Net версии 3.5. + Для установки [ProductName] требуется Microsoft .NET Framework версии 4.0 или более поздней. + Перед установкой [ProductName] установите Microsoft .NET Framework версии 2.0 с пакетом обновления 1 (SP1)или более поздним. + Службу Windows Update (wuauserv) невозможно отключить, она необходима для установки [ProductName]. + Оснастка PowerShell является частью операционной системы Windows. Установите ее с помощью элемента панели управления "Программы и компоненты" или диспетчера сервера. + Для установки [ProductName] требуется установщик веб-платформы Майкрософт, версии 3.0 или более поздней. + + Программа установки не обнаружила общую конфигурацию. + Для IIS включена общая конфигурация. Установка [ProductName] не поддерживается при использовании общей конфигурации. Отключите общую конфигурацию перед установкой этого компонента. + + Перед установкой [ProductName] необходимо остановить службу веб-публикаций (W3SVC). Эту службу нужно будет включить после установки. + Консоль управления IIS PowerShell + Оснастка IIS PowerShell + Для оснастки IIS PowerShell требуется PowerShell v1.0 или v2.0 + Для оснастки IIS PowerShell требуется установить WAS и конфигурацию + Пустая строка. + + + Платформа веб-ферм Майкрософт 2.2 + Агент веб-ферм Майкрософт 2.2 + Служба Web Farm Service + Служба Web Farm Service + Служба Web Farm Controller Service + Служба Web Farm Controller Service + Служба Web Farm Agent Service + Служба Web Farm Agent Service + Установщик веб-платформы является необходимым компонентом для установки платформы веб-ферм. Установите установщик веб-платформы с сайта http://www.microsoft.com/web/downloads/platform.aspx. + Инструмент веб-развертывания является необходимым компонентом для установки платформы веб-ферм. Установите инструмент веб-развертывания с сайта http://www.iis.net/download/WebDeploy. + + + Платформа веб-размещения Майкрософт + Платформа веб-размещения + Роли и компоненты веб-размещения. + Платформа размещения + Платформа размещения предоставляет API и команды PowerShell для управления веб-размещением. + Веб-роль + Веб-роль устанавливает динамическую службу WAS и поставщик переопределения URL-адресов для веб-размещения. + Antares Express + Развертывание панели управления в конфигурации, оптимизированной для установки на одном компьютере. + Роль подсистемы балансировки нагрузки + Роль подсистемы балансировки нагрузки позволяет настроить в маршрутизаторе запросов приложений маршрутизацию на основе правил веб-размещения. + Контроллер размещения + Контроллер размещения расширяет платформу веб-ферм 2.0, позволяя ей работать с веб-размещением. + Публикация — роль + Установка средств поддержки веб-развертывания и FTP-публикации. + Эта оснастка PowerShell, которая содержит командлеты для управления инфраструктурой Microsoft Web Hosting. + Динамическая служба WAS + Служба активации Windows, оптимизированная для веб-размещения высокой плотности. + Служба контроля ресурсов + Установка службы контроля ресурсов, которая позволяет собирать и публиковать сведения о среде выполнения и работоспособности. + Resource Metering + Позволяет собирать с веб-роли сведения о среде выполнения и работоспособности и публиковать их. + Применение квот размещения + Служит для отслеживания использования ресурсов веб-сайтами и выполнения настраиваемых действий при превышении квот. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/TRK/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/TRK/misc/setupstrings.wxl new file mode 100644 index 0000000000..83599c3b1c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/TRK/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1055 + + + + Paylaşılan Yapılandırma Yükleme Seçenekleri + IIS paylaşılan yapılandırmasına yükleme seçeneğini belirtin + Yüklerken paylaşılan yapılandırmayı güncelleştir + Bu modülü paylaşılan yapılandırma kullanan bir IIS sunucusuna yüklüyorsunuz. Bu paylaşılan yapılandırmayı kullanan ek IIS sunucuları varsa, bu modülü söz konusu makinelerin tümüne yüklemeniz gerekir. Web sunucularında oluşabilecek kesintileri en az indirmek için bu modülü şu adımları kullanarak yüklemeniz gerekir: İlk olarak, sonuncu hariç tüm makinelerde paylaşılan yapılandırmayı güncelleştirmeden modülü yüklemeniz gerekir. Bunu, aşağıdaki onay kutusunu seçmeden yapın. +Bu işlem, paylaşılan yapılandırmada hiçbir değişiklik yapmadan modül için gereken tüm ikili ve diğer dosyaları her bir makineye yükler. İkinci olarak, sonuncu makinede, altında çalıştığınız kullanıcı kimliğinin UNC paylaşımındaki applicationhost.config dosyasında okuma ve yazma erişimi olduğunu doğrulamalısınız. Sonra, modülü yüklemeli ve aşağıdaki paylaşılan yapılandırmayı güncelleştirme seçeneğini seçmeniz gerekir. + + + WebConfig özel eylemi başlatılıyor + web.config güncelleştiriliyor + + + + IIS Gelişmiş Günlüğü + IIS ardışık düzen verileri için gelişmiş günlüğü etkinleştirir. + IIS Gelişmiş Günlüğü + Genişletilebilir alan seçimi olan özel günlük dosyaları oluşturmaya olanak tanır. + IIS Gelişmiş Günlüğü Güncelleştirmesi + + + + IIS Dönüşüm Yöneticisi + Beta + Dönüşüm Yöneticisi IIS Medya Hizmetleri'ni etkinleştirir. + IIS Dönüşüm Yöneticisi + Medya dönüşümleri oluşturmayı etkinleştirir. + IIS Dönüşüm Yöneticisi Ana Bilgisayarı + [ProductName] için hizmet ana bilgisayarı. + IIS Dönüşüm Yöneticisi + İsteğe bağlı medya dosyalarını alternatif dosya ve kapsayıcı biçimlerine toplu olarak dönüştürün. + Bir IIS Transform Manager 1.0 Expression Encoder SP Task paketi bilgisayarda yüklü. [ProductName] ürününü yüklemeden önce bunu kaldırmalısınız. + + [ProductName] ürününü yüklemek için Microsoft .NET Framework 3.5 gereklidir. Sunucu Yöneticisi'ndeki 'Özellik Ekleme Sihirbazı'nı kullanarak .NET Framework 3.5.1 Özellikleri'ni yükleyin veya 'Windows özelliklerini aç veya kapat'ı kullanarak Microsoft .NET Framework 3.5'i açın. + + + + IIS Dijital Hak Yönetimi + Beta + Kesintisiz Akış sunularında Dijital Hak Yönetimini etkinleştirir. + + + ASP.NET Yüklü Değil + + + + + + + + + Bu bilgisayarda IIS Kesintisiz Akış - Beta bulundu. [ProductName] yüklemesi devam edemez. Bu ürünü yüklemek için, Denetim Masası'ndaki Program Ekle/Kaldır'ı kullanarak IIS Kesintisiz Akış - Beta'yı kaldırın. + Bu bilgisayarda IIS Medya Hizmetleri'nin uyumsuz bir sürümü var. [ProductName] yüklemesi devam edemez. Bu ürünü yüklemek için, Denetim Masası'ndaki Program Ekle/Kaldır'ı kullanarak IIS Medya Hizmetleri'ni kaldırın. + Bu ürünün daha yeni bir sürümü bu bilgisayarda yüklü veya bu bilgisayara yüklenebilir durumda. [ProductName] yüklemesi devam edemiyor. Bu ürünün yeni sürümünü yüklemek için, Denetim Masası'ndaki Program Ekle/Kaldır'ı kullanarak IIS Medya Hizmetleri'ni güncelleştirin. + Çalma Listesi Dosyasının Dönüştürülmesi Gerekiyor + + + + + Eski IIS Medya Hizmetleri Dosyaları Bulundu + + + + + Beta IIS Medya Hizmetleri Dosyaları Bulundu + + + + + + IIS Medya Paketi 1.0 + IIS Medya Paketi 1.0 Güncelleştirmesi + IIS Medya Hizmetleri 2.0 + IIS Medya Paketi 2.0 Güncelleştirmesi + IIS Medya Hizmetleri 3.0 + IIS Medya Hizmetleri 3.0 TAP 2 + IIS Medya Paketi 3.0 Güncelleştirmesi + IIS Medya Paketi özellikleri ve araçları. + IIS Media Services 5 Premium özellikleri ve araçları. + IIS Medya Hizmetleri 4.0 Beta 1 + IIS Medya Hizmetleri 4.0 + IIS Medya Hizmetleri 4.5 Beta 1 + IIS Media Services 5 Premium + + Web Çalma Listeleri + İstemcinin, çalma listelerinde başvurulan medya listelerini kayıttan yürütmesini denetler. + Oturum Yardımcısı + ASP.NET oturum durumu kalıcılığını etkinleştirir. (Web Sunucusu (IIS) için ASP.NET rol hizmetini gerektirir.) + Kullanıcı Arabirimi + IIS Yöneticisi'nde Web Çalma Listeleri özelliğini yapılandırır. + + Bit Hızı Azaltma + İstemcilerin karşıdan yüklediği dosyaların teslimini yavaşlatarak bant genişliğinden tasarruf sağlar. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Bit Hızı Azaltma özelliğini yapılandırır. + + Varlıklar + İsteğe bağlı varlıkların istemcilere HTTP ile uyarlamalı akışını etkinleştirir. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Kesintisiz Akış özelliğini yapılandırır. + + Kanallar + Kanal yayınlarının istemcilere HTTP ile uyarlamalı akışını etkinleştirir. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Canlı Kesintisiz Akış özelliğini yapılandırır. + + Dijital Hak Yönetimi + Kesintisiz Akış medyası için şifreleme ve lisanslama sağlar. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Dijital Hak Yönetimi özelliğini yapılandırır. + + [ProductName] için Microsoft Windows Vista Service Pack 1 veya üstü gereklidir. + [ProductName], Vista Home Basic üzerine yüklenemez. + [ProductName] için Microsoft Windows 7 Service Pack 1 veya üstü gereklidir. + + + IIS Veritabanı Yöneticisi + IIS Veritabanı Yöneticisi + + + Microsoft Web Yönetimi Hizmeti 2 + Microsoft Web Yönetimi Hizmeti + [ProductName] ürününün temel özelliklerini yükler. + Microsoft Web Yönetimi Hizmeti 2 + Web Yönetimi Hizmeti, yöneticilerin bu makinede bulunan Web sunucularını, siteleri ve uygulamaları yönetmeleri için uzaktan ve temsilci seçilmiş yönetim becerileri sağlar. + + + IIS 7 için Microsoft URL Yeniden Yazma Modülü 1.1 + IIS 7 için URL Yeniden Yazma Modülü 1.1 Güncelleştirmesi + URL Yeniden Yazma + IIS 7'nin URL ve içerik yeniden yazma yeteneklerini etkinleştirir. + Kullanıcı Arabirimi + IIS Yöneticisi'nde URL Yeniden Yazma Modülü özelliğini yapılandırır. + + + IIS URL Yeniden Yazma Modülü 2 + IIS URL Yeniden Yazma Modülü 2 Güncelleştirmesi + URL Yeniden Yazma + IIS 7'nin URL ve içerik yeniden yazma yeteneklerini etkinleştirir. + Kullanıcı Arabirimi + IIS Yöneticisi'nde URL Yeniden Yazma Modülü özelliğini yapılandırır. + + + IIS 7.0 için Yönetim Paketi + [ProductName] ürününün temel özelliklerini yükler. + 1254 + IIS 7.0 için Yönetim Paketi + Microsoft Corporation + İşletim sisteminin bu sürümü desteklenmiyor. [ProductName] yalnızca Windows Server 2008 ya da Windows Vista Service Pack 1 ve üstü üzerine yüklenebilir. + ASP.Net Özellikleri + ASP.NET, yetkilendirme ve özel hata ayarlarınızı yönetmenizi sağlayan Yetkilendirme ve Hata Sayfaları özelliklerini içerir. + Kimlik Doğrulaması + ASP.Net Kimlik Doğrulaması Açıklaması. + Yetkilendirme + ASP.NET Yetkilendirme, kullanıcılara Web sitelerinize ve uygulamalarınıza erişme yetkisi verme kurallarını yapılandırmanızı sağlar. + Hata Sayfaları + ASP.NET Hata Sayfaları, hata oluştuğunda döndürülen HTTP hata yanıtlarını yapılandırmanızı sağlar. + Modüller + ASP.Net Modülleri Açıklaması. + İşleyiciler + ASP.Net İşleyiciler Açıklaması. + Yapılandırma Düzenleyicisi + Yapılandırma Düzenleyicisi, IIS Yöneticisi'nde yapılandırma dosyalarındaki bölümleri, öznitelikleri, öğeleri ve koleksiyonları düzenlemenize olanak tanıyarak yapılandırma dosyalarınızı yönetmenizi sağlar. + İstek Filtreleme + İstek Filtreleme, Web siteniz için filtreleme kurallarını yapılandırmanızı, protokol ve içerik davranışını kısıtlamanızı sağlar. + FastCGI + FastCGI, Web sunucunuzdaki FastCGI uygulamaları için işlem havuzu ayarlarını yapılandırmanızı sağlar. + + + IIS 7 için Dinamik IP Kısıtlamaları Kurulumu + + + + + + + + + + + + + IIS 7 için Dinamik IP Kısıtlamaları - Beta + IIS 7 için Dinamik IP Kısıtlamaları - Beta 2 + IIS 7 için Dinamik IP Kısıtlamaları - Beta 3 + + IIS 7 için Dinamik IP Kısıtlamaları - Sürüm Adayı + IIS 7 için Dinamik IP Kısıtlamaları - Sürüm Adayı 2 + IIS 7 için Dinamik IP Kısıtlamaları - Sürüm Adayı 3 + + IIS 7 için Dinamik IP Kısıtlamaları - RTW + + IIS 7 için Dinamik IP Kısıtlamaları + IIS 7 için Dinamik IP Kısıtlamaları Kullanıcı Arabirimi + + Bu makinede IIS 7 - Beta için Dinamik IP Kısıtlamaları bulundu. Lütfen kaldırın ve yeniden deneyin + + + IIS 7.0 için WebDAV 7.5 + Bu ürünü kullanmak için IIS 7.0 CoreWebEngine ve W3SVC özellikleri yüklenmelidir. + WebDAV Sunucu Modülü + WebDAV Yönetimi Kullanıcı Arabirimi + + + IIS Arama Alt Yapısı İyileştirme Araç Seti 1.0 + IIS Arama Alt Yapısı İyileştirme Araç Seti 1.0 + Arama Alt Yapısı İyileştirme (SEO) Araç Seti 1.0 + Bu yükleyici veritabanı IIS Arama Alt Yapısı İyileştirme Araç Seti 1.0'ı yüklemek için gereken mantığı ve verileri içermektedir. + + + IIS Düzenleyicisi + + + IIS Raporları + Bu makinede Günlük Ayrıştırıcısı yüklü değil. Lütfen http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 adresinden Günlük Ayrıştırıcısı 2.2 sürümünü yükleyin ve sonra IIS Raporları yüklemesine devam edin + + + Önkoşul paketler bulunamadı. Bağımlılıkları çözümlemek ve bu programı yüklemek için lütfen setup.exe'yi çalıştırın. + Microsoft SQL Server 2008 Yönetim Nesneleri, IIS Veritabanı Yöneticisi'ni yüklemek için bir önkoşuldur. Microsoft SQL Server 2008 Yönetim Nesneleri'ni http://go.microsoft.com/fwlink/?LinkID=150946 adresinden yükleyebilirsiniz. + Microsoft SQL Server Sistem CLR Türleri, IIS Veritabanı Yöneticisi'ni yüklemek için bir önkoşuldur. Microsoft SQL Server Sistem CLR Türleri'ni http://go.microsoft.com/fwlink/?LinkID=150949 adresinden yükleyebilirsiniz. + + + Microsoft Web Grubu Çerçevesi + Microsoft Dış Önbellek + Web Grubu Çerçevesi, Uygulama İsteği Yönlendirme için bir önkoşuldur. Lütfen Web Grubu Çerçevesi'ni yükleyin. + Microsoft Uygulama İsteği Yönlendirme 2.5 + Çalışma Zamanı + IIS'ye Uygulama İsteği Yönlendirme özellikleri ekler. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Uygulama İsteği Yönlendirme özelliğini yapılandırır. + + + IIS 7.0 için Microsoft Windows PowerShell ek bileşeni + + + Microsoft Web Platformu Yükleyicisi 4.0 + Microsoft Web Platformu Yükleyicisi + [ProductName] için Windows XP SP2, Windows 2003 SP1, Windows Vista veya üstü gereklidir. + [ProductName] için Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 veya üstü gereklidir. + + + Microsoft Windows Azure Hizmetleri Yükleyicisi + Microsoft Windows Azure Hizmetleri Yükleyicisi + + + Internet Information Services (IIS) 7+ Yöneticisi + IIS Yöneticisi İstemcisi + Uzaktan İletişim Desteği + Bu ürün için Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 veya daha üstü gereklidir + IIS Yönetim Konsolu yüklenmedi ancak uzak IIS Sunucularını yönetmek için gerekiyor. Uzaktan yönetim desteğini yüklemeden önce lütfen 'Denetim Masası -> Programlar -> Windows Özelliklerini Aç veya Kapat'ı açın ve Internet Information Services özelliğinde IIS Yönetimi Konsolu'nu seçin. + Bu ürün Windows Server 2008, Windows Server 2008 R2 veya daha üstünde gerekli değildir. IIS Yönetim Konsolu'nu yüklemek üzere lütfen Sunucu Yöneticisi'ni açın ve Web Sunucusu Rolü için Rol Hizmetleri'nde IIS Yönetim Konsolu'nu seçin. + + + IIS 7.0 için IIS Yöneticisi Yayımlama + Yayımlama Kullanıcı Arabirimi + + + IIS 7.5 için Application Warm-Up 1.0 + + + + Bu bilgisayarda uyumsuz bir ürün ([CONFLICTING_PRODUCT_NAME]) mevcut. [ProductName] ürününün yüklemesi devam edemiyor. Bu ürünü yüklemek için [CONFLICTING_PRODUCT_NAME] ürününü kaldırmak amacıyla Denetim Masası'ndaki Program Ekle/Kaldır'ı kullanın. + [ProductName] ürününü yüklemek için yönetici ayrıcalıkları gereklidir. + [ProductName] ürününü kullanmak için IIS Sürüm 7.0 gereklidir. + [ProductName] ürününü yüklemek için IIS Sürüm 7.0 veya üstü gereklidir. + [ProductName] ürününü yüklemek için IIS Sürüm 7.5 veya üstü gereklidir. + [ProductName] ürününü yüklemek için IIS Sürüm 7 veya 7.5 gereklidir. + Bu makinede [ProductName] ürününün beta sürümü bulundu. + Bu makinede [ProductName] ürününün daha yeni bir sürümü bulundu. + Bu bilgisayara başka bir [ProductName] örneği önceden yüklendiğinden Kurulum devam edemiyor. Lütfen önce onu kaldırın ve sonra bu yükleme işlemini yeniden başlatın. + [ProductName] ürününü kullanmak için IIS 7.0 CoreWebEngine ve W3SVC özellikleri yüklenmelidir. + [ProductName] ürününü kullanmak için IIS Yönetim Konsolu yüklenmelidir. + [ProductName] ürününü yüklemeden önce lütfen Windows İşlem Etkinleştirme Hizmeti (WAS) ve Web Yönetimi Hizmeti (WMSvc) hizmetlerinin ikisini de durdurun. [ProductName] yüklendikten sonra hizmetleri yeniden başlatmanız gerekir. + [ProductName] ürününü yüklemek için IIS Metatabanı gereklidir. + [ProductName] ürünün 64-bit sürümü Microsoft Windows'un 32-bit bir sürümüne yüklenemez. + [ProductName] ürünün 32-bit sürümü Microsoft Windows'un 64-bit bir sürümüne yüklenemez. + [ProductName] ürününü yüklemek için Microsoft .NET Framework Sürüm 2.0 veya üstü gereklidir. + [ProductName] ürününü yüklemek için Microsoft .NET Framework Sürüm 3.5 veya üstü gereklidir. Microsoft .Net Sürüm 3.5'i yüklemek için Sunucu Yöneticisi altındaki 'Özellik Ekle' seçeneğini kullanın. + [ProductName] ürününü yüklemek için Microsoft .NET Framework Sürüm 4.0 veya üstü gereklidir. + [ProductName] ürününü yüklemeden önce lütfen Microsoft .NET Framework Sürüm 2.0 Service Pack 1'i (veya daha yeni bir hizmet paketini) yükleyin. + Windows Update (wuauserv) hizmeti devre dışı bırakılamaz; [ProductName] ürününü yüklemek için gereklidir. + PowerShell ek bileşeni Windows İşletim Sisteminin bir parçasıdır. Lütfen 'Programlar ve Özellikler' veya 'Sunucu Yöneticisi' aracılığıyla yükleyin. + [ProductName] ürününü yüklemek için Microsoft Web Platformu Yükleyicisi 3.0 veya üstü gereklidir. + + Kurulum paylaşılan yapılandırmayı silemedi. + IIS için paylaşılan yapılandırma etkin. Paylaşılan yapılandırma kullanılırken [ProductName] ürününün yüklenmesi desteklenmiyor. Bu özelliği yüklemeden önce lütfen paylaşılan yapılandırmayı devre dışı bırakın. + + [ProductName] ürününü yüklemeden önce lütfen World Wide Web Yayımlama Hizmeti'ni (W3SVC) durdurun. Yükleme işleminden sonra hizmeti yeniden başlatmanız gerekir. + IIS PowerShell Yönetim Konsolu + IIS PowerShell ek bileşeni + IIS PowerShell ek bileşeni için PowerShell v1.0 veya v2.0 yüklü olmalıdır + IIS PowerShell ek bileşeni için WAS ve yapılandırma yüklü olmalıdır + Bu hatalı bir dizedir. + + + Microsoft Web Grubu Çerçevesi Sürüm 2.2 + Microsoft Web Grubu Aracısı Sürüm 2.2 + Web Grubu Hizmeti + Web Grubu Hizmeti + Web Grubu Denetleyicisi Hizmeti + Web Grubu Denetleyicisi Hizmeti + Web Grubu Aracısı Hizmeti + Web Grubu Aracısı Hizmeti + Web Grubu Çerçevesi'ni yüklemek için Web Platformu Yükleyicisi bir önkoşuldur. Lütfen http://www.microsoft.com/web/downloads/platform.aspx adresinden Web Platformu Yükleyicisi'ni yükleyin. + Web Grubu Çerçevesi'ni yüklemek için Web Dağıtım Aracı bir önkoşuldur. Lütfen http://www.iis.net/download/WebDeploy adresinden Web Dağıtımı Aracı'nı yükleyin. + + + Microsoft Web Barındırma Çerçevesi + Web Barındırma Çerçevesi + Web Barındırma rolleri ve özellikleri. + Barındırma Çerçevesi + Barındırma Çerçevesi, Web Barındırma'yı yönetmek için API'ler ve PowerShell komutları sağlar. + Web Rolü + Web Rolü, Web Barındırma için Dinamik WAS hizmetini ve URL Yeniden Yazma sağlayıcısını yükler. + Antares Express + Tek makineli kurulum için en iyi duruma getirilen bir Denetim Masası yapılandırmasını dağıtır. + Yük Dengeleyici Rolü + Yük Dengeleyici Rolü, Uygulama İstek Yönlendiricisini Web Barındırma kurallarına göre yönlendirecek şekilde yapılandırır. + Barındırma Denetleyicisi + Barındırma Denetleyicisi, Web Grubu Çerçevesi 2.0'ı Web Barındırma ile çalışacak şekilde genişletir. + Yayımlama Rolü + Web Dağıtımı ve FTP yayımlama için desteği yükler. + Bu, Microsoft Web Barındırma altyapısını yönetmeyi sağlayan cmdlet'ler içeren bir PowerShell ek bileşenidir. + Dinamik WAS Hizmeti + Yüksek yoğunluklu Web Barındırma için en iyi duruma getirilmiş Windows İşlem Etkinleştirme hizmeti. + Kaynak Ölçümü Hizmeti + Çalışma zamanı ve sistem bilgisi toplamayı ve yayımlamayı sağlayan Kaynak Ölçümü hizmetini yükler. + Kaynak Ölçümü + Web Rolünden çalışma zamanı ve sistem bilgisi toplamayı ve yayımlamayı sağlar. + Barındırma Kota Uygulama + Web sitesi kaynak kullanımını izler ve kullanım kotası aşıldığında özel eylemler uygular. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/dutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/dutil.h new file mode 100644 index 0000000000..2a830b7c83 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/dutil.h @@ -0,0 +1,181 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +//------------------------------------------------------------------------------------------------- +// +// Header for utility layer that provides standard support for asserts, exit macros +// +//------------------------------------------------------------------------------------------------- + +#define DAPI __stdcall +#define DAPIV __cdecl // used only for functions taking variable length arguments + +#define DAPI_(type) EXTERN_C type DAPI +#define DAPIV_(type) EXTERN_C type DAPIV + + +// enums +enum REPORT_LEVEL { + REPORT_NONE, // turns off report (only valid for XXXSetLevel()) + REPORT_STANDARD, // written if reporting is on + REPORT_VERBOSE, // written only if verbose reporting is on + REPORT_DEBUG, // reporting useful when debugging code + REPORT_ERROR, // always gets reported, but can never be specified + }; + +// asserts and traces +#ifdef DEBUG + +typedef BOOL (DAPI *DUTIL_ASSERTDISPLAYFUNCTION)(LPCSTR sz); + +extern "C" void DAPI Dutil_SetAssertModule(__in HMODULE hAssertModule); +extern "C" void DAPI Dutil_SetAssertDisplayFunction(__in DUTIL_ASSERTDISPLAYFUNCTION pfn); +extern "C" void DAPI Dutil_Assert(const CHAR* szFile, int iLine); +extern "C" void DAPI Dutil_AssertSz(const CHAR* szFile, int iLine, const CHAR *szMsg); + +extern "C" void DAPI Dutil_TraceSetLevel(__in REPORT_LEVEL ll, __in BOOL fTraceFilenames); +extern "C" REPORT_LEVEL DAPI Dutil_TraceGetLevel(); +extern "C" void __cdecl Dutil_Trace(__in LPCSTR szFile, __in int iLine, __in REPORT_LEVEL rl, __in LPCSTR szMessage, ...); +extern "C" void __cdecl Dutil_TraceError(__in LPCSTR szFile, __in int iLine, __in REPORT_LEVEL rl, __in HRESULT hr, __in LPCSTR szMessage, ...); + +#endif + +#if defined DEBUG + +#define AssertSetModule(m) (void)Dutil_SetAssertModule(m) +#define AssertSetDisplayFunction(pfn) (void)Dutil_SetAssertDisplayFunction(pfn) +#define Assert(f) ((f) ? (void)0 : (void)Dutil_Assert(__FILE__, __LINE__)) +#define AssertSz(f, sz) ((f) ? (void)0 : (void)Dutil_AssertSz(__FILE__, __LINE__, sz)) + +#define TraceSetLevel(l, f) (void)Dutil_TraceSetLevel(l, f) +#define TraceGetLevel() (REPORT_LEVEL)Dutil_TraceGetLevel() +#define Trace(l, f) (void)Dutil_Trace(__FILE__, __LINE__, l, f, NULL) +#define Trace1(l, f, s) (void)Dutil_Trace(__FILE__, __LINE__, l, f, s) +#define Trace2(l, f, s, t) (void)Dutil_Trace(__FILE__, __LINE__, l, f, s, t) +#define Trace3(l, f, s, t, u) (void)Dutil_Trace(__FILE__, __LINE__, l, f, s, t, u) + +#define TraceError(x, f) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, NULL) +#define TraceError1(x, f, s) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, s) +#define TraceError2(x, f, s, t) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, s, t) +#define TraceError3(x, f, s, t, u) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, s, t, u) + +#define TraceErrorDebug(x, f) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, NULL) +#define TraceErrorDebug1(x, f, s) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, s) +#define TraceErrorDebug2(x, f, s, t) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, s, t) +#define TraceErrorDebug3(x, f, s, t, u) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, s, t, u) + +#else // !DEBUG + +#define AssertSetModule(m) +#define AssertSetDisplayFunction(pfn) +#define Assert(f) +#define AssertSz(f, sz) + +#define TraceSetLevel(l, f) +#define Trace(l, f) +#define Trace1(l, f, s) +#define Trace2(l, f, s, t) +#define Trace3(l, f, s, t, u) + +#define TraceError(x, f) +#define TraceError1(x, f, s) +#define TraceError2(x, f, s, t) +#define TraceError3(x, f, s, t, u) + +#define TraceErrorDebug(x, f) +#define TraceErrorDebug1(x, f, s) +#define TraceErrorDebug2(x, f, s, t) +#define TraceErrorDebug3(x, f, s, t, u) + +#endif // DEBUG + + +// ExitTrace can be overriden +#ifndef ExitTrace +#define ExitTrace TraceError +#endif +#ifndef ExitTrace1 +#define ExitTrace1 TraceError1 +#endif +#ifndef ExitTrace2 +#define ExitTrace2 TraceError2 +#endif +#ifndef ExitTrace3 +#define ExitTrace3 TraceError3 +#endif + +// Exit macros +#define ExitFunction() { goto LExit; } +#define ExitFunction1(x) { x; goto LExit; } + +#define ExitOnLastError(x, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace(x, s); goto LExit; } } +#define ExitOnLastError1(x, f, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace1(x, f, s); goto LExit; } } +#define ExitOnLastError2(x, f, s, t) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace2(x, f, s, t); goto LExit; } } + +#define ExitOnLastErrorDebugTrace(x, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { TraceErrorDebug(x, s); goto LExit; } } +#define ExitOnLastErrorDebugTrace1(x, f, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { TraceErrorDebug1(x, f, s); goto LExit; } } +#define ExitOnLastErrorDebugTrace2(x, f, s, t) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { TraceErrorDebug2(x, f, s, t); goto LExit; } } + +#define ExitWithLastError(x, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, s); goto LExit; } +#define ExitWithLastError1(x, f, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace1(x, f, s); goto LExit; } +#define ExitWithLastError2(x, f, s, t) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace2(x, f, s, t); goto LExit; } + +#define ExitOnFailure(x, s) if (FAILED(x)) { ExitTrace(x, s); goto LExit; } +#define ExitOnFailure1(x, f, s) if (FAILED(x)) { ExitTrace1(x, f, s); goto LExit; } +#define ExitOnFailure2(x, f, s, t) if (FAILED(x)) { ExitTrace2(x, f, s, t); goto LExit; } +#define ExitOnFailure3(x, f, s, t, u) if (FAILED(x)) { ExitTrace3(x, f, s, t, u); goto LExit; } + +#define ExitOnFailureDebugTrace(x, s) if (FAILED(x)) { TraceErrorDebug(x, s); goto LExit; } +#define ExitOnFailureDebugTrace1(x, f, s) if (FAILED(x)) { TraceErrorDebug1(x, f, s); goto LExit; } +#define ExitOnFailureDebugTrace2(x, f, s, t) if (FAILED(x)) { TraceErrorDebug2(x, f, s, t); goto LExit; } +#define ExitOnFailureDebugTrace3(x, f, s, t, u) if (FAILED(x)) { TraceErrorDebug3(x, f, s, t, u); goto LExit; } + +#define ExitOnNull(p, x, e, s) if (NULL == p) { x = e; ExitTrace(x, s); goto LExit; } +#define ExitOnNull1(p, x, e, f, s) if (NULL == p) { x = e; ExitTrace1(x, f, s); goto LExit; } +#define ExitOnNull2(p, x, e, f, s, t) if (NULL == p) { x = e; ExitTrace2(x, f, s, t); goto LExit; } + +#define ExitOnNullWithLastError(p, x, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, s); goto LExit; } +#define ExitOnNullWithLastError1(p, x, f, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace1(x, f, s); goto LExit; } + +#define ExitOnNullDebugTrace(p, x, e, s) if (NULL == p) { x = e; TraceErrorDebug(x, s); goto LExit; } +#define ExitOnNullDebugTrace1(p, x, e, f, s) if (NULL == p) { x = e; TraceErrorDebug1(x, f, s); goto LExit; } + +#define ExitOnNtError(x, s) if (NT_ERROR(x)) { ExitTrace(x, s); goto LExit; } +#define ExitOnNtError1(x, f, s) if (NT_ERROR(x)) { ExitTrace1(x, f, s); goto LExit; } + + +// release macros +#define ReleaseObject(x) if (x) { x->Release(); } +#define ReleaseVariant(x) { ::VariantClear(&x); } +#define ReleaseNullObject(x) if (x) { (x)->Release(); x = NULL; } +#define ReleaseCertificate(x) if (x) { ::CertFreeCertificateContext(x); x=NULL; } + + +// useful defines and macros +#define Unused(x) ((void)x) + +#ifndef MAXSIZE_T +#define MAXSIZE_T ((SIZE_T)~((SIZE_T)0)) +#endif + + +#if 1 +#define countof(ary) (sizeof(ary) / sizeof(ary[0])) +#else +#ifndef __cplusplus +#define countof(ary) (sizeof(ary) / sizeof(ary[0])) +#else +template static char countofVerify(void const *, T) throw() { return 0; } +template static void countofVerify(T *const, T *const *) throw() {}; +#define countof(arr) (sizeof(countofVerify(arr,&(arr))) * sizeof(arr)/sizeof(*(arr))) +#endif +#endif + + +#ifndef MAXSIZE_T +#define MAXSIZE_T ((SIZE_T)~((SIZE_T)0)) +#endif + +#define E_NOMOREITEMS HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) +#define AddRefAndRelease(x) { x->AddRef(); x->Release(); } diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/memutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/memutil.h new file mode 100644 index 0000000000..36077b0fc6 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/memutil.h @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +//------------------------------------------------------------------------------------------------- +// +// Header for memory helper functions. +// +//------------------------------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define ReleaseMem(p) if (p) { MemFree(p); } +#define ReleaseNullMem(p) if (p) { MemFree(p); p = NULL; } + + +HRESULT DAPI MemInitialize(); +void DAPI MemUninitialize(); + +LPVOID DAPI MemAlloc( + __in SIZE_T cbSize, + __in BOOL fZero + ); +LPVOID DAPI MemReAlloc( + __in LPVOID pv, + __in SIZE_T cbSize, + __in BOOL fZero + ); + +HRESULT DAPI MemFree( + __in LPVOID pv + ); +SIZE_T DAPI MemSize( + __in LPVOID pv + ); + +#ifdef __cplusplus +} +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/precomp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/precomp.h new file mode 100644 index 0000000000..e41eecd4e4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/precomp.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include +#include +#include +#include + +const WCHAR MAGIC_MULTISZ_DELIM = 128; + +#include "wcautil.h" +#include "memutil.h" +#include "strutil.h" diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/qtexec.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/qtexec.cpp new file mode 100644 index 0000000000..45d0945f62 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/qtexec.cpp @@ -0,0 +1,276 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Executes command line instructions without popping up a shell. +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + +#define OUTPUT_BUFFER 1024 + + +#define ONEMINUTE 60000 + +static HRESULT CreatePipes( + __out HANDLE *phOutRead, + __out HANDLE *phOutWrite, + __out HANDLE *phErrWrite, + __out HANDLE *phInRead, + __out HANDLE *phInWrite + ) +{ + Assert(phOutRead); + Assert(phOutWrite); + Assert(phErrWrite); + Assert(phInRead); + Assert(phInWrite); + + HRESULT hr = S_OK; + SECURITY_ATTRIBUTES sa; + HANDLE hOutTemp = INVALID_HANDLE_VALUE; + HANDLE hInTemp = INVALID_HANDLE_VALUE; + + HANDLE hOutRead = INVALID_HANDLE_VALUE; + HANDLE hOutWrite = INVALID_HANDLE_VALUE; + HANDLE hErrWrite = INVALID_HANDLE_VALUE; + HANDLE hInRead = INVALID_HANDLE_VALUE; + HANDLE hInWrite = INVALID_HANDLE_VALUE; + + // Fill out security structure so we can inherit handles + ::ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + // Create pipes + if (!::CreatePipe(&hOutTemp, &hOutWrite, &sa, 0)) + ExitOnLastError(hr, "failed to create output pipe"); + + if (!::CreatePipe(&hInRead, &hInTemp, &sa, 0)) + ExitOnLastError(hr, "failed to create input pipe"); + + + // Duplicate output pipe so standard error and standard output write to + // the same pipe + if (!::DuplicateHandle(::GetCurrentProcess(), hOutWrite, ::GetCurrentProcess(), &hErrWrite, 0, TRUE, DUPLICATE_SAME_ACCESS)) + ExitOnLastError(hr, "failed to duplicate write handle"); + + // We need to create new output read and input write handles that are + // non inheritable. Otherwise it creates handles that can't be closed. + if (!::DuplicateHandle(::GetCurrentProcess(), hOutTemp, ::GetCurrentProcess(), &hOutRead, 0, FALSE, DUPLICATE_SAME_ACCESS)) + ExitOnLastError(hr, "failed to duplicate output pipe"); + + if (!::DuplicateHandle(::GetCurrentProcess(), hInTemp, ::GetCurrentProcess(), &hInWrite, 0, FALSE, DUPLICATE_SAME_ACCESS)) + ExitOnLastError(hr, "failed to duplicate input pipe"); + + // now that everything has succeeded, assign to the outputs + *phOutRead = hOutRead; + hOutRead = INVALID_HANDLE_VALUE; + + *phOutWrite = hOutWrite; + hOutWrite = INVALID_HANDLE_VALUE; + + *phErrWrite = hErrWrite; + hErrWrite = INVALID_HANDLE_VALUE; + + *phInRead = hInRead; + hInRead = INVALID_HANDLE_VALUE; + + *phInWrite = hInWrite; + hInWrite = INVALID_HANDLE_VALUE; + +LExit: + if (INVALID_HANDLE_VALUE != hOutRead) + ::CloseHandle(hOutRead); + if (INVALID_HANDLE_VALUE != hOutWrite) + ::CloseHandle(hOutWrite); + if (INVALID_HANDLE_VALUE != hErrWrite) + ::CloseHandle(hErrWrite); + if (INVALID_HANDLE_VALUE != hInRead) + ::CloseHandle(hInRead); + if (INVALID_HANDLE_VALUE != hInWrite) + ::CloseHandle(hInWrite); + if (INVALID_HANDLE_VALUE != hOutTemp) + ::CloseHandle(hOutTemp); + if (INVALID_HANDLE_VALUE != hInTemp) + ::CloseHandle(hInTemp); + + return hr; +} + +static HRESULT LogOutput( + __in HANDLE hRead + ) +{ + BYTE *pBuffer = NULL; + LPWSTR szLog = NULL; + LPWSTR szTemp = NULL; + LPWSTR pEnd = NULL; + LPWSTR pNext = NULL; + LPSTR szWrite = NULL; + DWORD dwBytes = OUTPUT_BUFFER; + BOOL bFirst = TRUE; + BOOL bUnicode = TRUE; + HRESULT hr = S_OK; + + // Get buffer for output + pBuffer = (BYTE *)MemAlloc(OUTPUT_BUFFER, FALSE); + ExitOnNull(pBuffer, hr, E_OUTOFMEMORY, "Failed to allocate buffer for output."); + + while (0 != dwBytes) + { + ::ZeroMemory(pBuffer, OUTPUT_BUFFER); + if(!::ReadFile(hRead, pBuffer, OUTPUT_BUFFER - 1, &dwBytes, NULL) && GetLastError() != ERROR_BROKEN_PIPE) + { + ExitOnLastError(hr, "Failed to read from handle."); + } + + // Check for UNICODE or ANSI output + if (bFirst) + { + if ((isgraph(pBuffer[0]) && isgraph(pBuffer[1])) || + (isgraph(pBuffer[0]) && isspace(pBuffer[1])) || + (isspace(pBuffer[0]) && isgraph(pBuffer[1])) || + (isspace(pBuffer[0]) && isspace(pBuffer[1]))) + bUnicode = FALSE; + bFirst = FALSE; + } + + // Keep track of output + if (bUnicode) + { + hr = StrAllocConcat(&szLog, (LPWSTR)pBuffer, 0); + ExitOnFailure(hr, "failed to concatenate output strings"); + } + else + { + hr = StrAllocStringAnsi(&szTemp, (LPSTR)pBuffer, 0, CP_OEMCP); + ExitOnFailure(hr, "failed to allocate output string"); + hr = StrAllocConcat(&szLog, szTemp, 0); + ExitOnFailure(hr, "failed to concatenate output strings"); + } + + // Log each line of the output + pNext = szLog; + pEnd = wcschr(szLog, L'\r'); + if (NULL == pEnd) + pEnd = wcschr(szLog, L'\n'); + while (pEnd && *pEnd) + { + // Find beginning of next line + pEnd[0] = 0; + pEnd++; + if ((pEnd[0] == L'\r') || (pEnd[0] == L'\n')) + pEnd++; + + // Log output + hr = StrAnsiAllocString(&szWrite, pNext, 0, CP_OEMCP); + ExitOnFailure(hr, "failed to convert output to ANSI"); + WcaLog(LOGMSG_STANDARD, szWrite); + + // Next line + pNext = pEnd; + pEnd = wcschr(pNext, L'\r'); + if (NULL == pEnd) + pEnd = wcschr(pNext, L'\n'); + } + + hr = StrAllocString(&szTemp, pNext, 0); + ExitOnFailure(hr, "failed to allocate string"); + + hr = StrAllocString(&szLog, szTemp, 0); + ExitOnFailure(hr, "failed to allocate string"); + } + + // Print any text that didn't end with a new line + if (szLog && *szLog) + { + hr = StrAnsiAllocString(&szWrite, szLog, 0, CP_OEMCP); + ExitOnFailure(hr, "failed to convert output to ANSI"); + WcaLog(LOGMSG_VERBOSE, szWrite); + } + +LExit: + if (NULL != pBuffer) + MemFree(pBuffer); + + ReleaseNullStr(szLog); + ReleaseNullStr(szTemp); + ReleaseNullStr(szWrite); + + return hr; +} + +HRESULT QuietExec( + __in LPWSTR wzCommand, + __in DWORD dwTimeout + ) +{ + HRESULT hr = S_OK; + PROCESS_INFORMATION oProcInfo; + STARTUPINFOW oStartInfo; + DWORD dwExitCode = ERROR_SUCCESS; + HANDLE hOutRead = INVALID_HANDLE_VALUE; + HANDLE hOutWrite = INVALID_HANDLE_VALUE; + HANDLE hErrWrite = INVALID_HANDLE_VALUE; + HANDLE hInRead = INVALID_HANDLE_VALUE; + HANDLE hInWrite = INVALID_HANDLE_VALUE; + + memset(&oProcInfo, 0, sizeof(oProcInfo)); + memset(&oStartInfo, 0, sizeof(oStartInfo)); + + // Create output redirect pipes + hr = CreatePipes(&hOutRead, &hOutWrite, &hErrWrite, &hInRead, &hInWrite); + ExitOnFailure(hr, "failed to create output pipes"); + + // Set up startup structure + oStartInfo.cb = sizeof(STARTUPINFOW); + oStartInfo.dwFlags = STARTF_USESTDHANDLES; + oStartInfo.hStdInput = hInRead; + oStartInfo.hStdOutput = hOutWrite; + oStartInfo.hStdError = hErrWrite; + + WcaLog(LOGMSG_VERBOSE, "%S", wzCommand); + + if (::CreateProcessW(NULL, + wzCommand, // command line + NULL, // security info + NULL, // thread info + TRUE, // inherit handles + ::GetPriorityClass(::GetCurrentProcess()) | CREATE_NO_WINDOW, // creation flags + NULL, // environment + NULL, // cur dir + &oStartInfo, + &oProcInfo)) + { + ::CloseHandle(oProcInfo.hThread); + + // Close child output/input handles so it doesn't hang + ::CloseHandle(hOutWrite); + ::CloseHandle(hErrWrite); + ::CloseHandle(hInRead); + + // Log output + LogOutput(hOutRead); + + // Wait for everything to finish + ::WaitForSingleObject(oProcInfo.hProcess, dwTimeout); + if (!::GetExitCodeProcess(oProcInfo.hProcess, &dwExitCode)) + dwExitCode = ERROR_SEM_IS_SET; + ::CloseHandle(hOutRead); + ::CloseHandle(hInWrite); + ::CloseHandle(oProcInfo.hProcess); + } + else + ExitOnLastError(hr, "Command failed to execute."); + + hr = HRESULT_FROM_WIN32(dwExitCode); + ExitOnFailure(hr, "Command line returned an error."); + +LExit: + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/strutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/strutil.h new file mode 100644 index 0000000000..151003329e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/strutil.h @@ -0,0 +1,165 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +//------------------------------------------------------------------------------------------------- +// +// Header for string helper functions. +// +//------------------------------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define ReleaseStr(pwz) if (pwz) { StrFree(pwz); } +#define ReleaseNullStr(pwz) if (pwz) { StrFree(pwz); pwz = NULL; } +#define ReleaseBSTR(bstr) if (bstr) { ::SysFreeString(bstr); } +#define ReleaseNullBSTR(bstr) if (bstr) { ::SysFreeString(bstr); bstr = NULL; } + +HRESULT DAPI StrAlloc( + __inout LPWSTR* ppwz, + __in DWORD_PTR cch + ); +HRESULT DAPI StrAnsiAlloc( + __inout LPSTR* ppz, + __in DWORD_PTR cch + ); +HRESULT DAPI StrAllocString( + __inout LPWSTR* ppwz, + __in LPCWSTR wzSource, + __in DWORD_PTR cchSource + ); +HRESULT DAPI StrAnsiAllocString( + __inout LPSTR* ppsz, + __in LPCWSTR wzSource, + __in DWORD_PTR cchSource, + __in UINT uiCodepage + ); +HRESULT DAPI StrAllocStringAnsi( + __inout LPWSTR* ppwz, + __in LPCSTR szSource, + __in DWORD_PTR cchSource, + __in UINT uiCodepage + ); +HRESULT DAPI StrAllocPrefix( + __inout LPWSTR* ppwz, + __in LPCWSTR wzPrefix, + __in DWORD_PTR cchPrefix + ); +HRESULT DAPI StrAllocConcat( + __inout LPWSTR* ppwz, + __in LPCWSTR wzSource, + __in DWORD_PTR cchSource + ); +HRESULT __cdecl StrAllocFormatted( + __inout LPWSTR* ppwz, + __in LPCWSTR wzFormat, + ... + ); +HRESULT __cdecl StrAnsiAllocFormatted( + __inout LPSTR* ppsz, + __in LPCSTR szFormat, + ... + ); +HRESULT DAPI StrAllocFormattedArgs( + __inout LPWSTR* ppwz, + __in LPCWSTR wzFormat, + __in va_list args + ); +HRESULT DAPI StrAnsiAllocFormattedArgs( + __inout LPSTR* ppsz, + __in LPCSTR szFormat, + __in va_list args + ); + +HRESULT DAPI StrMaxLength( + __in LPVOID p, + __out DWORD_PTR* pcch + ); +HRESULT DAPI StrSize( + __in LPVOID p, + __out DWORD_PTR* pcb + ); + +HRESULT DAPI StrFree( + __in LPVOID p + ); + +HRESULT DAPI StrCurrentTime( + __inout LPWSTR* ppwz, + __in BOOL fGMT + ); +HRESULT DAPI StrCurrentDateTime( + __inout LPWSTR* ppwz, + __in BOOL fGMT + ); + +HRESULT DAPI StrHexEncode( + __in_ecount(cbSource) const BYTE* pbSource, + __in DWORD_PTR cbSource, + __out_ecount(cchDest) LPWSTR wzDest, + __in DWORD_PTR cchDest + ); +HRESULT DAPI StrHexDecode( + __in LPCWSTR wzSource, + __out_bcount(cbDest) BYTE* pbDest, + __in DWORD_PTR cbDest + ); + +HRESULT DAPI StrAllocBase85Encode( + __in_bcount(cbSource) const BYTE* pbSource, + __in DWORD_PTR cbSource, + __inout LPWSTR* pwzDest + ); +HRESULT DAPI StrAllocBase85Decode( + __in LPCWSTR wzSource, + __out BYTE** hbDest, + __out DWORD_PTR* pcbDest + ); + +HRESULT DAPI MultiSzLen( + __in LPCWSTR pwzMultiSz, + __out DWORD_PTR* pcch + ); +HRESULT DAPI MultiSzPrepend( + __inout LPWSTR* ppwzMultiSz, + __inout_opt DWORD_PTR *pcchMultiSz, + __in LPCWSTR pwzInsert + ); +HRESULT DAPI MultiSzFindSubstring( + __in LPCWSTR pwzMultiSz, + __in LPCWSTR pwzSubstring, + __out_opt DWORD_PTR* pdwIndex, + __out_opt LPCWSTR* ppwzFoundIn + ); +HRESULT DAPI MultiSzFindString( + __in LPCWSTR pwzMultiSz, + __in LPCWSTR pwzString, + __out DWORD_PTR* pdwIndex, + __out LPCWSTR* ppwzFound + ); +HRESULT DAPI MultiSzRemoveString( + __inout LPWSTR* ppwzMultiSz, + __in DWORD_PTR dwIndex + ); +HRESULT DAPI MultiSzInsertString( + __inout LPWSTR* ppwzMultiSz, + __inout_opt DWORD_PTR *pcchMultiSz, + __in DWORD_PTR dwIndex, + __in LPCWSTR pwzInsert + ); +HRESULT DAPI MultiSzReplaceString( + __inout LPWSTR* ppwzMultiSz, + __in DWORD_PTR dwIndex, + __in LPCWSTR pwzString + ); + +LPCWSTR wcsistr( + IN LPCWSTR wzString, + IN LPCWSTR wzCharSet + ); + +#ifdef __cplusplus +} +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcalog.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcalog.cpp new file mode 100644 index 0000000000..b162bd6152 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcalog.cpp @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library logging functions +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + + +/******************************************************************** + IsVerboseLogging() - internal helper function to detect if doing + verbose logging + +********************************************************************/ +static BOOL IsVerboseLogging() +{ + static int iVerbose = -1; + + if (0 > iVerbose) + { + iVerbose = WcaIsPropertySet("LOGVERBOSE"); + if (0 == iVerbose) // if the property wasn't set, check the registry to see if the logging policy was turned on + { + HKEY hkey = NULL; + WCHAR rgwc[16] = { 0 }; + DWORD cb = sizeof(rgwc); + if (ERROR_SUCCESS == ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Policies\\Microsoft\\Windows\\Installer", 0, KEY_QUERY_VALUE, &hkey)) + { + if (ERROR_SUCCESS == ::RegQueryValueExW(hkey, L"Logging", 0, NULL, reinterpret_cast(rgwc), &cb)) + { + for (LPCWSTR pwc = rgwc; (cb / sizeof(WCHAR)) > static_cast(pwc - rgwc) && *pwc; pwc++) + { + if (L'v' == *pwc || L'V' == *pwc) + { + iVerbose = 1; + break; + } + } + } + + ::RegCloseKey(hkey); + } + } + } + + Assert(iVerbose >= 0); + return (BOOL)iVerbose; +} + + +/******************************************************************** + WcaLog() - outputs trace and log info + +*******************************************************************/ +extern "C" void WcaLog( + __in LOGLEVEL llv, + __in const char* fmt, ... + ) +{ + static char szFmt[LOG_BUFFER]; + static char szBuf[LOG_BUFFER]; + static bool fInLogPrint = false; + + // prevent re-entrant logprints. (recursion issues between assert/logging code) + if (fInLogPrint) + return; + fInLogPrint = true; + + if (LOGMSG_STANDARD == llv || + (LOGMSG_VERBOSE == llv && IsVerboseLogging()) +#ifdef DEBUG + || LOGMSG_TRACEONLY == llv +#endif + ) + { + va_list args; + va_start(args, fmt); + + LPCSTR szLogName = WcaGetLogName(); + if (szLogName[0] != 0) + StringCchPrintfA(szFmt, countof(szFmt), "%s: %s", szLogName, fmt); + else + StringCchCopyA(szFmt, countof(szFmt), fmt); + + StringCchVPrintfA(szBuf, countof(szBuf), szFmt, args); + va_end(args); + +#ifdef DEBUG + // always write to the log in debug +#else + if (llv == LOGMSG_STANDARD || (llv == LOGMSG_VERBOSE && IsVerboseLogging())) +#endif + { + PMSIHANDLE hrec = MsiCreateRecord(1); + + ::MsiRecordSetStringA(hrec, 0, szBuf); + // TODO: Recursion on failure. May not be safe to assert from here. + WcaProcessMessage(INSTALLMESSAGE_INFO, hrec); + } + +#if DEBUG + StringCchCatA(szBuf, countof(szBuf), "\n"); + OutputDebugStringA(szBuf); +#endif + } + + fInLogPrint = false; + return; +} + + +/******************************************************************** + WcaDisplayAssert() - called before Assert() dialog shows + + NOTE: writes the assert string to the MSI log +********************************************************************/ +extern "C" BOOL WcaDisplayAssert( + __in LPCSTR sz + ) +{ + WcaLog(LOGMSG_STANDARD, "Debug Assert Message: %s", sz); + return TRUE; +} + + +/******************************************************************** + WcaLogError() - called before ExitOnXXX() macro exists the function + + NOTE: writes the hresult and error string to the MSI log +********************************************************************/ +extern "C" void WcaLogError( + __in HRESULT hr, + __in LPCSTR szMessage, + ... + ) +{ + char szBuffer[LOG_BUFFER]; + va_list dots; + + va_start(dots, szMessage); + StringCchVPrintfA(szBuffer, countof(szBuffer), szMessage, dots); + va_end(dots); + + // log the message if using Wca common layer + if (WcaIsInitialized()) + WcaLog(LOGMSG_STANDARD, "Error 0x%x: %s", hr, szBuffer); +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcascript.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcascript.cpp new file mode 100644 index 0000000000..b0a55946f9 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcascript.cpp @@ -0,0 +1,447 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library CaScript functions +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + + +static HRESULT CaScriptFileName( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __out LPWSTR* pwzScriptName + ); + + +/******************************************************************** + WcaCaScriptCreateKey() - creates a unique script key for this + CustomAction. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptCreateKey( + __out LPWSTR* ppwzScriptKey + ) +{ + AssertSz(WcaIsInitialized(), "WcaInitialize() should have been called before calling this function."); + HRESULT hr = S_OK; + + hr = StrAllocStringAnsi(ppwzScriptKey, WcaGetLogName(), 0, CP_ACP); + ExitOnFailure(hr, "Failed to create script key."); + +LExit: + return hr; +} + + +/******************************************************************** + WcaCaScriptCreate() - creates the appropriate script for this + CustomAction Script Key. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptCreate( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __in BOOL fAppend, + __in WCA_CASCRIPT_HANDLE* phScript + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzScriptPath = NULL; + HANDLE hScriptFile = INVALID_HANDLE_VALUE; + + hr = CaScriptFileName(action, script, fImpersonated, wzScriptKey, &pwzScriptPath); + ExitOnFailure(hr, "Failed to calculate script file name."); + + hScriptFile = ::CreateFileW(pwzScriptPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, fAppend ? OPEN_ALWAYS : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (INVALID_HANDLE_VALUE == hScriptFile) + { + ExitWithLastError1(hr, "Failed to open CaScript: %S", pwzScriptPath); + } + + if (fAppend && INVALID_SET_FILE_POINTER == ::SetFilePointer(hScriptFile, 0, NULL, FILE_END)) + { + ExitWithLastError(hr, "Failed to seek to end of file."); + } + + *phScript = reinterpret_cast(MemAlloc(sizeof(WCA_CASCRIPT_STRUCT), TRUE)); + ExitOnNull(*phScript, hr, E_OUTOFMEMORY, "Failed to allocate space for cascript handle."); + + (*phScript)->pwzScriptPath = pwzScriptPath; + pwzScriptPath = NULL; + (*phScript)->hScriptFile = hScriptFile; + hScriptFile = INVALID_HANDLE_VALUE; + +LExit: + if (INVALID_HANDLE_VALUE != hScriptFile) + { + ::CloseHandle(hScriptFile); + } + + ReleaseStr(pwzScriptPath); + return hr; +} + + +/******************************************************************** + WcaCaScriptOpen() - opens the appropriate script for this CustomAction + Script Key. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptOpen( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __in WCA_CASCRIPT_HANDLE* phScript + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzScriptPath = NULL; + HANDLE hScriptFile = INVALID_HANDLE_VALUE; + + hr = CaScriptFileName(action, script, fImpersonated, wzScriptKey, &pwzScriptPath); + ExitOnFailure(hr, "Failed to calculate script file name."); + + hScriptFile = ::CreateFileW(pwzScriptPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (INVALID_HANDLE_VALUE == hScriptFile) + { + ExitWithLastError1(hr, "Failed to open CaScript: %S", pwzScriptPath); + } + + *phScript = reinterpret_cast(MemAlloc(sizeof(WCA_CASCRIPT_STRUCT), TRUE)); + ExitOnNull(*phScript, hr, E_OUTOFMEMORY, "Failed to allocate space for cascript handle."); + + (*phScript)->pwzScriptPath = pwzScriptPath; + pwzScriptPath = NULL; + (*phScript)->hScriptFile = hScriptFile; + hScriptFile = INVALID_HANDLE_VALUE; + +LExit: + if (INVALID_HANDLE_VALUE != hScriptFile) + { + ::CloseHandle(hScriptFile); + } + + ReleaseStr(pwzScriptPath); + return hr; +} + + +/******************************************************************** + WcaCaScriptClose() - closes an open script handle. + +********************************************************************/ +extern "C" void WIXAPI WcaCaScriptClose( + __in WCA_CASCRIPT_HANDLE hScript, + __in WCA_CASCRIPT_CLOSE closeOperation + ) +{ + if (hScript) + { + if (INVALID_HANDLE_VALUE != hScript->hScriptFile) + { + ::CloseHandle(hScript->hScriptFile); + } + + if (hScript->pwzScriptPath) + { + if (WCA_CASCRIPT_CLOSE_DELETE == closeOperation) + { + ::DeleteFileW(hScript->pwzScriptPath); + } + + StrFree(hScript->pwzScriptPath); + } + + MemFree(hScript); + } +} + + +/******************************************************************** + WcaCaScriptReadAsCustomActionData() - read the ca script into a format + that is useable by other CA data + functions. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptReadAsCustomActionData( + __in WCA_CASCRIPT_HANDLE hScript, + __out LPWSTR* ppwzCustomActionData + ) +{ + HRESULT hr = S_OK; + LARGE_INTEGER liScriptSize = { 0 }; + BYTE* pbData = NULL; + DWORD cbData = 0; + + if (!::GetFileSizeEx(hScript->hScriptFile, &liScriptSize)) + { + ExitWithLastError(hr, "Failed to get size of ca script file."); + } + + if (0 != liScriptSize.HighPart || 0 != (liScriptSize.LowPart % sizeof(WCHAR))) + { + hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + ExitOnFailure(hr, "Invalid data read from ca script."); + } + + cbData = liScriptSize.LowPart; + pbData = static_cast(MemAlloc(cbData, TRUE)); + ExitOnNull(pbData, hr, E_OUTOFMEMORY, "Failed to allocate memory to read in ca script."); + + if (INVALID_SET_FILE_POINTER == ::SetFilePointer(hScript->hScriptFile, 0, NULL, FILE_BEGIN)) + { + ExitWithLastError(hr, "Failed to reset to beginning of ca script."); + } + + DWORD cbTotalRead = 0; + DWORD cbRead = 0; + do + { + if (!::ReadFile(hScript->hScriptFile, pbData + cbTotalRead, cbData - cbTotalRead, &cbRead, NULL)) + { + ExitWithLastError(hr, "Failed to read from ca script."); + } + + cbTotalRead += cbRead; + } while (cbRead && cbTotalRead < cbData); + + if (cbTotalRead != cbData) + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "Failed to completely read ca script."); + } + + // Add one to the allocated space because the data stored in the script is not + // null terminated. After copying the memory over, we'll ensure the string is + // null terminated. + DWORD cchData = cbData / sizeof(WCHAR) + 1; + hr = StrAlloc(ppwzCustomActionData, cchData); + ExitOnFailure(hr, "Failed to copy ca script."); + + CopyMemory(*ppwzCustomActionData, pbData, cbData); + (*ppwzCustomActionData)[cchData - 1] = L'\0'; + +LExit: + ReleaseMem(pbData); + return hr; +} + + +/******************************************************************** + WcaCaScriptWriteString() - writes a string to the ca script. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptWriteString( + __in WCA_CASCRIPT_HANDLE hScript, + __in LPCWSTR wzValue + ) +{ + HRESULT hr = S_OK; + DWORD cbFile = 0; + DWORD cbWrite = 0; + DWORD cbTotalWritten = 0; + WCHAR delim[] = { MAGIC_MULTISZ_DELIM }; // magic char followed by NULL terminator + + cbFile = ::SetFilePointer(hScript->hScriptFile, 0, NULL, FILE_END); + if (INVALID_SET_FILE_POINTER == cbFile) + { + ExitWithLastError(hr, "Failed to move file pointer to end of file."); + } + + // If there is existing data in the file, append on the magic delimeter + // before adding our new data on the end of the file. + if (0 < cbFile) + { + cbWrite = sizeof(delim); + cbTotalWritten = 0; + while (cbTotalWritten < cbWrite) + { + DWORD cbWritten = 0; + if (!::WriteFile(hScript->hScriptFile, reinterpret_cast(delim) + cbTotalWritten, cbWrite - cbTotalWritten, &cbWritten, NULL)) + { + ExitWithLastError(hr, "Failed to write data to ca script."); + } + + cbTotalWritten += cbWritten; + } + } + + cbWrite = lstrlenW(wzValue) * sizeof(WCHAR); + cbTotalWritten = 0; + while (cbTotalWritten < cbWrite) + { + DWORD cbWritten = 0; + if (!::WriteFile(hScript->hScriptFile, reinterpret_cast(wzValue) + cbTotalWritten, cbWrite - cbTotalWritten, &cbWritten, NULL)) + { + ExitWithLastError(hr, "Failed to write data to ca script."); + } + + cbTotalWritten += cbWritten; + } + +LExit: + return hr; +} + + +/******************************************************************** + WcaCaScriptWriteNumber() - writes a number to the ca script. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptWriteNumber( + __in WCA_CASCRIPT_HANDLE hScript, + __in DWORD dwValue + ) +{ + HRESULT hr = S_OK; + WCHAR wzBuffer[13] = { 0 }; + + hr = ::StringCchPrintfW(wzBuffer, countof(wzBuffer), L"%u", dwValue); + ExitOnFailure(hr, "Failed to convert number into string."); + + hr = WcaCaScriptWriteString(hScript, wzBuffer); + ExitOnFailure(hr, "Failed to write number to script."); + +LExit: + return hr; +} + + +/******************************************************************** + WcaCaScriptFlush() - best effort function to get script written to + disk. + +********************************************************************/ +extern "C" void WIXAPI WcaCaScriptFlush( + __in WCA_CASCRIPT_HANDLE hScript + ) +{ + ::FlushFileBuffers(hScript->hScriptFile); +} + + +/******************************************************************** + WcaCaScriptCleanup() - best effort clean-up of any cascripts left + over from this install/uninstall. + +********************************************************************/ +extern "C" void WIXAPI WcaCaScriptCleanup( + __in LPCWSTR wzProductCode, + __in BOOL fImpersonated + ) +{ + HRESULT hr = S_OK; + WCHAR wzTempPath[MAX_PATH]; + LPWSTR pwzWildCardPath = NULL; + WIN32_FIND_DATAW fd = { 0 }; + HANDLE hff = INVALID_HANDLE_VALUE; + LPWSTR pwzDeletePath = NULL; + + if (fImpersonated) + { + if (!::GetTempPathW(countof(wzTempPath), wzTempPath)) + { + ExitWithLastError(hr, "Failed to get temp path."); + } + } + else + { + if (!::GetWindowsDirectoryW(wzTempPath, countof(wzTempPath))) + { + ExitWithLastError(hr, "Failed to get windows path."); + } + + hr = ::StringCchCatW(wzTempPath, countof(wzTempPath), L"\\Installer\\"); + ExitOnFailure(hr, "Failed to concat Installer directory on windows path string."); + } + + hr = StrAllocFormatted(&pwzWildCardPath, L"%swix%s.*.???", wzTempPath, wzProductCode); + ExitOnFailure(hr, "Failed to allocate wildcard path to ca scripts."); + + hff = ::FindFirstFileW(pwzWildCardPath, &fd); + if (INVALID_HANDLE_VALUE == hff) + { + ExitWithLastError1(hr, "Failed to find files with pattern: %S", pwzWildCardPath); + } + + do + { + hr = StrAllocFormatted(&pwzDeletePath, L"%s%s", wzTempPath, fd.cFileName); + if (SUCCEEDED(hr)) + { + if (!::DeleteFileW(pwzDeletePath)) + { + DWORD er = ::GetLastError(); + WcaLog(LOGMSG_VERBOSE, "Failed to clean up CAScript file: %S, er: %d", fd.cFileName, er); + } + } + else + { + WcaLog(LOGMSG_VERBOSE, "Failed to allocate path to clean up CAScript file: %S, hr: 0x%x", fd.cFileName, hr); + } + } while(::FindNextFileW(hff, &fd)); + +LExit: + if (INVALID_HANDLE_VALUE == hff) + { + ::FindClose(hff); + } + + ReleaseStr(pwzDeletePath); + ReleaseStr(pwzWildCardPath); + return; +} + + +static HRESULT CaScriptFileName( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __out LPWSTR* ppwzScriptName + ) +{ + HRESULT hr = S_OK; + WCHAR wzTempPath[MAX_PATH]; + LPWSTR pwzProductCode = NULL; + WCHAR chInstallOrUninstall = action == WCA_ACTION_INSTALL ? L'i' : L'u'; + WCHAR chScheduledOrRollback = script == WCA_CASCRIPT_SCHEDULED ? L's' : L'r'; + WCHAR chUserOrMachine = fImpersonated ? L'u' : L'm'; + + if (fImpersonated) + { + if (!::GetTempPathW(countof(wzTempPath), wzTempPath)) + { + ExitWithLastError(hr, "Failed to get temp path."); + } + } + else + { + if (!::GetWindowsDirectoryW(wzTempPath, countof(wzTempPath))) + { + ExitWithLastError(hr, "Failed to get windows path."); + } + + hr = ::StringCchCatW(wzTempPath, countof(wzTempPath), L"\\Installer\\"); + ExitOnFailure(hr, "Failed to concat Installer directory on windows path string."); + } + + hr = WcaGetProperty(L"ProductCode", &pwzProductCode); + ExitOnFailure(hr, "Failed to get ProductCode."); + + hr = StrAllocFormatted(ppwzScriptName, L"%swix%s.%s.%c%c%c", wzTempPath, pwzProductCode, wzScriptKey, chScheduledOrRollback, chUserOrMachine, chInstallOrUninstall); + ExitOnFailure(hr, "Failed to allocate path to ca script."); + +LExit: + ReleaseStr(pwzProductCode); + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.cpp new file mode 100644 index 0000000000..5f7bbda74d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.cpp @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library. +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + +// globals +HMODULE g_hInstCADLL; + +// statics +static BOOL s_fInitialized; +static MSIHANDLE s_hInstall; +static MSIHANDLE s_hDatabase; +static char s_szCustomActionLogName[32]; +static UINT s_iRetVal; + + +/******************************************************************** + WcaGlobalInitialize() - initializes the Wca library, should be + called once per custom action Dll during + DllMain on DLL_PROCESS_ATTACH + +********************************************************************/ +extern "C" void WcaGlobalInitialize( + __in HINSTANCE hInst + ) +{ + g_hInstCADLL = hInst; + MemInitialize(); + + AssertSetModule(g_hInstCADLL); + AssertSetDisplayFunction(WcaDisplayAssert); +} + + +/******************************************************************** + WcaGlobalFinalize() - finalizes the Wca library, should be the + called once per custom action Dll during + DllMain on DLL_PROCESS_DETACH + +********************************************************************/ +extern "C" void WcaGlobalFinalize() +{ +#ifdef DEBUG + if (WcaIsInitialized()) + { + CHAR szBuf[2048]; + StringCchPrintfA(szBuf, countof(szBuf), "CustomAction %s called WcaInitialize() but not WcaTerminate()", WcaGetLogName()); + + AssertSz(FALSE, szBuf); + } +#endif + MemUninitialize(); + g_hInstCADLL = NULL; +} + + +/******************************************************************** + WcaInitialize() - initializes the Wca framework, should be the first + thing called by all CustomActions + +********************************************************************/ +extern "C" HRESULT WcaInitialize( + __in MSIHANDLE hInstall, + __in const char* szCustomActionLogName + ) +{ + // these statics should be called once per CustomAction invocation. + // Darwin does doesn't preserve DLL state across CustomAction calls so + // these should always be initialized to NULL. If that behavior changes + // we would need to do a careful review of all of our module/global data. + AssertSz(!s_fInitialized, "WcaInitialize() should only be called once per CustomAction"); + Assert(NULL == s_hInstall); + Assert(NULL == s_hDatabase); + Assert(0 == *s_szCustomActionLogName); + + HRESULT hr = S_OK; + + s_fInitialized = TRUE; + s_iRetVal = ERROR_SUCCESS; // assume all will go well + + s_hInstall = hInstall; + s_hDatabase = ::MsiGetActiveDatabase(s_hInstall); // may return null if deferred CustomAction + + hr = ::StringCchCopyA(s_szCustomActionLogName, countof(s_szCustomActionLogName), szCustomActionLogName); + ExitOnFailure1(hr, "Failed to copy CustomAction log name: %s", szCustomActionLogName); + + Assert(s_hInstall); +LExit: + if (FAILED(hr)) + { + if (s_hDatabase) + { + ::MsiCloseHandle(s_hDatabase); + s_hDatabase = NULL; + } + + s_hInstall = NULL; + s_fInitialized = FALSE; + } + + return hr; +} + + +/******************************************************************** + WcaFinalize() - cleans up after the Wca framework, should be the last + thing called by all CustomActions + +********************************************************************/ +extern "C" UINT WcaFinalize( + __in UINT iReturnValue + ) +{ + // clean up after our initialization + if (s_hDatabase) + { + ::MsiCloseHandle(s_hDatabase); + s_hDatabase = NULL; + } + + s_hInstall = NULL; + s_fInitialized = FALSE; + + // if no error occurred during the processing of the CusotmAction return the passed in return value + // otherwise return the previous failure + return (ERROR_SUCCESS == s_iRetVal) ? iReturnValue : s_iRetVal; +} + + +/******************************************************************** + WcaIsInitialized() - determines if WcaInitialize() has been called + +********************************************************************/ +extern "C" BOOL WcaIsInitialized() +{ + return s_fInitialized; +} + + +/******************************************************************** + WcaGetInstallHandle() - gets the handle to the active install session + +********************************************************************/ +extern "C" MSIHANDLE WcaGetInstallHandle() +{ + AssertSz(s_hInstall, "WcaInitialize() should be called before attempting to access the install handle."); + return s_hInstall; +} + + +/******************************************************************** + WcaGetDatabaseHandle() - gets the handle to the active database + + NOTE: this function can only be used in immediate CustomActions. + Deferred CustomActions do not have access to the active + database. +********************************************************************/ +extern "C" MSIHANDLE WcaGetDatabaseHandle() +{ + AssertSz(s_hDatabase, "WcaInitialize() should be called before attempting to access the install handle. Also note that deferred CustomActions do not have access to the active database."); + return s_hDatabase; +} + + +/******************************************************************** + WcaGetLogName() - gets the name of the CustomAction used in logging + +********************************************************************/ +extern "C" const char* WcaGetLogName() +{ + return s_szCustomActionLogName; +} + + +/******************************************************************** + WcaSetReturnValue() - sets the value to return from the CustomAction + +********************************************************************/ +extern "C" void WcaSetReturnValue( + __in UINT iReturnValue + ) +{ + s_iRetVal = iReturnValue; +} + + +/******************************************************************** + WcaCancelDetected() - determines if the user has canceled yet + + NOTE: returns true when WcaSetReturnValue() is set to ERROR_INSTALL_USEREXIT +********************************************************************/ +extern "C" BOOL WcaCancelDetected() +{ + return ERROR_INSTALL_USEREXIT == s_iRetVal; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.h new file mode 100644 index 0000000000..8265e27735 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.h @@ -0,0 +1,344 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library. +// +//------------------------------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define WIXAPI __stdcall +#define ExitTrace WcaLogError +#define ExitTrace1 WcaLogError +#define ExitTrace2 WcaLogError +#define ExitTrace3 WcaLogError + +#include "dutil.h" + +#define MessageExitOnLastError(x, e, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace(x, "%s", s); WcaErrorMessage(e, x, MB_OK, 0); goto LExit; } } +#define MessageExitOnLastError1(x, e, f, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace1(x, f, s); WcaErrorMessage(e, x, MB_OK, 1, s); goto LExit; } } + +#define MessageExitOnFailure(x, e, s) if (FAILED(x)) { ExitTrace(x, "%s", s); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 0); goto LExit; } +#define MessageExitOnFailure1(x, e, f, s) if (FAILED(x)) { ExitTrace1(x, f, s); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 1, s); goto LExit; } +#define MessageExitOnFailure2(x, e, f, s, t) if (FAILED(x)) { ExitTrace2(x, f, s, t); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 2, s, t); goto LExit; } +#define MessageExitOnFailure3(x, e, f, s, t, u) if (FAILED(x)) { ExitTrace2(x, f, s, t, u); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 3, s, t, u); goto LExit; } + +#define MessageExitOnNullWithLastError(p, x, e, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, "%s", s); WcaErrorMessage(e, x, MB_OK, 0); goto LExit; } +#define MessageExitOnNullWithLastError1(p, x, e, f, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, f, s); WcaErrorMessage(e, x, MB_OK, 1, s); goto LExit; } +#define MessageExitOnNullWithLastError2(p, x, e, f, s, t) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, f, s, t); WcaErrorMessage(e, x, MB_OK, 2, s, t); goto LExit; } + +#define MAX_DARWIN_KEY 73 +#define MAX_DARWIN_COLUMN 255 + +// Generic action enum. +enum WCA_ACTION +{ + WCA_ACTION_NONE, + WCA_ACTION_INSTALL, + WCA_ACTION_UNINSTALL, +}; + +enum WCA_CASCRIPT +{ + WCA_CASCRIPT_SCHEDULED, + WCA_CASCRIPT_ROLLBACK, +}; + +enum WCA_CASCRIPT_CLOSE +{ + WCA_CASCRIPT_CLOSE_PRESERVE, + WCA_CASCRIPT_CLOSE_DELETE, +}; + +typedef struct WCA_CASCRIPT_STRUCT +{ + LPWSTR pwzScriptPath; + HANDLE hScriptFile; +} *WCA_CASCRIPT_HANDLE; + +void WIXAPI WcaGlobalInitialize( + __in HINSTANCE hInst + ); +void WIXAPI WcaGlobalFinalize(); + +HRESULT WIXAPI WcaInitialize( + __in MSIHANDLE hInstall, + __in const char* szCustomActionLogName + ); +UINT WIXAPI WcaFinalize( + __in UINT iReturnValue + ); +BOOL WIXAPI WcaIsInitialized(); + +MSIHANDLE WIXAPI WcaGetInstallHandle(); +MSIHANDLE WIXAPI WcaGetDatabaseHandle(); + +const char* WIXAPI WcaGetLogName(); + +void WIXAPI WcaSetReturnValue( + __in UINT iReturnValue + ); +BOOL WIXAPI WcaCancelDetected(); + +const int LOG_BUFFER = 2048; +enum LOGLEVEL +{ + LOGMSG_TRACEONLY, // Never written to the log file (except in DEBUG builds) + LOGMSG_VERBOSE, // Written to log when LOGVERBOSE + LOGMSG_STANDARD // Written to log whenever informational logging is enabled +}; + +void __cdecl WcaLog( + __in LOGLEVEL llv, + __in const char* fmt, ... + ); +BOOL WIXAPI WcaDisplayAssert( + __in LPCSTR sz + ); +void __cdecl WcaLogError( + __in HRESULT hr, + __in LPCSTR szMessage, + ... + ); + + +UINT WIXAPI WcaProcessMessage( + __in INSTALLMESSAGE eMessageType, + __in MSIHANDLE hRecord + ); +UINT __cdecl WcaErrorMessage( + __in int iError, + __in HRESULT hrError, + __in UINT uiType, + __in DWORD cArgs, + ... + ); +HRESULT WIXAPI WcaProgressMessage( + __in UINT uiCost, + __in BOOL fExtendProgressBar + ); + +BOOL WIXAPI WcaIsInstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ); +BOOL WIXAPI WcaIsReInstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ); +BOOL WIXAPI WcaIsUninstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ); + +HRESULT WIXAPI WcaSetComponentState( + __in LPCWSTR wzComponent, + __in INSTALLSTATE isState + ); + +HRESULT WIXAPI WcaTableExists( + __in LPCWSTR wzTable + ); + +HRESULT WIXAPI WcaOpenView( + __in LPCWSTR wzSql, + __out MSIHANDLE* phView + ); +HRESULT WIXAPI WcaExecuteView( + __in MSIHANDLE hView, + __in MSIHANDLE hRec + ); +HRESULT WIXAPI WcaOpenExecuteView( + __in LPCWSTR wzSql, + __out MSIHANDLE* phView + ); +HRESULT WIXAPI WcaFetchRecord( + __in MSIHANDLE hView, + __out MSIHANDLE* phRec + ); +HRESULT WIXAPI WcaFetchSingleRecord( + __in MSIHANDLE hView, + __out MSIHANDLE* phRec + ); + +HRESULT WIXAPI WcaGetProperty( + __in LPCWSTR wzProperty, + __inout LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaGetFormattedProperty( + __in LPCWSTR wzProperty, + __out LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaGetFormattedString( + __in LPCWSTR wzString, + __out LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaGetIntProperty( + __in LPCWSTR wzProperty, + __inout int* piData + ); +HRESULT WIXAPI WcaGetTargetPath( + __in LPCWSTR wzFolder, + __out LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaSetProperty( + __in LPCWSTR wzPropertyName, + __in LPCWSTR wzPropertyValue + ); +HRESULT WIXAPI WcaSetIntProperty( + __in LPCWSTR wzPropertyName, + __in int nPropertyValue + ); +BOOL WIXAPI WcaIsPropertySet( + __in LPCSTR szProperty + ); + +HRESULT WIXAPI WcaGetRecordInteger( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout int* piData + ); +HRESULT WIXAPI WcaGetRecordString( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaGetRecordFormattedString( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout LPWSTR* ppwzData + ); + +HRESULT WIXAPI WcaAllocStream(__inout BYTE** ppbData, __in DWORD cbData); +HRESULT WIXAPI WcaFreeStream(__in BYTE* pbData); + +HRESULT WIXAPI WcaGetRecordStream( + __in MSIHANDLE hRecBinary, + __in UINT uiField, + __inout BYTE** ppbData, + __inout DWORD* pcbData + ); +HRESULT WIXAPI WcaSetRecordString( + __in MSIHANDLE hRec, + __in UINT uiField, + __in LPCWSTR wzData + ); +HRESULT WIXAPI WcaSetRecordInteger( + __in MSIHANDLE hRec, + __in UINT uiField, + __in int iValue + ); + +HRESULT WIXAPI WcaDoDeferredAction( + __in LPCWSTR wzAction, + __in LPCWSTR wzCustomActionData, + __in UINT uiCost + ); +DWORD WIXAPI WcaCountOfCustomActionDataRecords( + __in LPCWSTR wzData + ); +HRESULT WIXAPI WcaReadStringFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __inout LPWSTR* ppwzString + ); +HRESULT WIXAPI WcaReadIntegerFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __inout int* piResult + ); +HRESULT WIXAPI WcaReadStreamFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __out BYTE** ppbData, + __out DWORD_PTR* pcbData + ); +HRESULT WIXAPI WcaWriteStringToCaData( + __in LPCWSTR wzString, + __inout LPWSTR* ppwzCustomActionData + ); +HRESULT WIXAPI WcaWriteIntegerToCaData( + __in int i, + __inout LPWSTR* ppwzCustomActionData + ); +HRESULT WIXAPI WcaWriteStreamToCaData( + __in_bcount(cbData) const BYTE* pbData, + __in DWORD cbData, + __inout LPWSTR* ppwzCustomActionData + ); + +HRESULT __cdecl WcaAddTempRecord( + __inout MSIHANDLE* phTableView, + __inout MSIHANDLE* phColumns, + __in LPCWSTR wzTable, + __in UINT uiUniquifyColumn, + __in UINT cColumns, + ... + ); + +HRESULT WIXAPI WcaDumpTable( + __in LPCWSTR wzTable + ); + + +HRESULT WIXAPI WcaCaScriptCreateKey( + __out LPWSTR* ppwzScriptKey + ); + +HRESULT WIXAPI WcaCaScriptCreate( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __in BOOL fAppend, + __out WCA_CASCRIPT_HANDLE* phScript + ); + +HRESULT WIXAPI WcaCaScriptOpen( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __out WCA_CASCRIPT_HANDLE* phScript + ); + +void WIXAPI WcaCaScriptClose( + __in WCA_CASCRIPT_HANDLE hScript, + __in WCA_CASCRIPT_CLOSE closeOperation + ); + +HRESULT WIXAPI WcaCaScriptReadAsCustomActionData( + __in WCA_CASCRIPT_HANDLE hScript, + __out LPWSTR* ppwzCustomActionData + ); + +HRESULT WIXAPI WcaCaScriptWriteString( + __in WCA_CASCRIPT_HANDLE hScript, + __in LPCWSTR wzValue + ); + +HRESULT WIXAPI WcaCaScriptWriteNumber( + __in WCA_CASCRIPT_HANDLE hScript, + __in DWORD dwValue + ); + +void WIXAPI WcaCaScriptFlush( + __in WCA_CASCRIPT_HANDLE hScript + ); + +void WIXAPI WcaCaScriptCleanup( + __in LPCWSTR wzProductCode, + __in BOOL fImpersonated + ); + + +HRESULT QuietExec( + __in LPWSTR wzCommand, + __in DWORD dwTimeout + ); + +#ifdef __cplusplus +} +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcawrap.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcawrap.cpp new file mode 100644 index 0000000000..490a5d6713 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcawrap.cpp @@ -0,0 +1,1419 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library wrappers for MSI API +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + + +/******************************************************************** + WcaProcessMessage() - sends a message from the CustomAction + +********************************************************************/ +extern "C" UINT WcaProcessMessage( + __in INSTALLMESSAGE eMessageType, + __in MSIHANDLE hRecord + ) +{ + UINT er = ::MsiProcessMessage(WcaGetInstallHandle(), eMessageType, hRecord); + if (ERROR_INSTALL_USEREXIT == er || IDCANCEL == er) + WcaSetReturnValue(ERROR_INSTALL_USEREXIT); + + return er; +} + + +/******************************************************************** + WcaErrorMessage() - sends an error message from the CustomAction using + the Error table + + NOTE: Any and all var_args (...) must be WCHAR* +********************************************************************/ +extern "C" UINT WcaErrorMessage( + __in int iError, + __in HRESULT hrError, + __in UINT uiType, + __in DWORD cArgs, + ... + ) +{ + UINT er; + MSIHANDLE hRec = NULL; + va_list args; + + uiType |= INSTALLMESSAGE_ERROR; // ensure error type is set + hRec = ::MsiCreateRecord(cArgs + 2); + if (!hRec) + { + er = ERROR_OUTOFMEMORY; + ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to create record when sending error message"); + } + + er = ::MsiRecordSetInteger(hRec, 1, iError); + ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to set error code into error message"); + + er = ::MsiRecordSetInteger(hRec, 2, hrError); + ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to set hresult code into error message"); + + va_start(args, cArgs); + for (DWORD i = 0; i < cArgs; i++) + { + er = ::MsiRecordSetStringW(hRec, i + 3, va_arg(args, WCHAR*)); + ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to set string string into error message"); + } + va_end(args); + + er = WcaProcessMessage(static_cast(uiType), hRec); +LExit: + if (hRec) + ::MsiCloseHandle(hRec); + + return er; +} + + +/******************************************************************** + WcaProgressMessage() - extends the progress bar or sends a progress + update from the CustomAction + +********************************************************************/ +extern "C" HRESULT WcaProgressMessage( + __in UINT uiCost, + __in BOOL fExtendProgressBar + ) +{ + static BOOL fExplicitProgressMessages = FALSE; + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + MSIHANDLE hRec = ::MsiCreateRecord(3); + + // if aren't extending the progress bar and we haven't switched into explicit message mode + if (!fExtendProgressBar && !fExplicitProgressMessages) + { + AssertSz(::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_SCHEDULED) || + ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_COMMIT) || + ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK), "can only send progress bar messages in a deferred CustomAction"); + + // tell Darwin to use explicit progress messages + ::MsiRecordSetInteger(hRec, 1, 1); + ::MsiRecordSetInteger(hRec, 2, 1); + ::MsiRecordSetInteger(hRec, 3, 0); + + er = WcaProcessMessage(INSTALLMESSAGE_PROGRESS, hRec); + if (0 == er || IDOK == er || IDYES == er) + hr = S_OK; + else if (IDABORT == er || IDCANCEL == er) + { + WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit + ExitFunction1(hr = S_FALSE); + } + else + hr = E_UNEXPECTED; + ExitOnFailure(hr, "failed to tell Darwin to use explicit progress messages"); + + fExplicitProgressMessages = TRUE; + } +#if DEBUG + else if (fExtendProgressBar) // if we are extending the progress bar, make sure we're not deferred + { + AssertSz(!::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_SCHEDULED), "cannot add ticks to progress bar length from deferred CustomAction"); + } +#endif + + // send the progress message + ::MsiRecordSetInteger(hRec, 1, (fExtendProgressBar) ? 3 : 2); + ::MsiRecordSetInteger(hRec, 2, uiCost); + ::MsiRecordSetInteger(hRec, 3, 0); + + er = WcaProcessMessage(INSTALLMESSAGE_PROGRESS, hRec); + if (0 == er || IDOK == er || IDYES == er) + { + hr = S_OK; + } + else if (IDABORT == er || IDCANCEL == er) + { + WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit + hr = S_FALSE; + } + else + hr = E_UNEXPECTED; + +LExit: + if (hRec) + ::MsiCloseHandle(hRec); + + return hr; +} + + +/******************************************************************** + WcaIsInstalling() - determines if a pair of installstates means install + +********************************************************************/ +extern "C" BOOL WcaIsInstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ) +{ + return (INSTALLSTATE_LOCAL == isAction || + INSTALLSTATE_SOURCE == isAction || + (INSTALLSTATE_DEFAULT == isAction && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled))); +} + +/******************************************************************** + WcaIsReInstalling() - determines if a pair of installstates means install + +********************************************************************/ +extern "C" BOOL WcaIsReInstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ) +{ + return ((INSTALLSTATE_LOCAL == isAction || + INSTALLSTATE_SOURCE == isAction || + INSTALLSTATE_DEFAULT == isAction) && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled)); +} + + +/******************************************************************** + WcaIsUninstalling() - determines if a pair of installstates means uninstall + +********************************************************************/ +extern "C" BOOL WcaIsUninstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ) +{ + return ((INSTALLSTATE_ABSENT == isAction || + INSTALLSTATE_REMOVED == isAction) && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled)); +} + + +/******************************************************************** + WcaSetComponentState() - sets the install state of a Component + +********************************************************************/ +extern "C" HRESULT WcaSetComponentState( + __in LPCWSTR wzComponent, + __in INSTALLSTATE isState + ) +{ + UINT er = ::MsiSetComponentStateW(WcaGetInstallHandle(), wzComponent, isState); + if (ERROR_INSTALL_USEREXIT == er) + WcaSetReturnValue(er); + + return HRESULT_FROM_WIN32(er); +} + + +/******************************************************************** + WcaTableExists() - determines if installing database contains a table + +********************************************************************/ +extern "C" HRESULT WcaTableExists( + __in LPCWSTR wzTable + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + +// NOTE: The following line of commented out code should work in a +// CustomAction but does not in Windows Installer v1.1 + // er = ::MsiDatabaseIsTablePersistentW(hDatabase, wzTable); + + // a "most elegant" workaround a Darwin v1.1 bug + PMSIHANDLE hRec; + er = ::MsiDatabaseGetPrimaryKeysW(WcaGetDatabaseHandle(), wzTable, &hRec); + + if (ERROR_SUCCESS == er) + hr = S_OK; + else if (ERROR_INVALID_TABLE == er) + hr = S_FALSE; + else + hr = E_FAIL; + Assert(SUCCEEDED(hr)); + + return hr; +} + + +/******************************************************************** + WcaOpenView() - opens a view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaOpenView( + __in LPCWSTR wzSql, + __out MSIHANDLE* phView + ) +{ + if (!wzSql || !*wzSql|| !phView) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiDatabaseOpenViewW(WcaGetDatabaseHandle(), wzSql, phView); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to open view on database with SQL: %S", wzSql); + +LExit: + return hr; +} + + +/******************************************************************** + WcaExecuteView() - executes a parameterized open view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaExecuteView( + __in MSIHANDLE hView, + __in MSIHANDLE hRec + ) +{ + if (!hView) + return E_INVALIDARG; + AssertSz(hRec, "Use WcaOpenExecuteView() if you don't need to pass in a record"); + + HRESULT hr = S_OK; + UINT er = ::MsiViewExecute(hView, hRec); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to execute view"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaOpenExecuteView() - opens and executes a view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaOpenExecuteView( + __in LPCWSTR wzSql, + __out MSIHANDLE* phView + ) +{ + if (!wzSql || !*wzSql|| !phView) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiDatabaseOpenViewW(WcaGetDatabaseHandle(), wzSql, phView); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to open view on database"); + + er = ::MsiViewExecute(*phView, NULL); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to execute view"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaFetchRecord() - gets the next record from a view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaFetchRecord( + __in MSIHANDLE hView, + __out MSIHANDLE* phRec + ) +{ + if (!hView|| !phRec) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiViewFetch(hView, phRec); + hr = HRESULT_FROM_WIN32(er); + if (FAILED(hr) && E_NOMOREITEMS != hr) + ExitOnFailure(hr, "failed to fetch record from view"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaFetchSingleRecord() - gets a single record from a view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaFetchSingleRecord( + __in MSIHANDLE hView, + __out MSIHANDLE* phRec + ) +{ + if (!hView|| !phRec) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiViewFetch(hView, phRec); + if (ERROR_NO_MORE_ITEMS == er) + hr = S_FALSE; + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to fetch single record from view"); + +#ifdef DEBUG // only do this in debug to verify that a single record was returned + MSIHANDLE hRecTest; + er = ::MsiViewFetch(hView, &hRecTest); + AssertSz(ERROR_NO_MORE_ITEMS == er && NULL == hRecTest, "WcaSingleFetch() did not fetch a single record"); + ::MsiCloseHandle(hRecTest); +#endif + +LExit: + return hr; +} + + +/******************************************************************** + WcaGetProperty - gets a string property value from the active install + +********************************************************************/ +extern "C" HRESULT WcaGetProperty( + __in LPCWSTR wzProperty, + __inout LPWSTR* ppwzData + ) +{ + if (!wzProperty || !*wzProperty || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + DWORD_PTR cch = 0; + + if (!*ppwzData) + { + er = ::MsiGetPropertyW(WcaGetInstallHandle(), wzProperty, L"", (DWORD *)&cch); + if (ERROR_MORE_DATA == er || ERROR_SUCCESS == er) + { + hr = StrAlloc(ppwzData, ++cch); + } + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to allocate string for Property '%S'", wzProperty); + } + else + { + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "Failed to get previous size of property data string."); + } + + er = ::MsiGetPropertyW(WcaGetInstallHandle(), wzProperty, *ppwzData, (DWORD *)&cch); + if (ERROR_MORE_DATA == er) + { + Assert(*ppwzData); + hr = StrAlloc(ppwzData, ++cch); + ExitOnFailure1(hr, "Failed to allocate string for Property '%S'", wzProperty); + + er = ::MsiGetPropertyW(WcaGetInstallHandle(), wzProperty, *ppwzData, (DWORD *)&cch); + } + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to get data for property '%S'", wzProperty); + +LExit: + return hr; +} + + +/******************************************************************** + WcaGetFormattedProperty - gets a formatted string property value from + the active install + +********************************************************************/ +extern "C" HRESULT WcaGetFormattedProperty( + __in LPCWSTR wzProperty, + __out LPWSTR* ppwzData + ) +{ + if (!wzProperty || !*wzProperty || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + LPWSTR pwzPropertyValue = NULL; + + + hr = WcaGetProperty(wzProperty, &pwzPropertyValue); + ExitOnFailure1(hr, "failed to get %S", wzProperty); + + hr = WcaGetFormattedString(pwzPropertyValue, ppwzData); + ExitOnFailure2(hr, "failed to get formatted value for property: '%S' with value: '%S'", wzProperty, pwzPropertyValue); + +LExit: + ReleaseStr(pwzPropertyValue); + return hr; +} + + +/******************************************************************** + WcaGetFormattedString - gets a formatted string value from + the active install + +********************************************************************/ +extern "C" HRESULT WcaGetFormattedString( + __in LPCWSTR wzString, + __out LPWSTR* ppwzData + ) +{ + if (!wzString || !*wzString || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hRecord = ::MsiCreateRecord(1); + DWORD_PTR cch = 0; + + er = ::MsiRecordSetStringW(hRecord, 0, wzString); + ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "Failed to set record field 0 with '%S'", wzString); + + if (!*ppwzData) + { + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecord, L"", (DWORD *)&cch); + if (ERROR_MORE_DATA == er || ERROR_SUCCESS == er) + { + hr = StrAlloc(ppwzData, ++cch); + } + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to allocate string for formatted string: '%S'", wzString); + } + else + { + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "Failed to get previous size of property data string"); + } + + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecord, *ppwzData, (DWORD *)&cch); + if (ERROR_MORE_DATA == er) + { + hr = StrAlloc(ppwzData, ++cch); + ExitOnFailure1(hr, "Failed to allocate string for formatted string: '%S'", wzString); + + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecord, *ppwzData, (DWORD *)&cch); + } + ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "Failed to get formatted string: '%S'", wzString); + +LExit: + return hr; +} + + +/******************************************************************** + WcaGetIntProperty - gets an integer property value from the active install + +********************************************************************/ +extern "C" HRESULT WcaGetIntProperty( + __in LPCWSTR wzProperty, + __inout int* piData + ) +{ + if (!piData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er; + + WCHAR wzValue[32]; + DWORD cch = countof(wzValue) - 1; + + er = ::MsiGetPropertyW(WcaGetInstallHandle(), wzProperty, wzValue, &cch); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to get data for property '%S'", wzProperty); + + *piData = wcstol(wzValue, NULL, 10); + +LExit: + return hr; +} + + +/******************************************************************** + WcaGetTargetPath - gets the target path for a specified folder + +********************************************************************/ +extern "C" HRESULT WcaGetTargetPath( + __in LPCWSTR wzFolder, + __out LPWSTR* ppwzData + ) +{ + if (!wzFolder || !*wzFolder || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + + UINT er = ERROR_SUCCESS; + DWORD_PTR cch = 0; + + if (!*ppwzData) + { + er = ::MsiGetTargetPathW(WcaGetInstallHandle(), wzFolder, L"", (DWORD*)&cch); + if (ERROR_MORE_DATA == er || ERROR_SUCCESS == er) + { + cch++; //Add one for the null terminator + hr = StrAlloc(ppwzData, cch); + } + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to allocate string for target path of folder: '%S'", wzFolder); + } + else + { + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "Failed to get previous size of string"); + } + + er = ::MsiGetTargetPathW(WcaGetInstallHandle(), wzFolder, *ppwzData, (DWORD*)&cch); + if (ERROR_MORE_DATA == er) + { + cch++; + hr = StrAlloc(ppwzData, cch); + ExitOnFailure1(hr, "Failed to allocate string for target path of folder: '%S'", wzFolder); + + er = ::MsiGetTargetPathW(WcaGetInstallHandle(), wzFolder, *ppwzData, (DWORD*)&cch); + } + ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "Failed to get target path for folder '%S'", wzFolder); + +LExit: + return hr; +} + + +/******************************************************************** + WcaSetProperty - sets a string property value in the active install + +********************************************************************/ +extern "C" HRESULT WcaSetProperty( + __in LPCWSTR wzPropertyName, + __in LPCWSTR wzPropertyValue + ) +{ + if (!wzPropertyName || !*wzPropertyName || !wzPropertyValue) + return E_INVALIDARG; + + UINT er = ::MsiSetPropertyW(WcaGetInstallHandle(), wzPropertyName, wzPropertyValue); + HRESULT hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to set property: %S", wzPropertyName); + +LExit: + return hr; +} + + +/******************************************************************** + WcaSetIntProperty - sets a integer property value in the active install + +********************************************************************/ +extern "C" HRESULT WcaSetIntProperty( + __in LPCWSTR wzPropertyName, + __in int nPropertyValue + ) +{ + if (!wzPropertyName || !*wzPropertyName) + return E_INVALIDARG; + + // 12 characters should be enough for a 32-bit int: 10 digits, 1 sign, 1 null + WCHAR wzPropertyValue[13]; + HRESULT hr = StringCchPrintfW(wzPropertyValue, countof(wzPropertyValue), L"%d", nPropertyValue); + ExitOnFailure1(hr, "failed to convert into string property value: %d", nPropertyValue); + + UINT er = ::MsiSetPropertyW(WcaGetInstallHandle(), wzPropertyName, wzPropertyValue); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to set property: %S", wzPropertyName); + +LExit: + return hr; +} + + +/******************************************************************** + WcaIsPropertySet() - returns TRUE if property is set + +********************************************************************/ +extern "C" BOOL WcaIsPropertySet( + __in LPCSTR szProperty + ) +{ + DWORD cchProperty = 0; + UINT er = ::MsiGetPropertyA(WcaGetInstallHandle(), szProperty, "", &cchProperty); + AssertSz(ERROR_INVALID_PARAMETER != er && ERROR_INVALID_HANDLE != er, "Unexpected return value from ::MsiGetProperty()"); + + return 0 < cchProperty; // property is set if the length is greater than zero +} + + +/******************************************************************** + WcaGetRecordInteger() - gets an integer field out of a record + + NOTE: returns S_FALSE if the field was null +********************************************************************/ +extern "C" HRESULT WcaGetRecordInteger( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout int* piData + ) +{ + if (!hRec || !piData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + *piData = ::MsiRecordGetInteger(hRec, uiField); + if (MSI_NULL_INTEGER == *piData) + hr = S_FALSE; + +//LExit: + return hr; +} + + +/******************************************************************** + WcaGetRecordString() - gets a string field out of a record + +********************************************************************/ +extern "C" HRESULT WcaGetRecordString( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout LPWSTR* ppwzData + ) +{ + if (!hRec || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er; + DWORD_PTR cch = 0; + + if (!*ppwzData) + { + er = ::MsiRecordGetStringW(hRec, uiField, L"", (DWORD*)&cch); + if (ERROR_MORE_DATA == er || ERROR_SUCCESS == er) + { + hr = StrAlloc(ppwzData, ++cch); + } + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to allocate memory for record string"); + } + else + { + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "Failed to get previous size of string"); + } + + er = ::MsiRecordGetStringW(hRec, uiField, *ppwzData, (DWORD*)&cch); + if (ERROR_MORE_DATA == er) + { + hr = StrAlloc(ppwzData, ++cch); + ExitOnFailure(hr, "Failed to allocate memory for record string"); + + er = ::MsiRecordGetStringW(hRec, uiField, *ppwzData, (DWORD*)&cch); + } + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to get string from record"); + +LExit: + return hr; +} + + +/******************************************************************** + HideNulls() - internal helper function to escape [~] in formatted strings + +********************************************************************/ +static void HideNulls( + __in LPWSTR wzData + ) +{ + LPWSTR pwz = wzData; + + while(*pwz) + { + if (pwz[0] == L'[' && pwz[1] == L'~' && pwz[2] == L']') // found a null [~] + { + pwz[0] = L'!'; // turn it into !$! + pwz[1] = L'$'; + pwz[2] = L'!'; + pwz += 3; + } + else + pwz++; + } +} + + +/******************************************************************** + RevealNulls() - internal helper function to unescape !$! in formatted strings + +********************************************************************/ +static void RevealNulls( + __in LPWSTR wzData + ) +{ + LPWSTR pwz = wzData; + + while(*pwz) + { + if (pwz[0] == L'!' && pwz[1] == L'$' && pwz[2] == L'!') // found the fake null !$! + { + pwz[0] = L'['; // turn it back into [~] + pwz[1] = L'~'; + pwz[2] = L']'; + pwz += 3; + } + else + pwz++; + } +} + + +/******************************************************************** + WcaGetRecordFormattedString() - gets formatted string filed from record + +********************************************************************/ +extern "C" HRESULT WcaGetRecordFormattedString( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout LPWSTR* ppwzData + ) +{ + if (!hRec || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er; + DWORD_PTR cch = 0; + PMSIHANDLE hRecFormat; + + // get the format string + hr = WcaGetRecordString(hRec, uiField, ppwzData); + ExitOnFailure(hr, "failed to get string from record"); + + if (!**ppwzData) + ExitFunction(); + + // hide the nulls '[~]' so we can get them back after formatting + HideNulls(*ppwzData); + + // set up the format record + hRecFormat = ::MsiCreateRecord(1); + ExitOnNull(hRecFormat, hr, E_UNEXPECTED, "Failed to create record to format string"); + hr = WcaSetRecordString(hRecFormat, 0, *ppwzData); + ExitOnFailure(hr, "failed to set string to format record"); + + // format the string + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "failed to get max length of string"); + + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecFormat, *ppwzData, (DWORD*)&cch); + if (ERROR_MORE_DATA == er) + { + hr = StrAlloc(ppwzData, ++cch); + ExitOnFailure(hr, "Failed to allocate memory for record string"); + + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecFormat, *ppwzData, (DWORD*)&cch); + } + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to format string"); + + // put the nulls back + RevealNulls(*ppwzData); + +LExit: + return hr; +} + + +/******************************************************************** + WcaAllocStream() - creates a byte stream of the specified size + + NOTE: Use WcaFreeStream() to release the byte stream +********************************************************************/ +extern "C" HRESULT WcaAllocStream( + __inout BYTE** ppbData, + __in DWORD cbData + ) +{ + Assert(ppbData); + HRESULT hr; + BYTE* pbNewData; + + if (*ppbData) + pbNewData = (BYTE*)MemReAlloc(*ppbData, cbData, TRUE); + else + pbNewData = (BYTE*)MemAlloc(cbData, TRUE); + + if (!pbNewData) + ExitOnLastError(hr, "Failed to allocate string"); + *ppbData = pbNewData; + pbNewData = NULL; + + hr = S_OK; +LExit: + if (pbNewData) + MemFree(pbNewData); + + return hr; +} + + +/******************************************************************** + WcaFreeStream() - frees a byte stream + +********************************************************************/ +extern "C" HRESULT WcaFreeStream( + __in BYTE* pbData + ) +{ + if (!pbData) + return E_INVALIDARG; + + HRESULT hr = MemFree(pbData); + return hr; +} + + +/******************************************************************** + WcaReadRecordStream() - gets a byte stream field from record + +********************************************************************/ +extern "C" HRESULT WcaGetRecordStream( + __in MSIHANDLE hRecBinary, + __in UINT uiField, + __inout BYTE** ppbData, + __inout DWORD* pcbData + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + if (!hRecBinary || !ppbData || !pcbData) + return E_INVALIDARG; + + *pcbData = 0; + er = ::MsiRecordReadStream(hRecBinary, uiField, NULL, pcbData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get size of stream"); + + hr = WcaAllocStream(ppbData, *pcbData); + ExitOnFailure(hr, "failed to allocate data for stream"); + + er = ::MsiRecordReadStream(hRecBinary, uiField, (char*)*ppbData, pcbData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to read from stream"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaSetRecordString() - set a string field in record + +********************************************************************/ +extern "C" HRESULT WcaSetRecordString( + __in MSIHANDLE hRec, + __in UINT uiField, + __in LPCWSTR wzData + ) +{ + if (!hRec || !wzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiRecordSetStringW(hRec, uiField, wzData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to set string in record"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaSetRecordInteger() - set a integer field in record + +********************************************************************/ +extern "C" HRESULT WcaSetRecordInteger( + __in MSIHANDLE hRec, + __in UINT uiField, + __in int iValue + ) +{ + if (!hRec) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiRecordSetInteger(hRec, uiField, iValue); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to set integer in record"); + +LExit: + return hr; +} + + +/******************************************************************** + + WcaDoDeferredAction() - schedules an action at this point in the script + +********************************************************************/ +extern "C" HRESULT WcaDoDeferredAction( + __in LPCWSTR wzAction, + __in LPCWSTR wzCustomActionData, + __in UINT uiCost + ) +{ + HRESULT hr = S_OK; + UINT er; + + if (wzCustomActionData && *wzCustomActionData) + { + er = ::MsiSetPropertyW(WcaGetInstallHandle(), wzAction, wzCustomActionData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to set CustomActionData for deferred action"); + } + + if (0 < uiCost) + { + hr = WcaProgressMessage(uiCost, TRUE); // add ticks to the progress bar + // TODO: handle the return codes correctly + } + + er = ::MsiDoActionW(WcaGetInstallHandle(), wzAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed MsiDoAction on deferred action"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaCountOfCustomActionDataRecords() - counts the number of records + passed to a deferred CustomAction + +********************************************************************/ +extern "C" DWORD WcaCountOfCustomActionDataRecords( + __in LPCWSTR wzData + ) +{ + if (!wzData) + return E_INVALIDARG; + + WCHAR delim[] = {MAGIC_MULTISZ_DELIM, 0}; // magic char followed by NULL terminator + DWORD dwCount = 0; + + // Loop through until there are no delimiters, we are at the end of the string, or the delimiter is the last character in the string + for (LPCWSTR pwzCurrent = wzData; pwzCurrent && *pwzCurrent && *(pwzCurrent + 1); pwzCurrent = wcsstr(pwzCurrent, delim)) + { + dwCount++; + pwzCurrent++; + } + + return dwCount; +} + + +/******************************************************************** + BreakDownCustomActionData() - internal helper to chop up CustomActionData + + NOTE: this modifies the passed in data +********************************************************************/ +static LPWSTR BreakDownCustomActionData( + __inout LPWSTR* ppwzData + ) +{ + if (!ppwzData) + return NULL; + if (0 == *ppwzData) + return NULL; + + WCHAR delim[] = {MAGIC_MULTISZ_DELIM, 0}; // magic char followed by Null terminator + + LPWSTR pwzReturn = *ppwzData; + LPWSTR pwz = wcsstr(pwzReturn, delim); + if (pwz) + { + *pwz = 0; + *ppwzData = pwz + 1; + } + else + *ppwzData = 0; + + return pwzReturn; +} + + +/******************************************************************** + WcaReadStringFromCaData() - reads a string out of the CustomActionData + + NOTE: this modifies the passed in ppwzCustomActionData variable +********************************************************************/ +extern "C" HRESULT WcaReadStringFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __inout LPWSTR* ppwzString + ) +{ + HRESULT hr = S_OK; + + LPCWSTR pwz = BreakDownCustomActionData(ppwzCustomActionData); + if (!pwz) + return E_NOMOREITEMS; + + hr = StrAllocString(ppwzString, pwz, 0); + ExitOnFailure(hr, "failed to allocate memory for string"); + + hr = S_OK; +LExit: + return hr; +} + + +/******************************************************************** + WcaReadIntegerFromCaData() - reads an integer out of the CustomActionData + + NOTE: this modifies the passed in ppwzCustomActionData variable +********************************************************************/ +extern "C" HRESULT WcaReadIntegerFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __inout int* piResult + ) +{ + LPCWSTR pwz = BreakDownCustomActionData(ppwzCustomActionData); + if (!pwz) + return E_NOMOREITEMS; + + *piResult = wcstol(pwz, NULL, 10); + return S_OK; +} + + +/******************************************************************** + WcaReadStreamFromCaData() - reads a stream out of the CustomActionData + + NOTE: this modifies the passed in ppwzCustomActionData variable + NOTE: returned stream should be freed with WcaFreeStream() +********************************************************************/ +extern "C" HRESULT WcaReadStreamFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __out BYTE** ppbData, + __out DWORD_PTR* pcbData + ) +{ + HRESULT hr; + + LPCWSTR pwz = BreakDownCustomActionData(ppwzCustomActionData); + if (!pwz) + return E_NOMOREITEMS; + + hr = StrAllocBase85Decode(pwz, ppbData, pcbData); + ExitOnFailure(hr, "failed to decode string into stream"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaWriteStringToCaData() - adds a string to the CustomActionData to + feed a deferred CustomAction + +********************************************************************/ +extern "C" HRESULT WcaWriteStringToCaData( + __in LPCWSTR wzString, + __inout LPWSTR* ppwzCustomActionData + ) +{ + HRESULT hr = S_OK; + WCHAR delim[] = {MAGIC_MULTISZ_DELIM, 0}; // magic char followed by NULL terminator + + if (!ppwzCustomActionData) + return E_INVALIDARG; + + DWORD cchString = lstrlenW(wzString) + 1; // assume we'll be adding the delim + DWORD_PTR cchCustomActionData = 0; + + if (*ppwzCustomActionData) + { + hr = StrMaxLength(*ppwzCustomActionData, &cchCustomActionData); + ExitOnFailure(hr, "failed to get length of custom action data"); + } + + if ((cchCustomActionData - lstrlenW(*ppwzCustomActionData)) < cchString + 1) + { + cchCustomActionData += cchString + 1 + 255; // add 255 for good measure + hr = StrAlloc(ppwzCustomActionData, cchCustomActionData); + ExitOnFailure(hr, "Failed to allocate memory for CustomActionData string"); + ExitOnNull(*ppwzCustomActionData, hr, E_OUTOFMEMORY, "Failed to allocate memory for CustomActionData string"); + } + + if (**ppwzCustomActionData) // if data exists toss the delimiter on before adding more to the end + StringCchCatW(*ppwzCustomActionData, cchCustomActionData, delim); + StringCchCatW(*ppwzCustomActionData, cchCustomActionData, wzString); + +LExit: + return hr; +} + + +/******************************************************************** + WcaWriteStringToCaData() - adds an integer to the CustomActionData to + feed a deferred CustomAction + +********************************************************************/ +extern "C" HRESULT WcaWriteIntegerToCaData( + __in int i, + __inout LPWSTR* ppwzCustomActionData + ) +{ + WCHAR wzBuffer[13]; + StringCchPrintfW(wzBuffer, countof(wzBuffer), L"%d", i); + + return WcaWriteStringToCaData(wzBuffer, ppwzCustomActionData); +} + + +/******************************************************************** + WcaWriteStringToCaData() - adds a byte stream to the CustomActionData to + feed a deferred CustomAction + +********************************************************************/ +extern "C" HRESULT WcaWriteStreamToCaData( + __in_bcount(cbData) const BYTE* pbData, + __in DWORD cbData, + __inout LPWSTR* ppwzCustomActionData + ) +{ + HRESULT hr; + LPWSTR pwzData = NULL; + + hr = StrAllocBase85Encode(pbData, cbData, &pwzData); + ExitOnFailure(hr, "failed to encode data into string"); + + hr = WcaWriteStringToCaData(pwzData, ppwzCustomActionData); + +LExit: + ReleaseStr(pwzData); + return hr; +} + + +/******************************************************************** +WcaAddTempRecord - adds a temporary record to the active database + +NOTE: you cannot use PMSIHANDLEs for the __in/__out parameters +NOTE: uiUniquifyColumn can be 0 if no column needs to be made unique +********************************************************************/ +extern "C" HRESULT WcaAddTempRecord( + __inout MSIHANDLE* phTableView, + __inout MSIHANDLE* phColumns, + __in LPCWSTR wzTable, + __in UINT uiUniquifyColumn, + __in UINT cColumns, + ... + ) +{ + Assert(phTableView && phColumns); + + static DWORD dwUniquifyValue = ::GetTickCount(); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzQuery = NULL; + PMSIHANDLE hTempRec; + DWORD i; + va_list args; + + LPWSTR pwzData = NULL; + LPWSTR pwzUniquify = NULL; + + // + // if we don't have a table and it's columns already + // + if (NULL == *phTableView) + { + // set the query + hr = StrAllocFormatted(&pwzQuery, L"SELECT * FROM `%s`",wzTable); + ExitOnFailure(hr, "failed to allocate string for query"); + + // Open and Execute the temp View + hr = WcaOpenExecuteView(pwzQuery, phTableView); + ExitOnFailure1(hr, "failed to openexecute temp view with query %S", pwzQuery); + } + + if (NULL == *phColumns) + { + // use GetColumnInfo to populate the datatype record + er = ::MsiViewGetColumnInfo(*phTableView, MSICOLINFO_TYPES, phColumns); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to columns for table: %S", wzTable); + } + AssertSz(::MsiRecordGetFieldCount(*phColumns) == cColumns, "passed in argument does not match number of columns in table"); + + // + // create the temp record + // + hTempRec = ::MsiCreateRecord(cColumns); + ExitOnNull1(hTempRec, hr, E_UNEXPECTED, "could not create temp record for table: %S", wzTable); + + // + // loop through all the columns filling in the data + // + va_start(args, cColumns); + for (i = 1; i <= cColumns; i++) + { + hr = WcaGetRecordString(*phColumns, i, &pwzData); + ExitOnFailure1(hr, "failed to get the data type for %d", i); + + // if data type is string write string + if (L's' == *pwzData || L'S' == *pwzData || L'g' == *pwzData || L'G' == *pwzData || L'l' == *pwzData || L'L' == *pwzData) + { + LPCWSTR wz = va_arg(args, WCHAR*); + + // if this is the column that is supposed to be unique add the time stamp on the end + if (uiUniquifyColumn == i) + { + hr = StrAllocFormatted(&pwzUniquify, L"%s%u", wz, ++dwUniquifyValue); // up the count so we have no collisions on the unique name + ExitOnFailure1(hr, "failed to allocate string for unique column: %d", uiUniquifyColumn); + + wz = pwzUniquify; + } + + er = ::MsiRecordSetStringW(hTempRec, i, wz); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to set string value at position %d", i); + } + // if data type is integer write integer + else if (L'i' == *pwzData || L'I' == *pwzData || L'j' == *pwzData || L'J' == *pwzData) + { + AssertSz(uiUniquifyColumn != i, "Cannot uniquify an integer column"); + int iData = va_arg(args, int); + + er = ::MsiRecordSetInteger(hTempRec, i, iData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to set integer value at position %d", i); + } + else + { + // not supporting binary streams so error out + hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH); + ExitOnFailure2(hr, "unsupported data type '%S' in column: %d", pwzData, i); + } + } + va_end(args); + + // + // add the temporary record to the MSI + // + er = ::MsiViewModify(*phTableView, MSIMODIFY_INSERT_TEMPORARY, hTempRec); + hr = HRESULT_FROM_WIN32(er); + if (FAILED(hr)) + { + MSIDBERROR dbErr; + WCHAR wzBuf[MAX_PATH]; + DWORD cchBuf = countof(wzBuf); + + dbErr = ::MsiViewGetErrorW(*phTableView, wzBuf, &cchBuf); + ExitOnFailure2(hr, "failed to add temporary row, dberr: %d, err: %S", dbErr, wzBuf); + } + +LExit: + ReleaseStr(pwzUniquify); + ReleaseStr(pwzData); + ReleaseStr(pwzQuery); + + return hr; +} + + +/******************************************************************** +WcaDumpTable - dumps a table to the log file + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaDumpTable( + __in LPCWSTR wzTable + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzQuery = NULL; + PMSIHANDLE hView; + PMSIHANDLE hColumns; + DWORD cColumns = 0; + PMSIHANDLE hRec; + + LPWSTR pwzData = NULL; + LPWSTR pwzPrint = NULL; + + hr = StrAllocFormatted(&pwzQuery, L"SELECT * FROM `%s`",wzTable); + ExitOnFailure(hr, "failed to allocate string for query"); + + // Open and Execute the temp View + hr = WcaOpenExecuteView(pwzQuery, &hView); + ExitOnFailure1(hr, "failed to openexecute temp view with query %S", pwzQuery); + + // Use GetColumnInfo to populate the names of the columns. + er = ::MsiViewGetColumnInfo(hView, MSICOLINFO_NAMES, &hColumns); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to columns for table: %S", wzTable); + + cColumns = ::MsiRecordGetFieldCount(hColumns); + + WcaLog(LOGMSG_STANDARD, "--- Begin Table Dump %S ---", wzTable); + + // Loop through all the columns filling in the data. + for (DWORD i = 1; i <= cColumns; i++) + { + hr = WcaGetRecordString(hColumns, i, &pwzData); + ExitOnFailure1(hr, "failed to get the column name for %d", i); + + hr = StrAllocConcat(&pwzPrint, pwzData, 0); + ExitOnFailure(hr, "Failed to add column name."); + + hr = StrAllocConcat(&pwzPrint, L"\t", 1); + ExitOnFailure(hr, "Failed to add column name."); + } + + WcaLog(LOGMSG_STANDARD, "%S", pwzPrint); + + // Now dump the actual rows. + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + if (pwzPrint && *pwzPrint) + { + *pwzPrint = L'\0'; + } + + for (DWORD i = 1; i <= cColumns; i++) + { + hr = WcaGetRecordString(hRec, i, &pwzData); + ExitOnFailure1(hr, "failed to get the column name for %d", i); + + hr = StrAllocConcat(&pwzPrint, pwzData, 0); + ExitOnFailure(hr, "Failed to add column name."); + + hr = StrAllocConcat(&pwzPrint, L"\t", 1); + ExitOnFailure(hr, "Failed to add column name."); + } + + WcaLog(LOGMSG_STANDARD, "%S", pwzPrint); + } + + WcaLog(LOGMSG_STANDARD, "--- End Table Dump %S ---", wzTable); + +LExit: + ReleaseStr(pwzPrint); + ReleaseStr(pwzData); + ReleaseStr(pwzQuery); + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/AspNetCoreModule.ico b/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/AspNetCoreModule.ico new file mode 100644 index 0000000000..bcafd4a5b7 Binary files /dev/null and b/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/AspNetCoreModule.ico differ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/bannrbmp.bmp b/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/bannrbmp.bmp new file mode 100644 index 0000000000..8507592b05 Binary files /dev/null and b/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/bannrbmp.bmp differ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/dlgbmp.bmp b/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/dlgbmp.bmp new file mode 100644 index 0000000000..c3810b4037 Binary files /dev/null and b/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/dlgbmp.bmp differ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/copy-outputs.targets b/src/Installers/Windows/AspNetCoreModule-Setup/build/copy-outputs.targets new file mode 100644 index 0000000000..bdc59f4f6d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/copy-outputs.targets @@ -0,0 +1,18 @@ + + + + + + + + $(Configuration)\$(PlatformShortname)\ + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/exports.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/exports.props new file mode 100644 index 0000000000..512b082102 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/exports.props @@ -0,0 +1,13 @@ + + + + + + $(MSBuildThisFileDirectory)..\ + + + + $(MSBuildThisFileDirectory)..\ + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/settings.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings.props new file mode 100644 index 0000000000..ba1ca74632 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings.props @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/common.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/common.props new file mode 100644 index 0000000000..0130b6e5ab --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/common.props @@ -0,0 +1,53 @@ + + + + + + + x64 + x86 + + + + + + 10.0.15063.0 + $(IisOobWinSdkVersion) + Unicode + bin\$(Configuration)\$(PlatformShortname)\ + obj\$(Configuration)\$(PlatformShortname)\ + + + + + + + Level3 + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + WIN32;%(PreprocessorDefinitions) + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/debug.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/debug.props new file mode 100644 index 0000000000..710f5553d0 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/debug.props @@ -0,0 +1,29 @@ + + + + + + true + true + false + + + + + + + true + Disabled + true + EnableFastChecks + MultiThreadedDebug + + + false + false + true + /JMC- + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/release.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/release.props new file mode 100644 index 0000000000..d7eb8ffa35 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/release.props @@ -0,0 +1,51 @@ + + + + + + + true + true + + + + + + + false + false + true + + + + + + + Full + Speed + false + MultiThreaded + true + + + true + true + UseLinkTimeCodeGeneration + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/submodule.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/submodule.props new file mode 100644 index 0000000000..00046cf191 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/submodule.props @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/versions.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/versions.props new file mode 100644 index 0000000000..3be2245e72 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/versions.props @@ -0,0 +1,38 @@ + + + + + 7 + 1 + + + $([MSBuild]::Multiply(12,$([MSBuild]::Subtract($([System.DateTime]::Now.Year), 2016)))) + $([MSBuild]::Add( $([MSBuild]::Subtract($([System.DateTime]::Now.Month), 10)), $(VersionDateMonths))) + $([System.DateTime]::Now.ToString("dd")) + $([System.String]::Concat($([System.Int32]::Parse('$(VersionDateTotalMonths)').ToString("D3")), $(VersionDateDays))) + $(VersionBuildMajor) + $([System.DateTime]::Now.ToString("HHmm")) + + + + + /DPRODUCT_MAJOR=$(PRODUCT_MAJOR) %(AdditionalOptions) + + + /DPRODUCT_MINOR=$(PRODUCT_MINOR) %(AdditionalOptions) + + + /DBUILD_MAJOR=$(BUILD_MAJOR) %(AdditionalOptions) + + + /DBUILD_MINOR=$(BUILD_MINOR) %(AdditionalOptions) + + + + + PRODUCT_MAJOR=$(PRODUCT_MAJOR);$(ResourceCompilePreprocessorDefinitions) + PRODUCT_MINOR=$(PRODUCT_MINOR);$(ResourceCompilePreprocessorDefinitions) + BUILD_MAJOR=$(BUILD_MAJOR);$(ResourceCompilePreprocessorDefinitions) + BUILD_MINOR=$(BUILD_MINOR);$(ResourceCompilePreprocessorDefinitions) + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/license/license.rtf b/src/Installers/Windows/AspNetCoreModule-Setup/license/license.rtf new file mode 100644 index 0000000000..91c46e44c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/license/license.rtf @@ -0,0 +1,97 @@ +{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033\deflangfe2052{\fonttbl{\f0\fswiss\fprq2\fcharset0 Tahoma;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\froman\fprq2\fcharset0 Times New Roman;}{\f3\fswiss\fprq2\fcharset0 Calibri;}{\f4\fnil\fcharset2 Symbol;}} +{\colortbl ;\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;} +{\stylesheet{ Normal;}{\s1 heading 1;}} +{\*\generator Riched20 10.0.10586}\viewkind4\uc1 +\pard\nowidctlpar\sb120\sa120\b\f0\fs22 MICROSOFT SOFTWARE LICENSE TERMS\fs20\par + +\pard\brdrb\brdrs\brdrw10\brsp20 \nowidctlpar\sb120\sa120\fs22 MICROSOFT ASP.NET CORE MODULE\fs20\par + +\pard\widctlpar\sb120\sa120 These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. Please read them. They apply to the software named above, which includes the media on which you received it, if any. The terms also apply to any Microsoft\b0\par + +\pard\nowidctlpar\fi-360\li360\sb120\sa120\tx360\f1\'b7\tab\f0 updates,\par +\f1\'b7\tab\f0 supplements,\par +\f1\'b7\tab\f0 Internet-based services, and\par +\f1\'b7\tab\f0 support services\par + +\pard\nowidctlpar\sb120\sa120 for this software, unless other terms accompany those items. If so, those terms apply.\par +\b BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE.\par + +\pard\brdrt\brdrs\brdrw10\brsp20 \nowidctlpar\sb120\sa120 IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW.\par + +\pard\nowidctlpar\s1\fi-357\li357\sb120\sa120\tx360 1.\tab INSTALLATION AND USE RIGHTS. \b0\f2\par + +\pard\widctlpar\fi-363\li720\sb120\sa120\b\f0 a.\~\~\~ Installation and Use.\b0 You may install and use any number of copies of the software to design, develop and test your programs.\b\par +b.\~\~\~ Third Party Programs.\b0 The software may include third party programs that Microsoft, not the third party, licenses to you under this agreement. Notices, if any, for the third party program are included for your information only.\b\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\kerning36 2.\tab ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS.\par + +\pard\widctlpar\fi-363\li720\sb120\sa120\kerning0 a.\~\~\~ DISTRIBUTABLE CODE.\~ \b0 The software is comprised of Distributable Code. \ldblquote Distributable Code\rdblquote is code that you are permitted to distribute in programs you develop if you comply with the terms below.\b\par + +\pard\widctlpar\fi-357\li1077\sb120\sa120 i.\~\~\~\~\~ Right to Use and Distribute. \b0\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-360\li1797\sb120\sa120 You may copy and distribute the object code form of the software.\par +{\pntext\f4\'B7\tab}Third Party Distribution. You may permit distributors of your programs to copy and distribute the Distributable Code as part of those programs.\par + +\pard\widctlpar\fi-357\li1077\sb120\sa120\b ii.\~\~\~ Distribution Requirements.\b0 \b For any Distributable Code you distribute, you must\b0\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-360\li1797\sb120\sa120 add significant primary functionality to it in your programs;\par +{\pntext\f4\'B7\tab}require distributors and external end users to agree to terms that protect it at least as much as this agreement;\par +{\pntext\f4\'B7\tab}display your valid copyright notice on your programs; and\par +{\pntext\f4\'B7\tab}indemnify, defend, and hold harmless Microsoft from any claims, including attorneys\rquote fees, related to the distribution or use of your programs.\par + +\pard\widctlpar\fi-357\li1077\sb120\sa120\b iii.\~\~ Distribution Restrictions.\b0 \b You may not\b0\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-360\li1797\sb120\sa120 alter any copyright, trademark or patent notice in the Distributable Code;\par +{\pntext\f4\'B7\tab}use Microsoft\rquote s trademarks in your programs\rquote names or in a way that suggests your programs come from or are endorsed by Microsoft;\par +{\pntext\f4\'B7\tab}include Distributable Code in malicious, deceptive or unlawful programs; or\par +{\pntext\f4\'B7\tab}modify or distribute the source code of any Distributable Code so that any part of it becomes subject to an Excluded License. An Excluded License is one that requires, as a condition of use, modification or distribution, that\par +{\pntext\f4\'B7\tab}the code be disclosed or distributed in source code form; or\par +{\pntext\f4\'B7\tab}others have the right to modify it.\f2\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\b\f0 3.\tab\kerning36 SCOPE OF LICENSE. \b0 The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not\b\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-360\li1797\sb120\sa120\kerning0\b0 work around any technical limitations in the software;\par +{\pntext\f4\'B7\tab}reverse engineer, decompile or disassemble the software, except and only to the extent that applicable law expressly permits, despite this limitation;\par +{\pntext\f4\'B7\tab}publish the software for others to copy;\par +{\pntext\f4\'B7\tab}rent, lease or lend the software;\par +{\pntext\f4\'B7\tab}transfer the software or this agreement to any third party; or\par +{\pntext\f4\'B7\tab}use the software for commercial software hosting services.\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\b 4.\tab\cf1\highlight2 DATA.\cf0\highlight0\b0 The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but not all, as described in the product documentation. You can learn more about data collection and use in the help documentation and the privacy statement at {{\field{\*\fldinst{HYPERLINK https://privacy.microsoft.com/en-us/privacystatement }}{\fldrslt{https://privacy.microsoft.com/en-us/privacystatement\ul0\cf0}}}}\f0\fs20 . {\f3\fs22{\field{\*\fldinst{HYPERLINK http://go.microsoft.com/fwlink/?LinkID=528096Your }}{\fldrslt{http://go.microsoft.com/fwlink/?LinkID=528096\f0\fs20 Your\ul0\cf0}}}}\f0\fs20 use of the software operates as your consent to these practices.\par +\b 5.\tab\kerning36 BACKUP COPY. \b0 You may make one backup copy of the software. You may use it only to reinstall the software.\b\par +6.\tab DOCUMENTATION. \b0 Any person that has valid access to your computer or internal network may copy and use the documentation for your internal, reference purposes.\b\par +7.\tab EXPORT RESTRICTIONS. \b0 The software is subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the software. These laws include restrictions on destinations, end users and end use. For additional information, see {{\field{\*\fldinst{HYPERLINK www.microsoft.com/exporting }}{\fldrslt{www.microsoft.com/exporting\ul0\cf0}}}}\f0\fs20 .\b\par +8.\tab SUPPORT SERVICES. \b0 Because this software is \ldblquote as is,\rdblquote we may not provide support services for it.\b\par +9.\tab ENTIRE AGREEMENT. \b0 This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services.\b\par +10.\tab APPLICABLE LAW.\par + +\pard\widctlpar\fi-363\li720\sb120\sa120\kerning0 a.\tab United States. \b0 If you acquired the software in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort.\b\par +b.\~\~\~ Outside the United States. If you acquired the software in any other country, the laws of that country apply.\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\kerning36 11.\tab LEGAL EFFECT. \b0 This agreement describes certain legal rights. You may have other rights under the laws of your country. You may also have rights with respect to the party from whom you acquired the software. This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so.\b\par +12.\tab DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED \ldblquote AS-IS.\rdblquote YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. YOU MAY HAVE ADDITIONAL CONSUMER RIGHTS OR STATUTORY GUARANTEES UNDER YOUR LOCAL LAWS WHICH THIS AGREEMENT CANNOT CHANGE. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.\par + +\pard\widctlpar\li357\sb120\sa120\kerning0 FOR AUSTRALIA \endash YOU HAVE STATUTORY GUARANTEES UNDER THE AUSTRALIAN CONSUMER LAW AND NOTHING IN THESE TERMS IS INTENDED TO AFFECT THOSE RIGHTS.\b0\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\kerning36\b 13.LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.\par + +\pard\widctlpar\li357\sb120\sa120\kerning0\b0 This limitation applies to\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-270\li720\sb120\sa120 anything related to the software, services, content (including code) on third party Internet sites, or third party programs; and\par +{\pntext\f4\'B7\tab}claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.\par + +\pard\widctlpar\sb120\sa120 It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.\par +\lang9 Please note: As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French.\lang1033\par +\lang9 Remarque : Ce logiciel \'e9tant distribu\'e9 au Qu\'e9bec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en fran\'e7ais.\lang1033\par +\kerning36\b EXON\'c9RATION DE GARANTIE. \b0 Le logiciel vis\'e9 par une licence est offert \'ab tel quel \'bb. Toute utilisation de ce logiciel est \'e0 votre seule risque et p\'e9ril. Microsoft n\rquote accorde aucune autre garantie expresse. Vous pouvez b\'e9n\'e9ficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualit\'e9 marchande, d\rquote ad\'e9quation \'e0 un usage particulier et d\rquote absence de contrefa\'e7on sont exclues.\b\par +LIMITATION DES DOMMAGES-INT\'c9R\'caTS ET EXCLUSION DE RESPONSABILIT\'c9 POUR LES DOMMAGES. \b0 Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement \'e0 hauteur de 5,00 $ US. Vous ne pouvez pr\'e9tendre \'e0 aucune indemnisation pour les autres dommages, y compris les dommages sp\'e9ciaux, indirects ou accessoires et pertes de b\'e9n\'e9fices.\b\par +\kerning0\b0\lang9 Cette limitation concerne :\lang1033\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-720\li720\sb120\sa120\lang9 tout ce qui est reli\'e9 au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et\par +{\pntext\f4\'B7\tab}les r\'e9clamations au titre de violation de contrat ou de garantie, ou au titre de responsabilit\'e9 stricte, de n\'e9gligence ou d\rquote une autre faute dans la limite autoris\'e9e par la loi en vigueur.\lang1033\par + +\pard\widctlpar\sb120\sa120\lang9 Elle s\rquote applique \'e9galement, m\'eame si Microsoft connaissait ou devrait conna\'eetre l\rquote\'e9ventualit\'e9 d\rquote un tel dommage. Si votre pays n\rquote autorise pas l\rquote exclusion ou la limitation de responsabilit\'e9 pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l\rquote exclusion ci-dessus ne s\rquote appliquera pas \'e0 votre \'e9gard.\lang1033\par +\kerning36\b\fs19 EFFET JURIDIQUE. \b0 Le pr\'e9sent contrat d\'e9crit certains droits juridiques. Vous pourriez avoir d\rquote autres droits pr\'e9vus par les lois de votre pays. Le pr\'e9sent contrat ne modifie pas les droits que vous conf\'e8rent les lois de votre pays si celles-ci ne le permettent pas.\b\par +\kerning0\b0\f2\fs20\par +} + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/setupstrings.wxl new file mode 100644 index 0000000000..5ac48523c5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/setupstrings.wxl @@ -0,0 +1,52 @@ + + + + 1033 + + + Microsoft ASP.NET Core Module + Microsoft ASP.NET Core Module V2 + ASP.NET Core IIS Runtime + Adds the support of asp.net core application to IIS. + Microsoft ASP.NET Core Module for IIS Express + Microsoft ASP.NET Core Module V2 for IIS Express + IIS Express 8.0 or higher is not installed. + + + + Microsoft Corporation + An incompatible product, [CONFLICTING_PRODUCT_NAME], is on this computer. Installation of [ProductName] cannot continue. To install this product, use Add/Remove Programs on the Control Panel to remove [CONFLICTING_PRODUCT_NAME]. + Administrator privilege is required to install [ProductName]. + IIS Version 7.0 is required to use [ProductName]. + IIS Version 7.0 or greater is required to install [ProductName]. + IIS Version 7.5 or greater is required to install [ProductName]. + IIS Version 7 or 7.5 is required to install [ProductName]. + IIS Version 8.0 or greater is required to install [ProductName]. + The beta version of [ProductName] was found on this machine. + A newer version of [ProductName] was found on this machine. + Setup cannot continue because another instance of [ProductName] is already installed on this computer. Please uninstall it first and then re-launch this installation. + The IIS 7.0 CoreWebEngine and W3SVC features must be installed to use [ProductName]. + The IIS Management Console must be installed to use [ProductName]. + Please stop both services Windows Process Activation Service (WAS) and Web Management Service (WMSvc) before installing [ProductName]. You will need to start the services after installing [ProductName]. + IIS Metabase is required to install [ProductName]. + The 64-bit version of [ProductName] cannot be installed on a 32-bit edition of Microsoft Windows. + The 32-bit version of [ProductName] cannot be installed on a 64-bit edition of Microsoft Windows. + Microsoft .NET Framework Version 2.0 or greater is required to install [ProductName]. + Microsoft .NET Framework Version 3.5 or greater is required to install [ProductName]. Use 'Add Features' under the Server Manager to install Microsoft .Net Version 3.5. + Microsoft .NET Framework Version 4.0 or greater is required to install [ProductName]. + Please install Microsoft .NET Framework Version 2.0 Service Pack 1 (or a later service pack), before installing [ProductName]. + The Windows Update (wuauserv) service cannot be disabled, it is required to install [ProductName]. + The PowerShell snap-in is part of Windows Operating System. Please install it via 'Programs and Features' or 'Server Manager'. + Microsoft Web Platform Installer Version 3.0 or greater is required to install [ProductName]. + + Setup failed to detect shared configuration. + Shared configuration is enabled for IIS. Installing [ProductName] is not supported when using shared configuration. Please disable shared configuration before installing this feature. + + Please stop World Wide Web Publishing Service (W3SVC) before installing [ProductName]. You will need to start the service after installation. + IIS PowerShell Management Console + IIS PowerShell snap-in + IIS PowerShell snap-in requires PowerShell v1.0 or v2.0 installed + IIS PowerShell snap-in requires WAS and configuration installed + This is a bogus string. + + diff --git a/src/Installers/Windows/Directory.Build.props b/src/Installers/Windows/Directory.Build.props new file mode 100644 index 0000000000..096863e245 --- /dev/null +++ b/src/Installers/Windows/Directory.Build.props @@ -0,0 +1,20 @@ + + + + $([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)..\..\..\')) + $(RepositoryRoot)artifacts/ + $(RootOutputPath)bin/$(Configuration)/$(MSBuildProjectName)/ + $(BaseOutputPath) + $(RootOutputPath)obj/$(MSBuildProjectName)/ + $(BaseIntermediateOutputPath)$(Configuration)/ + $(IntermediateOutputPath)$(Platform)/ + + aspnetcore-runtime + + $(RuntimeInstallerBaseName)-internal + + + + + + diff --git a/src/Installers/Windows/Directory.Build.targets b/src/Installers/Windows/Directory.Build.targets new file mode 100644 index 0000000000..8dc63cace9 --- /dev/null +++ b/src/Installers/Windows/Directory.Build.targets @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Installers/Windows/SharedFramework/DependencyProvider.wxs b/src/Installers/Windows/SharedFramework/DependencyProvider.wxs new file mode 100644 index 0000000000..d62c3dfe7d --- /dev/null +++ b/src/Installers/Windows/SharedFramework/DependencyProvider.wxs @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/SharedFramework/Product.props b/src/Installers/Windows/SharedFramework/Product.props new file mode 100644 index 0000000000..a6a29c3f80 --- /dev/null +++ b/src/Installers/Windows/SharedFramework/Product.props @@ -0,0 +1,11 @@ + + + Microsoft ASP.NET Core Shared Framework + Microsoft ASP.NET Core $(PackageBrandingVersion) Shared Framework ($(Platform)) + AspNetCore.SharedFramework + + $(DefineConstants);ProductName=$(ProductName) + $(DefineConstants);ProductNameShort=$(ProductNameShort) + $(DefineConstants);ProductNameFolder=$(ProductNameFolder) + + diff --git a/src/Installers/Windows/SharedFramework/Product.wxs b/src/Installers/Windows/SharedFramework/Product.wxs new file mode 100644 index 0000000000..c97b12e5c4 --- /dev/null +++ b/src/Installers/Windows/SharedFramework/Product.wxs @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/SharedFramework/SharedFramework.wixproj b/src/Installers/Windows/SharedFramework/SharedFramework.wixproj new file mode 100644 index 0000000000..5dd1ce6809 --- /dev/null +++ b/src/Installers/Windows/SharedFramework/SharedFramework.wixproj @@ -0,0 +1,51 @@ + + + + + + + + AspNetCoreSharedFramework + $(RuntimeInstallerBaseName)-$(PackageVersion)-win-$(Platform) + Package + no + sfx_$(Platform).cab + C681D730-4505-42C6-9E6C-87F757C4FB32 + true + 5150;5151 + true + $(SharedFrameworkHarvestRootPath)\$(Platform)\ + $(DefineConstants);AspNetCoreSharedFrameworkSource=$(HarvestSource) + $(SharedFrameworkNamespaceGuid) + + + + + $(WixExtDir)\WixDependencyExtension.dll + WixDependencyExtension + + + $(WixExtDir)\WixNetFxExtension.dll + WixNetFxExtension + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixUIExtension.dll + WixUIExtension + + + + + + true + CG_AspNetCoreSharedFramework + DotNetFolder + var.AspNetCoreSharedFrameworkSource + + + + + diff --git a/src/Installers/Windows/SharedFramework/Strings.wxl b/src/Installers/Windows/SharedFramework/Strings.wxl new file mode 100644 index 0000000000..ffac28752f --- /dev/null +++ b/src/Installers/Windows/SharedFramework/Strings.wxl @@ -0,0 +1,5 @@ + + + ASP.NET Core Shared Framework + ASP.NET Core Shared Framework + \ No newline at end of file diff --git a/src/Installers/Windows/SharedFrameworkBundle/Bundle.wxs b/src/Installers/Windows/SharedFrameworkBundle/Bundle.wxs new file mode 100644 index 0000000000..2ca506b46e --- /dev/null +++ b/src/Installers/Windows/SharedFrameworkBundle/Bundle.wxs @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/SharedFrameworkBundle/DotNetLogo.bmp b/src/Installers/Windows/SharedFrameworkBundle/DotNetLogo.bmp new file mode 100644 index 0000000000..f652d049e8 Binary files /dev/null and b/src/Installers/Windows/SharedFrameworkBundle/DotNetLogo.bmp differ diff --git a/src/Installers/Windows/SharedFrameworkBundle/Product.props b/src/Installers/Windows/SharedFrameworkBundle/Product.props new file mode 100644 index 0000000000..a77dc7a3df --- /dev/null +++ b/src/Installers/Windows/SharedFrameworkBundle/Product.props @@ -0,0 +1,31 @@ + + + Microsoft ASP.NET Core $(PackageBrandingVersion) + + + + Shared Framework + $(BundleNameShort) - $(BundleNameSub) + $(BundleName) ($(Platform)) + Microsoft Corporation + dd_AspNetCoreSharedFramework_ + + + Microsoft + .NET Core + Microsoft ASP.NET Core $(PackageBrandingVersion) Shared Framework + $(BundleNameFull) + + + + $(DefineConstants);BundleName=$(BundleName) + $(DefineConstants);BundleNameFull=$(BundleNameFull) + $(DefineConstants);BundleNameShort=$(BundleNameShort) + $(DefineConstants);BundleNameSub=$(BundleNameSub) + $(DefineConstants);BundleManufacturer=$(BundleManufacturer) + $(DefineConstants);BundleLogPrefix=$(BundleLogPrefix) + $(DefineConstants);BundleRegManufacturer=$(BundleRegManufacturer) + $(DefineConstants);BundleRegFamily=$(BundleRegFamily) + $(DefineConstants);BundleRegName=$(BundleRegName) + + diff --git a/src/Installers/Windows/SharedFrameworkBundle/SharedFrameworkBundle.wixproj b/src/Installers/Windows/SharedFrameworkBundle/SharedFrameworkBundle.wixproj new file mode 100644 index 0000000000..e4d3697989 --- /dev/null +++ b/src/Installers/Windows/SharedFrameworkBundle/SharedFrameworkBundle.wixproj @@ -0,0 +1,36 @@ + + + + + + + + AspNetCoreSharedFrameworkBundle + Bundle + $(RuntimeInstallerBaseName)-$(PackageVersion)-win-$(Platform) + $(SharedFrameworkNamespaceGuid) + D6C54D8B-043F-4877-B751-60E7390F9EC6 + + + + + $(WixExtDir)\WixDependencyExtension.dll + WixDependencyExtension + + + $(WixExtDir)\WixBalExtension.dll + WixBalExtension + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/SharedFrameworkBundle/thm.wxl b/src/Installers/Windows/SharedFrameworkBundle/thm.wxl new file mode 100644 index 0000000000..bb88e23d9e --- /dev/null +++ b/src/Installers/Windows/SharedFrameworkBundle/thm.wxl @@ -0,0 +1,61 @@ + + + [BundleNameFull] Setup + [BundleNameShort] + [BundleNameSub] + Welcome + Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit. + Version [WixBundleVersion] + Are you sure you want to cancel? + Previous version + Setup Help + /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or + creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and + no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + &Close + [WixBundleName] <a href="#">license terms</a>. + I &agree to the license terms and conditions + &Options + &Install + &Close + Setup Options + Install location: + &Browse + &OK + &Cancel + Setup Progress + Processing: + Initializing... + &Cancel + Modify Setup + &Repair + &Uninstall + &Close + Repair Successfully Completed + Uninstall Successfully Completed + Installation Successfully Completed + Setup Successful + &Launch + You must restart your computer before you can use the software. + &Restart + &Close + Setup Failed + Setup Failed + Uninstall Failed + Repair Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close + Files In Use + The following applications are using files that need to be updated: + Close the &applications and attempt to restart them. + &Do not close applications. A reboot will be required. + &OK + &Cancel + \ No newline at end of file diff --git a/src/Installers/Windows/SharedFrameworkBundle/thm.xml b/src/Installers/Windows/SharedFrameworkBundle/thm.xml new file mode 100644 index 0000000000..f9323a366f --- /dev/null +++ b/src/Installers/Windows/SharedFrameworkBundle/thm.xml @@ -0,0 +1,80 @@ + + + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + #(loc.Title) + #(loc.SubTitle) + + + #(loc.HelpHeader) + #(loc.HelpText) + + + + Welcome to the #(loc.Caption). + [WixBundleName] <a href="https://go.microsoft.com/fwlink/?LinkId=320539">license terms</a> and <a href="https://go.microsoft.com/fwlink/?LinkId=786378">privacy statement</a>. + #(loc.InstallAcceptCheckbox) + + + + + + #(loc.OptionsHeader) + #(loc.OptionsLocationLabel) + + + + + + + #(loc.FilesInUseHeader) + #(loc.FilesInUseLabel) + + + + + + + + + + #(loc.ProgressHeader) + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + + + + + #(loc.ModifyHeader) + + + + + + #(loc.SuccessHeader) + #(loc.SuccessInstallHeader) + #(loc.SuccessRepairHeader) + #(loc.SuccessUninstallHeader) + + #(loc.SuccessRestartText) + + + + + #(loc.FailureHeader) + #(loc.FailureInstallHeader) + #(loc.FailureUninstallHeader) + #(loc.FailureRepairHeader) + #(loc.FailureHyperlinkLogText) + + #(loc.FailureRestartText) + + + + \ No newline at end of file diff --git a/src/Installers/Windows/SharedFrameworkLib/Library.wxs b/src/Installers/Windows/SharedFrameworkLib/Library.wxs new file mode 100644 index 0000000000..e3a367a7e4 --- /dev/null +++ b/src/Installers/Windows/SharedFrameworkLib/Library.wxs @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/SharedFrameworkLib/SharedFrameworkLib.wixproj b/src/Installers/Windows/SharedFrameworkLib/SharedFrameworkLib.wixproj new file mode 100644 index 0000000000..672ca7de66 --- /dev/null +++ b/src/Installers/Windows/SharedFrameworkLib/SharedFrameworkLib.wixproj @@ -0,0 +1,27 @@ + + + + + + AspNetCoreSharedFrameworkLib$(Platform) + $(WixlibBaseFileName)-$(PackageVersion)-win-$(Platform) + Library + true + $(SharedFrameworkNamespaceGuid) + 5244BC49-2568-4701-80A6-EAB8950AB5FA + + + + $(DefineConstants);Debug + + + + + + $(WixExtDir)\WixBalExtension.dll + WixBalExtension + + + + + diff --git a/src/Installers/Windows/WindowsHostingBundle/ANCM.wxs b/src/Installers/Windows/WindowsHostingBundle/ANCM.wxs new file mode 100644 index 0000000000..dd47afe26c --- /dev/null +++ b/src/Installers/Windows/WindowsHostingBundle/ANCM.wxs @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/WindowsHostingBundle/Bundle.wxs b/src/Installers/Windows/WindowsHostingBundle/Bundle.wxs new file mode 100644 index 0000000000..96f43c5515 --- /dev/null +++ b/src/Installers/Windows/WindowsHostingBundle/Bundle.wxs @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/WindowsHostingBundle/DotNetCore.wxs b/src/Installers/Windows/WindowsHostingBundle/DotNetCore.wxs new file mode 100644 index 0000000000..5f017547dd --- /dev/null +++ b/src/Installers/Windows/WindowsHostingBundle/DotNetCore.wxs @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/WindowsHostingBundle/DotNetLogo.bmp b/src/Installers/Windows/WindowsHostingBundle/DotNetLogo.bmp new file mode 100644 index 0000000000..f652d049e8 Binary files /dev/null and b/src/Installers/Windows/WindowsHostingBundle/DotNetLogo.bmp differ diff --git a/src/Installers/Windows/WindowsHostingBundle/Product.props b/src/Installers/Windows/WindowsHostingBundle/Product.props new file mode 100644 index 0000000000..64492e50c9 --- /dev/null +++ b/src/Installers/Windows/WindowsHostingBundle/Product.props @@ -0,0 +1,31 @@ + + + Microsoft .NET Core $(PackageBrandingVersion) + + + + Windows Server Hosting + $(BundleNameShort) - $(BundleNameSub) + $(BundleName) ($(Platform)) + Microsoft Corporation + dd_DotNetCoreWinSvrHosting + + + Microsoft + .NET Core + Microsoft .NET Core $(PackageBrandingVersion) - Windows Server Hosting + $(BundleNameFull) + + + + $(DefineConstants);BundleName=$(BundleName) + $(DefineConstants);BundleNameFull=$(BundleNameFull) + $(DefineConstants);BundleNameShort=$(BundleNameShort) + $(DefineConstants);BundleNameSub=$(BundleNameSub) + $(DefineConstants);BundleManufacturer=$(BundleManufacturer) + $(DefineConstants);BundleLogPrefix=$(BundleLogPrefix) + $(DefineConstants);BundleRegManufacturer=$(BundleRegManufacturer) + $(DefineConstants);BundleRegFamily=$(BundleRegFamily) + $(DefineConstants);BundleRegName=$(BundleRegName) + + diff --git a/src/Installers/Windows/WindowsHostingBundle/Product.targets b/src/Installers/Windows/WindowsHostingBundle/Product.targets new file mode 100644 index 0000000000..038dd250ff --- /dev/null +++ b/src/Installers/Windows/WindowsHostingBundle/Product.targets @@ -0,0 +1,90 @@ + + + $(IntermediateOutputPath)d\ + $(BaseIntermediateOutputPath) + $(DefineConstants);DepsPath=$(DepsPath) + + + + + + x64 + DotNetRedistLtsInstallerx64 + $(MicrosoftNETCoreAppPackageVersion) + + + x86 + DotNetRedistLtsInstallerx86 + $(MicrosoftNETCoreAppPackageVersion) + + + + + + https://dotnetcli.azureedge.net/dotnet/ + $(DotNetAssetRootUrl)/ + + + + + dotnet-runtime-$(MicrosoftNETCoreAppPackageVersion)-win-x64.exe + + + dotnet-runtime-$(MicrosoftNETCoreAppPackageVersion)-win-x86.exe + + + + + + + + + + + + + + + + + + + + + + + + + DotNetRedistLtsInstallerProductVersion%(Platforms.Identity) + DotNetRedistLtsInstallerProductCode%(Platforms.Identity) + DotNetRedistLtsInstallerUpgradeCode%(Platforms.Identity) + + + + + + + + + + + + + + + + $(DefineConstants);DotNetRedistLtsInstallerx64=$(DotNetRedistLtsInstallerx64) + $(DefineConstants);DotNetRedistLtsInstallerProductVersionx64=$(DotNetRedistLtsInstallerProductVersionx64) + $(DefineConstants);DotNetRedistLtsInstallerProductCodex64=$(DotNetRedistLtsInstallerProductCodex64) + $(DefineConstants);DotNetRedistLtsInstallerUpgradeCodex64=$(DotNetRedistLtsInstallerUpgradeCodex64) + $(DefineConstants);DotNetRedistLtsInstallerx86=$(DotNetRedistLtsInstallerx86) + $(DefineConstants);DotNetRedistLtsInstallerProductVersionx86=$(DotNetRedistLtsInstallerProductVersionx86) + $(DefineConstants);DotNetRedistLtsInstallerProductCodex86=$(DotNetRedistLtsInstallerProductCodex86) + $(DefineConstants);DotNetRedistLtsInstallerUpgradeCodex86=$(DotNetRedistLtsInstallerUpgradeCodex86) + + + diff --git a/src/Installers/Windows/WindowsHostingBundle/Strings.wxl b/src/Installers/Windows/WindowsHostingBundle/Strings.wxl new file mode 100644 index 0000000000..069fdd7451 --- /dev/null +++ b/src/Installers/Windows/WindowsHostingBundle/Strings.wxl @@ -0,0 +1,10 @@ + + + Some features that were selected requires .NET 4.5.1. Please install .NET 4.5.1, then install this product again. + This product requires IIS 7.5. Please install IIS, then install this product again. + This product requires Visual Studio 2015 Update 2 or later. Please install Visual Studio 2015 Update 2 or later, then install this product again. + This product requires Visual Studio 2015 Update 3 or later. Please install Visual Studio 2015 Update 3 or later, then install this product again. + Setup has detected that Visual Studio 2015 Update 3 may not be completely installed. Please repair Visual Studio 2015 Update 3, then install this product again. + This product requires the Web Developer Tools feature in Visual Studio 2015. Please enable the feature by going to Programs and Features in Windows, then modify Visual Studio 2015. + This product requires Visual Studio 2015 or Visual Studio Express 2015 for Web to be installed. Please install the missing product, then install this product again. + diff --git a/src/Installers/Windows/WindowsHostingBundle/WindowsHostingBundle.wixproj b/src/Installers/Windows/WindowsHostingBundle/WindowsHostingBundle.wixproj new file mode 100644 index 0000000000..70d2362433 --- /dev/null +++ b/src/Installers/Windows/WindowsHostingBundle/WindowsHostingBundle.wixproj @@ -0,0 +1,43 @@ + + + + + + + + + WindowsServerHostingBundle + dotnet-hosting-$(PackageVersion)-win + 6F1B115C-1903-40CB-837D-7961AB610F4E + Bundle + x86 + + + $(HostingBundleNamespaceGuid) + + + + + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixDependencyExtension.dll + WixDependencyExtension + + + $(WixExtDir)\WixBalExtension.dll + WixBalExtension + + + + + + + + + + + diff --git a/src/Installers/Windows/WindowsHostingBundle/thm.wxl b/src/Installers/Windows/WindowsHostingBundle/thm.wxl new file mode 100644 index 0000000000..87ae937c7d --- /dev/null +++ b/src/Installers/Windows/WindowsHostingBundle/thm.wxl @@ -0,0 +1,61 @@ + + + [WixBundleName] Setup + [BundleNameShort] + [BundleNameSub] + Welcome + Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit. + Version [WixBundleVersion] + Are you sure you want to cancel? + Previous version + Setup Help + /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or + creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and + no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + &Close + [WixBundleName] <a href="#">license terms</a>. + I &agree to the license terms and conditions + &Options + &Install + &Close + Setup Options + Install location: + &Browse + &OK + &Cancel + Setup Progress + Processing: + Initializing... + &Cancel + Modify Setup + &Repair + &Uninstall + &Close + Repair Successfully Completed + Uninstall Successfully Completed + Installation Successfully Completed + Setup Successful + &Launch + You must restart your computer before you can use the software. + &Restart + &Close + Setup Failed + Setup Failed + Uninstall Failed + Repair Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close + Files In Use + The following applications are using files that need to be updated: + Close the &applications and attempt to restart them. + &Do not close applications. A reboot will be required. + &OK + &Cancel + \ No newline at end of file diff --git a/src/Installers/Windows/WindowsHostingBundle/thm.xml b/src/Installers/Windows/WindowsHostingBundle/thm.xml new file mode 100644 index 0000000000..8ca4905b72 --- /dev/null +++ b/src/Installers/Windows/WindowsHostingBundle/thm.xml @@ -0,0 +1,84 @@ + + + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + #(loc.Title) + #(loc.SubTitle) + + + #(loc.HelpHeader) + #(loc.HelpText) + + + + Welcome to the #(loc.Caption). + Please restart IIS after the installation completes. You can find additional information <a href="https://go.microsoft.com/fwlink/?LinkId=798277">here</a>. + IIS is not enabled on this machine. If you intend to run ASP.NET Core applications with IIS, you must install IIS before running this installer. You can find additional information <a href="https://go.microsoft.com/fwlink/?LinkId=798277">here</a>. + [WixBundleName] <a href="https://go.microsoft.com/fwlink/?LinkId=320539">license terms</a> and <a href="https://go.microsoft.com/fwlink/?LinkId=786378">privacy statement</a>. + #(loc.InstallAcceptCheckbox) + + + + + + #(loc.OptionsHeader) + #(loc.OptionsLocationLabel) + + + + + + + #(loc.FilesInUseHeader) + #(loc.FilesInUseLabel) + + + + + + + + + + #(loc.ProgressHeader) + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + + + + + #(loc.ModifyHeader) + Please restart IIS after the installation completes. You can find additional information <a href="https://go.microsoft.com/fwlink/?LinkId=798277">here</a>. + IIS is not enabled on this machine. If you intend to run ASP.NET Core applications with IIS, you must install IIS before running this installer. You can find additional information <a href="https://go.microsoft.com/fwlink/?LinkId=798277">here</a>. + + + + + + #(loc.SuccessHeader) + #(loc.SuccessInstallHeader) + #(loc.SuccessRepairHeader) + #(loc.SuccessUninstallHeader) + + #(loc.SuccessRestartText) + + + + + #(loc.FailureHeader) + #(loc.FailureInstallHeader) + #(loc.FailureUninstallHeader) + #(loc.FailureRepairHeader) + #(loc.FailureHyperlinkLogText) + + #(loc.FailureRestartText) + + + + \ No newline at end of file diff --git a/src/Installers/Windows/WindowsInstallers.proj b/src/Installers/Windows/WindowsInstallers.proj new file mode 100644 index 0000000000..f8b8135b27 --- /dev/null +++ b/src/Installers/Windows/WindowsInstallers.proj @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/Wix.props b/src/Installers/Windows/Wix.props new file mode 100644 index 0000000000..f2737edad2 --- /dev/null +++ b/src/Installers/Windows/Wix.props @@ -0,0 +1,37 @@ + + + + $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(AspNetCorePatchVersion).0 + Release + x64 + ENU + en-US + $(RootOutputPath)bin/$(Configuration)/installers/ + $(BaseOutputPath) + + + + + -fv + ICE61 + 1033 + + + + false + + + E1FD1271-E0F0-4B8B-B4BE-01F2EBA58F4E + C43D5520-11B3-4D62-B6FE-5D6840B04101 + + + + $(DefineConstants);files=$(MSBuildThisFileDirectory)files + $(DefineConstants);Version=$(Version) + $(DefineConstants);Culture=$(Cultures) + $(DefineConstants);MajorVersion=$(AspNetCoreMajorVersion) + $(DefineConstants);MinorVersion=$(AspNetCoreMinorVersion) + $(DefineConstants);PackageVersion=$(PackageVersion) + + + diff --git a/src/Installers/Windows/Wix.targets b/src/Installers/Windows/Wix.targets new file mode 100644 index 0000000000..85eecfa243 --- /dev/null +++ b/src/Installers/Windows/Wix.targets @@ -0,0 +1,43 @@ + + + $(ProductName) + Microsoft.$(ProductNameShort)_$(Platform)_$(Lang),v$(PackageVersion) + $(DefineConstants);DepProviderKey=$(DepProviderKey) + + + + $(Version);$(Platform) + $(GuidInputs);$(BuildNumber) + + + + + + + + + + + + + + + + $(DefineConstants);ProductCode=$(ProductCode);UpgradeCode=$(UpgradeCode) + + + + + + + + + + + + + $(DefineConstants);BundleProviderKey=$(BundleProviderKey);BundleUpgradeCode=$(BundleUpgradeCode) + + + + diff --git a/src/Installers/Windows/build.ps1 b/src/Installers/Windows/build.ps1 new file mode 100644 index 0000000000..c6493b84c2 --- /dev/null +++ b/src/Installers/Windows/build.ps1 @@ -0,0 +1,98 @@ +# +# This script requires internal-only access to the code which generates ANCM installers. +# + +#requires -version 5 +[cmdletbinding()] +param( + [string]$Configuration = 'Debug', + [Parameter(Mandatory = $true)] + [Alias("x86")] + [string]$Runtime86Zip, + [Parameter(Mandatory = $true)] + [Alias("x64")] + [string]$Runtime64Zip, + [string]$BuildNumber = 't000', + [string]$SignType = '', + [string]$PackageVersionPropsUrl = $null, + [string]$AccessTokenSuffix = $null, + [string]$AssetRootUrl = $null, + [switch]$clean +) + +$ErrorActionPreference = 'Stop' +$repoRoot = Resolve-Path "$PSScriptRoot/../../../" +Import-Module -Scope Local "$repoRoot/scripts/common.psm1" -Force +$msbuild = Get-MSBuildPath -Prerelease -requires 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64' + +$harvestRoot = "$repoRoot/obj/sfx/" +if ($clean) { + Remove-Item -Recurse -Force $harvestRoot -ErrorAction Ignore | Out-Null +} + +New-Item "$harvestRoot/x86", "$harvestRoot/x64" -ItemType Directory -ErrorAction Ignore | Out-Null + +if (-not (Test-Path "$harvestRoot/x86/shared/")) { + Expand-Archive $Runtime86Zip -DestinationPath "$harvestRoot/x86" +} + +if (-not (Test-Path "$harvestRoot/x64/shared/")) { + Expand-Archive $Runtime64Zip -DestinationPath "$harvestRoot/x64" +} + +Push-Location $PSScriptRoot +try { + Invoke-Block { & $msbuild ` + tasks/InstallerTasks.csproj ` + -nologo ` + -m ` + -v:m ` + -nodeReuse:false ` + -restore ` + -t:Build ` + "-p:Configuration=$Configuration" + } + + [string[]] $msbuildArgs = @() + + if ($clean) { + $msbuildArgs += '-t:Clean' + } + + if ($AssetRootUrl) { + $msbuildArgs += "-p:DotNetAssetRootUrl=$AssetRootUrl" + } + + if ($AccessTokenSuffix) { + $msbuildArgs += "-p:DotNetAccessTokenSuffix=$AccessTokenSuffix" + } + + if ($PackageVersionPropsUrl) { + $IntermediateDir = Join-Path $PSScriptRoot 'obj' + $PropsFilePath = Join-Path $IntermediateDir 'external-dependencies.props' + New-Item -ItemType Directory $IntermediateDir -ErrorAction Ignore | Out-Null + Get-RemoteFile "${PackageVersionPropsUrl}${AccessTokenSuffix}" $PropsFilePath + $msbuildArgs += "-p:DotNetPackageVersionPropsPath=$PropsFilePath" + } + + $msbuildArgs += '-t:Build' + + Invoke-Block { & $msbuild ` + WindowsInstallers.proj ` + -restore ` + -nologo ` + -m ` + -v:m ` + -nodeReuse:false ` + -clp:Summary ` + "-p:SharedFrameworkHarvestRootPath=$repoRoot/obj/sfx/" ` + "-p:Configuration=$Configuration" ` + "-p:BuildNumber=$BuildNumber" ` + "-p:SignType=$SignType" ` + "-bl:$repoRoot/artifacts/logs/installers.msbuild.binlog" ` + @msbuildArgs + } +} +finally { + Pop-Location +} diff --git a/src/Installers/Windows/files/eula.rtf b/src/Installers/Windows/files/eula.rtf new file mode 100644 index 0000000000..70fb842c6c --- /dev/null +++ b/src/Installers/Windows/files/eula.rtf @@ -0,0 +1,113 @@ +{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033\deflangfe1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 Tahoma;}{\f1\froman\fprq2\fcharset0 Times New Roman;}{\f2\fswiss\fprq2\fcharset0 Calibri;}{\f3\fnil\fcharset2 Symbol;}} +{\colortbl ;\red31\green73\blue125;\red0\green0\blue255;} +{\*\listtable +{\list\listhybrid +{\listlevel\levelnfc0\leveljc0\levelstartat1{\leveltext\'02\'00.;}{\levelnumbers\'01;}\jclisttab\tx360} +{\listlevel\levelnfc4\leveljc0\levelstartat1{\leveltext\'02\'01.;}{\levelnumbers\'01;}\jclisttab\tx363} +{\listlevel\levelnfc2\leveljc0\levelstartat1{\leveltext\'02\'02.;}{\levelnumbers\'01;}\jclisttab\tx720}\listid1 } +{\list\listhybrid +{\listlevel\levelnfc0\leveljc0\levelstartat1{\leveltext\'02\'00.;}{\levelnumbers\'01;}\jclisttab\tx363} +{\listlevel\levelnfc4\leveljc0\levelstartat1{\leveltext\'02\'01.;}{\levelnumbers\'01;}\jclisttab\tx363}\listid2 }} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}} +{\*\generator Riched20 6.3.9600}{\*\mmathPr\mnaryLim0\mdispDef1\mwrapIndent1440 }\viewkind4\uc1 +\pard\nowidctlpar\sb120\sa120\b\f0\fs24 MICROSOFT SOFTWARE LICENSE TERMS\par + +\pard\brdrb\brdrs\brdrw10\brsp20 \nowidctlpar\sb120\sa120 MICROSOFT .NET LIBRARY \par + +\pard\nowidctlpar\sb120\sa120\fs19 These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. Please read them. They apply to the software named above, which includes the media on which you received it, if any. The terms also apply to any Microsoft\par + +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent363{\pntxtb\'B7}}\nowidctlpar\fi-363\li720\sb120\sa120\b0 updates,\par +{\pntext\f3\'B7\tab}supplements,\par +{\pntext\f3\'B7\tab}Internet-based services, and\par +{\pntext\f3\'B7\tab}support services\par + +\pard\nowidctlpar\sb120\sa120\b for this software, unless other terms accompany those items. If so, those terms apply.\par +BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE.\par + +\pard\brdrt\brdrs\brdrw10\brsp20 \nowidctlpar\sb120\sa120 IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE PERPETUAL RIGHTS BELOW.\par + +\pard +{\listtext\f0 1.\tab}\jclisttab\tx360\ls1\nowidctlpar\fi-357\li357\sb120\sa120 INSTALLATION AND USE RIGHTS. \par + +\pard +{\listtext\f0 a.\tab}\jclisttab\tx363\ls1\ilvl1\nowidctlpar\fi-363\li720\sb120\sa120 Installation and Use.\b0\fs20 You may install and use any number of copies of the software to design, develop and test your programs.\par +{\listtext\f0 b.\tab}\b\fs19 Third Party Programs.\b0\fs20 The software may include third party programs that Microsoft, not the third party, licenses to you under this agreement. Notices, if any, for the third party program are included for your information only.\b\fs19\par + +\pard +{\listtext\f0 2.\tab}\jclisttab\tx360\ls1\nowidctlpar\fi-357\li357\sb120\sa120\fs20 ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS.\par + +\pard +{\listtext\f0 a.\tab}\jclisttab\tx363\ls1\ilvl1\nowidctlpar\fi-363\li720\sb120\sa120 DISTRIBUTABLE CODE.\~ \b0 The software is comprised of Distributable Code. \f1\ldblquote\f0 Distributable Code\f1\rdblquote\f0 is code that you are permitted to distribute in programs you develop if you comply with the terms below.\b\par + +\pard +{\listtext\f0 i.\tab}\jclisttab\tx720\ls1\ilvl2\nowidctlpar\fi-357\li1077\sb120\sa120\tx1077 Right to Use and Distribute. \par + +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent360{\pntxtb\'B7}}\nowidctlpar\fi-357\li1434\sb120\sa120\b0 You may copy and distribute the object code form of the software.\par +{\pntext\f3\'B7\tab}Third Party Distribution. You may permit distributors of your programs to copy and distribute the Distributable Code as part of those programs.\par + +\pard\nowidctlpar\fi-357\li1077\sb120\sa120\tx1077\b ii.\tab Distribution Requirements.\b0 \b For any Distributable Code you distribute, you must\par + +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent360{\pntxtb\'B7}}\nowidctlpar\fi-357\li1434\sb120\sa120\b0 add significant primary functionality to it in your programs;\par +{\pntext\f3\'B7\tab}require distributors and external end users to agree to terms that protect it at least as much as this agreement;\par +{\pntext\f3\'B7\tab}display your valid copyright notice on your programs; and\par +{\pntext\f3\'B7\tab}indemnify, defend, and hold harmless Microsoft from any claims, including attorneys\rquote fees, related to the distribution or use of your programs.\par + +\pard\nowidctlpar\fi-357\li1077\sb120\sa120\tx1077\b iii.\tab Distribution Restrictions.\b0 \b You may not\par + +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent360{\pntxtb\'B7}}\nowidctlpar\fi-357\li1434\sb120\sa120\b0 alter any copyright, trademark or patent notice in the Distributable Code;\par +{\pntext\f3\'B7\tab}use Microsoft\rquote s trademarks in your programs\rquote names or in a way that suggests your programs come from or are endorsed by Microsoft;\par +{\pntext\f3\'B7\tab}include Distributable Code in malicious, deceptive or unlawful programs; or\par +{\pntext\f3\'B7\tab}modify or distribute the source code of any Distributable Code so that any part of it becomes subject to an Excluded License. An Excluded License is one that requires, as a condition of use, modification or distribution, that\par + +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent360{\pntxtb\'B7}}\nowidctlpar\fi-358\li1792\sb120\sa120 the code be disclosed or distributed in source code form; or\cf1\f2\par +{\pntext\f3\'B7\tab}\cf0\f0 others have the right to modify it.\cf1\f2\par + +\pard\nowidctlpar\fi-357\li357\sb120\sa120\cf0\b\f0 3.\tab\fs19 SCOPE OF LICENSE. \b0 The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not\par + +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent363{\pntxtb\'B7}}\nowidctlpar\fi-363\li720\sb120\sa120 work around any technical limitations in the software;\par +{\pntext\f3\'B7\tab}reverse engineer, decompile or disassemble the software, except and only to the extent that applicable law expressly permits, despite this limitation;\par +{\pntext\f3\'B7\tab}publish the software for others to copy;\par +{\pntext\f3\'B7\tab}rent, lease or lend the software;\par +{\pntext\f3\'B7\tab}transfer the software or this agreement to any third party; or\par +{\pntext\f3\'B7\tab}use the software for commercial software hosting services.\par + +\pard\nowidctlpar\fi-357\li357\sb120\sa120\b\fs20 4.\tab\fs19 BACKUP COPY. \b0 You may make one backup copy of the software. You may use it only to reinstall the software.\par +\b\fs20 5.\tab\fs19 DOCUMENTATION. \b0 Any person that has valid access to your computer or internal network may copy and use the documentation for your internal, reference purposes.\par +\b\fs20 6.\tab\fs19 EXPORT RESTRICTIONS. \b0 The software is subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the software. These laws include restrictions on destinations, end users and end use. For additional information, see {\fs20{\field{\*\fldinst{HYPERLINK www.microsoft.com/exporting }}{\fldrslt{www.microsoft.com/exporting\ul0\cf0}}}}\f0\fs19 .\fs20\par +\b 7.\tab\fs19 SUPPORT SERVICES. \b0 Because this software is \ldblquote as is,\rdblquote we may not provide support services for it.\par +\b\fs20 8.\tab\fs19 ENTIRE AGREEMENT. \b0 This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services.\par +\b\fs20 9.\tab\fs19 APPLICABLE LAW.\par + +\pard +{\listtext\f0 a.\tab}\jclisttab\tx363\ls2\ilvl1\nowidctlpar\fi-363\li720\sb120\sa120 United States. \b0 If you acquired the software in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort.\par +{\listtext\f0 b.\tab}\b Outside the United States. If you acquired the software in any other country, the laws of that country apply.\par + +\pard +{\pntext\f0 1.\tab}{\*\pn\pnlvlbody\pnf0\pnindent360\pnstart1\pndec{\pntxta.}} +\nowidctlpar\fi-357\li357\sb120\sa120 LEGAL EFFECT. \b0 This agreement describes certain legal rights. You may have other rights under the laws of your country. You may also have rights with respect to the party from whom you acquired the software. This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so.\par +{\pntext\f0 2.\tab}\b DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED \ldblquote AS-IS.\rdblquote YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. YOU MAY HAVE ADDITIONAL CONSUMER RIGHTS OR STATUTORY GUARANTEES UNDER YOUR LOCAL LAWS WHICH THIS AGREEMENT CANNOT CHANGE. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.\par + +\pard\nowidctlpar\li357\sb120\sa120 FOR AUSTRALIA \endash YOU HAVE STATUTORY GUARANTEES UNDER THE AUSTRALIAN CONSUMER LAW AND NOTHING IN THESE TERMS IS INTENDED TO AFFECT THOSE RIGHTS.\par + +\pard\nowidctlpar\fi-357\li357\sb120\sa120\fs20 12.\tab\fs19 LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.\par + +\pard\nowidctlpar\li357\sb120\sa120\b0 This limitation applies to\par + +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent363{\pntxtb\'B7}}\nowidctlpar\fi-363\li720\sb120\sa120 anything related to the software, services, content (including code) on third party Internet sites, or third party programs; and\par +{\pntext\f3\'B7\tab}claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.\par + +\pard\nowidctlpar\sb120\sa120 It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.\par +\lang9 Please note: As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French.\par +Remarque : Ce logiciel \'e9tant distribu\'e9 au Qu\'e9bec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en fran\'e7ais.\par +\b\lang1033 EXON\'c9RATION DE GARANTIE. \b0 Le logiciel vis\'e9 par une licence est offert \'ab tel quel \'bb. Toute utilisation de ce logiciel est \'e0 votre seule risque et p\'e9ril. Microsoft n\rquote accorde aucune autre garantie expresse. Vous pouvez b\'e9n\'e9ficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualit\'e9 marchande, d\rquote ad\'e9quation \'e0 un usage particulier et d\rquote absence de contrefa\'e7on sont exclues.\par +\b LIMITATION DES DOMMAGES-INT\'c9R\'caTS ET EXCLUSION DE RESPONSABILIT\'c9 POUR LES DOMMAGES. \b0 Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement \'e0 hauteur de 5,00 $ US. Vous ne pouvez pr\'e9tendre \'e0 aucune indemnisation pour les autres dommages, y compris les dommages sp\'e9ciaux, indirects ou accessoires et pertes de b\'e9n\'e9fices.\par +\lang9 Cette limitation concerne :\par + +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent360{\pntxtb\'B7}}\nowidctlpar\li720\sb120\sa120 tout ce qui est reli\'e9 au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et\par +{\pntext\f3\'B7\tab}les r\'e9clamations au titre de violation de contrat ou de garantie, ou au titre de responsabilit\'e9 stricte, de n\'e9gligence ou d\rquote une autre faute dans la limite autoris\'e9e par la loi en vigueur.\par + +\pard\nowidctlpar\sb120\sa120 Elle s\rquote applique \'e9galement, m\'eame si Microsoft connaissait ou devrait conna\'eetre l\rquote\'e9ventualit\'e9 d\rquote un tel dommage. Si votre pays n\rquote autorise pas l\rquote exclusion ou la limitation de responsabilit\'e9 pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l\rquote exclusion ci-dessus ne s\rquote appliquera pas \'e0 votre \'e9gard.\par +\b\lang1033 EFFET JURIDIQUE. \b0 Le pr\'e9sent contrat d\'e9crit certains droits juridiques. Vous pourriez avoir d\rquote autres droits pr\'e9vus par les lois de votre pays. Le pr\'e9sent contrat ne modifie pas les droits que vous conf\'e8rent les lois de votre pays si celles-ci ne le permettent pas.\par +\b\fs20\lang1036\par +} + \ No newline at end of file diff --git a/src/Installers/Windows/tasks/GenerateGuid.cs b/src/Installers/Windows/tasks/GenerateGuid.cs new file mode 100644 index 0000000000..f6e8039864 --- /dev/null +++ b/src/Installers/Windows/tasks/GenerateGuid.cs @@ -0,0 +1,38 @@ +// 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.Build.Framework; +using Microsoft.Build.Utilities; + +namespace RepoTasks +{ + public class GenerateGuid : Task + { + [Output] + public string Guid { get; private set; } + + [Required] + public string NamespaceGuid { get; set; } + + [Required] + public ITaskItem[] Values { get; set; } + + public override bool Execute() + { + try + { + var value = string.Join(",", Values.Select(o => o.ItemSpec).ToArray()).ToLowerInvariant(); + + Guid = Uuid.Create(new Guid(NamespaceGuid), value).ToString(); + } + catch (Exception e) + { + Log.LogErrorFromException(e); + } + + return !Log.HasLoggedErrors; + } + } +} diff --git a/src/Installers/Windows/tasks/GetMsiProperty.cs b/src/Installers/Windows/tasks/GetMsiProperty.cs new file mode 100644 index 0000000000..90f3cd3d24 --- /dev/null +++ b/src/Installers/Windows/tasks/GetMsiProperty.cs @@ -0,0 +1,38 @@ +// 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 Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Microsoft.Deployment.WindowsInstaller.Package; + +namespace RepoTasks +{ + public class GetMsiProperty : Task + { + [Required] + public string InstallPackage { get; set; } + + [Required] + public string Property { get; set; } + + [Output] + public string Value { get; set; } + + public override bool Execute() + { + try + { + using (var package = new InstallPackage(InstallPackage, 0)) + { + Value = package.Property[Property]; + } + } + catch (Exception exception) + { + Log.LogErrorFromException(exception); + } + return !Log.HasLoggedErrors; + } + } +} diff --git a/src/Installers/Windows/tasks/InstallerTasks.csproj b/src/Installers/Windows/tasks/InstallerTasks.csproj new file mode 100644 index 0000000000..a6d3ce18f1 --- /dev/null +++ b/src/Installers/Windows/tasks/InstallerTasks.csproj @@ -0,0 +1,23 @@ + + + + net461 + false + false + + + + + + + + + + $(WiXSdkPath)\Microsoft.Deployment.WindowsInstaller.dll + + + $(WiXSdkPath)\Microsoft.Deployment.WindowsInstaller.Package.dll + + + + diff --git a/src/Installers/Windows/tasks/Uuid.cs b/src/Installers/Windows/tasks/Uuid.cs new file mode 100644 index 0000000000..8083117d38 --- /dev/null +++ b/src/Installers/Windows/tasks/Uuid.cs @@ -0,0 +1,79 @@ +// 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.Net; +using System.Security.Cryptography; +using System.Text; + +namespace RepoTasks +{ + /// + /// Implementation of RFC 4122 - A Universally Unique Identifier (UUID) URN Namespace. + /// + internal sealed class Uuid + { + /// + /// Generates a version 3 UUID given a namespace UUID and name. This is based on the algorithm described in + /// RFC 4122 (http://www.apps.ietf.org/rfc/rfc4122.html), section 4.3. + /// + /// + /// + /// + public static Guid Create(Guid namespaceId, string name) + { + // 1. Convert the name to a canonical sequence of octets (as defined by the standards or conventions of its name space); put the name space ID in network byte order. + byte[] namespaceBytes = namespaceId.ToByteArray(); + // Octet 0-3 + int timeLow = IPAddress.HostToNetworkOrder(BitConverter.ToInt32(namespaceBytes, 0)); + // Octet 4-5 + short timeMid = IPAddress.HostToNetworkOrder(BitConverter.ToInt16(namespaceBytes, 4)); + // Octet 6-7 + short timeHiVersion = IPAddress.HostToNetworkOrder(BitConverter.ToInt16(namespaceBytes, 6)); + + // 2. Compute the hash of the namespace ID concatenated with the name + byte[] nameBytes = Encoding.Unicode.GetBytes(name); + byte[] hashBuffer = new byte[namespaceBytes.Length + nameBytes.Length]; + + Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, hashBuffer, 0, 4); + Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, hashBuffer, 4, 2); + Buffer.BlockCopy(BitConverter.GetBytes(timeHiVersion), 0, hashBuffer, 6, 2); + Buffer.BlockCopy(namespaceBytes, 8, hashBuffer, 8, 8); + Buffer.BlockCopy(nameBytes, 0, hashBuffer, 16, nameBytes.Length); + byte[] hash; + + using (SHA256 sha256 = new SHA256Managed()) + { + hash = sha256.ComputeHash(hashBuffer); + } + + Array.Resize(ref hash, 16); + + // 3. Set octets zero through 3 of the time_low field to octets zero through 3 of the hash. + timeLow = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(hash, 0)); + Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, hash, 0, 4); + + // 4. Set octets zero and one of the time_mid field to octets 4 and 5 of the hash. + timeMid = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(hash, 4)); + Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, hash, 4, 2); + + // 5. Set octets zero and one of the time_hi_and_version field to octets 6 and 7 of the hash. + timeHiVersion = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(hash, 6)); + + // 6. Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the appropriate 4-bit version number from Section 4.1.3. + timeHiVersion = (short)((timeHiVersion & 0x0fff) | 0x3000); + Buffer.BlockCopy(BitConverter.GetBytes(timeHiVersion), 0, hash, 6, 2); + + // 7. Set the clock_seq_hi_and_reserved field to octet 8 of the hash. + // 8. Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively. + hash[8] = (byte)((hash[8] & 0x3f) | 0x80); + + // Steps 9-11 are essentially no-ops, but provided for completion sake + // 9. Set the clock_seq_low field to octet 9 of the hash. + // 10. Set octets zero through five of the node field to octets 10 through 15 of the hash. + // 11. Convert the resulting UUID to local byte order. + + return new Guid(hash); + } + } +} diff --git a/src/PackageArchive/Archive.CiServer.Patch.Compat/Archive.CiServer.Patch.Compat.zipproj b/src/PackageArchive/Archive.CiServer.Patch.Compat/Archive.CiServer.Patch.Compat.zipproj new file mode 100644 index 0000000000..55592e1dfa --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch.Compat/Archive.CiServer.Patch.Compat.zipproj @@ -0,0 +1,14 @@ + + + + + + + nuGetPackagesArchive-ci-server-compat-$(PackageVersion).patch.zip + true + false + true + + + + diff --git a/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.1.txt b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.1.txt new file mode 100644 index 0000000000..502b30a472 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.1.txt @@ -0,0 +1,6581 @@ +libuv\1.10.0\libuv.1.10.0.nupkg +libuv\1.10.0\libuv.1.10.0.nupkg.sha512 +libuv\1.10.0\libuv.nuspec +libuv\1.10.0\License.txt +libuv\1.10.0\runtimes\linux-arm\native\libuv.so +libuv\1.10.0\runtimes\linux-arm64\native\libuv.so +libuv\1.10.0\runtimes\linux-armel\native\libuv.so +libuv\1.10.0\runtimes\linux-x64\native\libuv.so +libuv\1.10.0\runtimes\osx\native\libuv.dylib +libuv\1.10.0\runtimes\win-arm\native\libuv.dll +libuv\1.10.0\runtimes\win-x64\native\libuv.dll +libuv\1.10.0\runtimes\win-x86\native\libuv.dll +messagepack\1.7.3.4\lib\net45\MessagePack.dll +messagepack\1.7.3.4\lib\net47\MessagePack.dll +messagepack\1.7.3.4\lib\netstandard1.6\MessagePack.dll +messagepack\1.7.3.4\lib\netstandard2.0\MessagePack.dll +messagepack\1.7.3.4\messagepack.1.7.3.4.nupkg +messagepack\1.7.3.4\messagepack.1.7.3.4.nupkg.sha512 +messagepack\1.7.3.4\messagepack.nuspec +microsoft.applicationinsights.aspnetcore\2.1.1\lib\net451\Microsoft.ApplicationInsights.AspNetCore.dll +microsoft.applicationinsights.aspnetcore\2.1.1\lib\netstandard1.6\Microsoft.ApplicationInsights.AspNetCore.dll +microsoft.applicationinsights.aspnetcore\2.1.1\microsoft.applicationinsights.aspnetcore.2.1.1.nupkg +microsoft.applicationinsights.aspnetcore\2.1.1\microsoft.applicationinsights.aspnetcore.2.1.1.nupkg.sha512 +microsoft.applicationinsights.aspnetcore\2.1.1\microsoft.applicationinsights.aspnetcore.nuspec +microsoft.applicationinsights.dependencycollector\2.4.1\content\ApplicationInsights.config.install.xdt +microsoft.applicationinsights.dependencycollector\2.4.1\content\ApplicationInsights.config.transform +microsoft.applicationinsights.dependencycollector\2.4.1\content\ApplicationInsights.config.uninstall.xdt +microsoft.applicationinsights.dependencycollector\2.4.1\lib\net40\Microsoft.AI.DependencyCollector.dll +microsoft.applicationinsights.dependencycollector\2.4.1\lib\net45\Microsoft.AI.DependencyCollector.dll +microsoft.applicationinsights.dependencycollector\2.4.1\lib\netstandard1.6\Microsoft.AI.DependencyCollector.dll +microsoft.applicationinsights.dependencycollector\2.4.1\microsoft.applicationinsights.dependencycollector.2.4.1.nupkg +microsoft.applicationinsights.dependencycollector\2.4.1\microsoft.applicationinsights.dependencycollector.2.4.1.nupkg.sha512 +microsoft.applicationinsights.dependencycollector\2.4.1\microsoft.applicationinsights.dependencycollector.nuspec +microsoft.applicationinsights\2.4.0\lib\net40\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\net45\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\net46\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\netstandard1.3\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\portable-win81+wpa81\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\uap10.0\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\wp8\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\microsoft.applicationinsights.2.4.0.nupkg +microsoft.applicationinsights\2.4.0\microsoft.applicationinsights.2.4.0.nupkg.sha512 +microsoft.applicationinsights\2.4.0\microsoft.applicationinsights.nuspec +microsoft.aspnet.webapi.client\5.2.6\.signature.p7s +microsoft.aspnet.webapi.client\5.2.6\lib\net45\System.Net.Http.Formatting.dll +microsoft.aspnet.webapi.client\5.2.6\lib\netstandard2.0\System.Net.Http.Formatting.dll +microsoft.aspnet.webapi.client\5.2.6\lib\portable-wp8+netcore45+net45+wp81+wpa81\System.Net.Http.Formatting.dll +microsoft.aspnet.webapi.client\5.2.6\microsoft.aspnet.webapi.client.5.2.6.nupkg +microsoft.aspnet.webapi.client\5.2.6\microsoft.aspnet.webapi.client.5.2.6.nupkg.sha512 +microsoft.aspnet.webapi.client\5.2.6\microsoft.aspnet.webapi.client.nuspec +microsoft.aspnetcore.all\2.1.1\.signature.p7s +microsoft.aspnetcore.all\2.1.1\build\netcoreapp2.1\Microsoft.AspNetCore.All.props +microsoft.aspnetcore.all\2.1.1\build\netcoreapp2.1\Microsoft.AspNetCore.All.targets +microsoft.aspnetcore.all\2.1.1\lib\netcoreapp2.1\_._ +microsoft.aspnetcore.all\2.1.1\microsoft.aspnetcore.all.2.1.1.nupkg +microsoft.aspnetcore.all\2.1.1\microsoft.aspnetcore.all.2.1.1.nupkg.sha512 +microsoft.aspnetcore.all\2.1.1\microsoft.aspnetcore.all.nuspec +microsoft.aspnetcore.antiforgery\2.1.1\.signature.p7s +microsoft.aspnetcore.antiforgery\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Antiforgery.dll +microsoft.aspnetcore.antiforgery\2.1.1\microsoft.aspnetcore.antiforgery.2.1.1.nupkg +microsoft.aspnetcore.antiforgery\2.1.1\microsoft.aspnetcore.antiforgery.2.1.1.nupkg.sha512 +microsoft.aspnetcore.antiforgery\2.1.1\microsoft.aspnetcore.antiforgery.nuspec +microsoft.aspnetcore.app\2.1.1\.signature.p7s +microsoft.aspnetcore.app\2.1.1\build\netcoreapp2.1\Microsoft.AspNetCore.App.props +microsoft.aspnetcore.app\2.1.1\build\netcoreapp2.1\Microsoft.AspNetCore.App.targets +microsoft.aspnetcore.app\2.1.1\lib\netcoreapp2.1\_._ +microsoft.aspnetcore.app\2.1.1\microsoft.aspnetcore.app.2.1.1.nupkg +microsoft.aspnetcore.app\2.1.1\microsoft.aspnetcore.app.2.1.1.nupkg.sha512 +microsoft.aspnetcore.app\2.1.1\microsoft.aspnetcore.app.nuspec +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\.signature.p7s +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\lib\net461\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\lib\netcoreapp2.0\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\microsoft.aspnetcore.applicationinsights.hostingstartup.2.1.1.nupkg +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\microsoft.aspnetcore.applicationinsights.hostingstartup.2.1.1.nupkg.sha512 +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\microsoft.aspnetcore.applicationinsights.hostingstartup.nuspec +microsoft.aspnetcore.authentication.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Abstractions.dll +microsoft.aspnetcore.authentication.abstractions\2.1.1\microsoft.aspnetcore.authentication.abstractions.2.1.1.nupkg +microsoft.aspnetcore.authentication.abstractions\2.1.1\microsoft.aspnetcore.authentication.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.abstractions\2.1.1\microsoft.aspnetcore.authentication.abstractions.nuspec +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureAD.UI.dll +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureAD.UI.Views.dll +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\microsoft.aspnetcore.authentication.azuread.ui.2.1.1.nupkg +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\microsoft.aspnetcore.authentication.azuread.ui.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\microsoft.aspnetcore.authentication.azuread.ui.nuspec +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.dll +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Views.dll +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\microsoft.aspnetcore.authentication.azureadb2c.ui.2.1.1.nupkg +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\microsoft.aspnetcore.authentication.azureadb2c.ui.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\microsoft.aspnetcore.authentication.azureadb2c.ui.nuspec +microsoft.aspnetcore.authentication.cookies\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.cookies\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Cookies.dll +microsoft.aspnetcore.authentication.cookies\2.1.1\microsoft.aspnetcore.authentication.cookies.2.1.1.nupkg +microsoft.aspnetcore.authentication.cookies\2.1.1\microsoft.aspnetcore.authentication.cookies.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.cookies\2.1.1\microsoft.aspnetcore.authentication.cookies.nuspec +microsoft.aspnetcore.authentication.core\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.core\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Core.dll +microsoft.aspnetcore.authentication.core\2.1.1\microsoft.aspnetcore.authentication.core.2.1.1.nupkg +microsoft.aspnetcore.authentication.core\2.1.1\microsoft.aspnetcore.authentication.core.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.core\2.1.1\microsoft.aspnetcore.authentication.core.nuspec +microsoft.aspnetcore.authentication.facebook\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.facebook\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Facebook.dll +microsoft.aspnetcore.authentication.facebook\2.1.1\microsoft.aspnetcore.authentication.facebook.2.1.1.nupkg +microsoft.aspnetcore.authentication.facebook\2.1.1\microsoft.aspnetcore.authentication.facebook.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.facebook\2.1.1\microsoft.aspnetcore.authentication.facebook.nuspec +microsoft.aspnetcore.authentication.google\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.google\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Google.dll +microsoft.aspnetcore.authentication.google\2.1.1\microsoft.aspnetcore.authentication.google.2.1.1.nupkg +microsoft.aspnetcore.authentication.google\2.1.1\microsoft.aspnetcore.authentication.google.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.google\2.1.1\microsoft.aspnetcore.authentication.google.nuspec +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.JwtBearer.dll +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\microsoft.aspnetcore.authentication.jwtbearer.2.1.1.nupkg +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\microsoft.aspnetcore.authentication.jwtbearer.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\microsoft.aspnetcore.authentication.jwtbearer.nuspec +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.MicrosoftAccount.dll +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\microsoft.aspnetcore.authentication.microsoftaccount.2.1.1.nupkg +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\microsoft.aspnetcore.authentication.microsoftaccount.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\microsoft.aspnetcore.authentication.microsoftaccount.nuspec +microsoft.aspnetcore.authentication.oauth\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.oauth\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.OAuth.dll +microsoft.aspnetcore.authentication.oauth\2.1.1\microsoft.aspnetcore.authentication.oauth.2.1.1.nupkg +microsoft.aspnetcore.authentication.oauth\2.1.1\microsoft.aspnetcore.authentication.oauth.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.oauth\2.1.1\microsoft.aspnetcore.authentication.oauth.nuspec +microsoft.aspnetcore.authentication.openidconnect\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.openidconnect\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.OpenIdConnect.dll +microsoft.aspnetcore.authentication.openidconnect\2.1.1\microsoft.aspnetcore.authentication.openidconnect.2.1.1.nupkg +microsoft.aspnetcore.authentication.openidconnect\2.1.1\microsoft.aspnetcore.authentication.openidconnect.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.openidconnect\2.1.1\microsoft.aspnetcore.authentication.openidconnect.nuspec +microsoft.aspnetcore.authentication.twitter\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.twitter\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Twitter.dll +microsoft.aspnetcore.authentication.twitter\2.1.1\microsoft.aspnetcore.authentication.twitter.2.1.1.nupkg +microsoft.aspnetcore.authentication.twitter\2.1.1\microsoft.aspnetcore.authentication.twitter.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.twitter\2.1.1\microsoft.aspnetcore.authentication.twitter.nuspec +microsoft.aspnetcore.authentication.wsfederation\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.wsfederation\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.WsFederation.dll +microsoft.aspnetcore.authentication.wsfederation\2.1.1\microsoft.aspnetcore.authentication.wsfederation.2.1.1.nupkg +microsoft.aspnetcore.authentication.wsfederation\2.1.1\microsoft.aspnetcore.authentication.wsfederation.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.wsfederation\2.1.1\microsoft.aspnetcore.authentication.wsfederation.nuspec +microsoft.aspnetcore.authentication\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.dll +microsoft.aspnetcore.authentication\2.1.1\microsoft.aspnetcore.authentication.2.1.1.nupkg +microsoft.aspnetcore.authentication\2.1.1\microsoft.aspnetcore.authentication.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication\2.1.1\microsoft.aspnetcore.authentication.nuspec +microsoft.aspnetcore.authorization.policy\2.1.1\.signature.p7s +microsoft.aspnetcore.authorization.policy\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.Policy.dll +microsoft.aspnetcore.authorization.policy\2.1.1\microsoft.aspnetcore.authorization.policy.2.1.1.nupkg +microsoft.aspnetcore.authorization.policy\2.1.1\microsoft.aspnetcore.authorization.policy.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authorization.policy\2.1.1\microsoft.aspnetcore.authorization.policy.nuspec +microsoft.aspnetcore.authorization\2.1.1\.signature.p7s +microsoft.aspnetcore.authorization\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.dll +microsoft.aspnetcore.authorization\2.1.1\microsoft.aspnetcore.authorization.2.1.1.nupkg +microsoft.aspnetcore.authorization\2.1.1\microsoft.aspnetcore.authorization.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authorization\2.1.1\microsoft.aspnetcore.authorization.nuspec +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\.signature.p7s +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\lib\net461\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\lib\netcoreapp2.0\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\microsoft.aspnetcore.azureappservices.hostingstartup.2.1.1.nupkg +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\microsoft.aspnetcore.azureappservices.hostingstartup.2.1.1.nupkg.sha512 +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\microsoft.aspnetcore.azureappservices.hostingstartup.nuspec +microsoft.aspnetcore.azureappservicesintegration\2.1.1\.signature.p7s +microsoft.aspnetcore.azureappservicesintegration\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.AzureAppServicesIntegration.dll +microsoft.aspnetcore.azureappservicesintegration\2.1.1\microsoft.aspnetcore.azureappservicesintegration.2.1.1.nupkg +microsoft.aspnetcore.azureappservicesintegration\2.1.1\microsoft.aspnetcore.azureappservicesintegration.2.1.1.nupkg.sha512 +microsoft.aspnetcore.azureappservicesintegration\2.1.1\microsoft.aspnetcore.azureappservicesintegration.nuspec +microsoft.aspnetcore.connections.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.connections.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Connections.Abstractions.dll +microsoft.aspnetcore.connections.abstractions\2.1.1\microsoft.aspnetcore.connections.abstractions.2.1.1.nupkg +microsoft.aspnetcore.connections.abstractions\2.1.1\microsoft.aspnetcore.connections.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.connections.abstractions\2.1.1\microsoft.aspnetcore.connections.abstractions.nuspec +microsoft.aspnetcore.cookiepolicy\2.1.1\.signature.p7s +microsoft.aspnetcore.cookiepolicy\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.CookiePolicy.dll +microsoft.aspnetcore.cookiepolicy\2.1.1\microsoft.aspnetcore.cookiepolicy.2.1.1.nupkg +microsoft.aspnetcore.cookiepolicy\2.1.1\microsoft.aspnetcore.cookiepolicy.2.1.1.nupkg.sha512 +microsoft.aspnetcore.cookiepolicy\2.1.1\microsoft.aspnetcore.cookiepolicy.nuspec +microsoft.aspnetcore.cors\2.1.1\.signature.p7s +microsoft.aspnetcore.cors\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Cors.dll +microsoft.aspnetcore.cors\2.1.1\microsoft.aspnetcore.cors.2.1.1.nupkg +microsoft.aspnetcore.cors\2.1.1\microsoft.aspnetcore.cors.2.1.1.nupkg.sha512 +microsoft.aspnetcore.cors\2.1.1\microsoft.aspnetcore.cors.nuspec +microsoft.aspnetcore.cryptography.internal\2.1.1\.signature.p7s +microsoft.aspnetcore.cryptography.internal\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.Internal.dll +microsoft.aspnetcore.cryptography.internal\2.1.1\microsoft.aspnetcore.cryptography.internal.2.1.1.nupkg +microsoft.aspnetcore.cryptography.internal\2.1.1\microsoft.aspnetcore.cryptography.internal.2.1.1.nupkg.sha512 +microsoft.aspnetcore.cryptography.internal\2.1.1\microsoft.aspnetcore.cryptography.internal.nuspec +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\.signature.p7s +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\lib\netcoreapp2.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\microsoft.aspnetcore.cryptography.keyderivation.2.1.1.nupkg +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\microsoft.aspnetcore.cryptography.keyderivation.2.1.1.nupkg.sha512 +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\microsoft.aspnetcore.cryptography.keyderivation.nuspec +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Abstractions.dll +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\microsoft.aspnetcore.dataprotection.abstractions.2.1.1.nupkg +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\microsoft.aspnetcore.dataprotection.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\microsoft.aspnetcore.dataprotection.abstractions.nuspec +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.AzureKeyVault.dll +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\microsoft.aspnetcore.dataprotection.azurekeyvault.2.1.1.nupkg +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\microsoft.aspnetcore.dataprotection.azurekeyvault.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\microsoft.aspnetcore.dataprotection.azurekeyvault.nuspec +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.AzureStorage.dll +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\microsoft.aspnetcore.dataprotection.azurestorage.2.1.1.nupkg +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\microsoft.aspnetcore.dataprotection.azurestorage.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\microsoft.aspnetcore.dataprotection.azurestorage.nuspec +microsoft.aspnetcore.dataprotection.extensions\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection.extensions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Extensions.dll +microsoft.aspnetcore.dataprotection.extensions\2.1.1\microsoft.aspnetcore.dataprotection.extensions.2.1.1.nupkg +microsoft.aspnetcore.dataprotection.extensions\2.1.1\microsoft.aspnetcore.dataprotection.extensions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection.extensions\2.1.1\microsoft.aspnetcore.dataprotection.extensions.nuspec +microsoft.aspnetcore.dataprotection\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.dll +microsoft.aspnetcore.dataprotection\2.1.1\microsoft.aspnetcore.dataprotection.2.1.1.nupkg +microsoft.aspnetcore.dataprotection\2.1.1\microsoft.aspnetcore.dataprotection.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection\2.1.1\microsoft.aspnetcore.dataprotection.nuspec +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.Abstractions.dll +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\microsoft.aspnetcore.diagnostics.abstractions.2.1.1.nupkg +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\microsoft.aspnetcore.diagnostics.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\microsoft.aspnetcore.diagnostics.abstractions.nuspec +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\.signature.p7s +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.dll +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\microsoft.aspnetcore.diagnostics.entityframeworkcore.2.1.1.nupkg +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\microsoft.aspnetcore.diagnostics.entityframeworkcore.2.1.1.nupkg.sha512 +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\microsoft.aspnetcore.diagnostics.entityframeworkcore.nuspec +microsoft.aspnetcore.diagnostics\2.1.1\.signature.p7s +microsoft.aspnetcore.diagnostics\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.dll +microsoft.aspnetcore.diagnostics\2.1.1\microsoft.aspnetcore.diagnostics.2.1.1.nupkg +microsoft.aspnetcore.diagnostics\2.1.1\microsoft.aspnetcore.diagnostics.2.1.1.nupkg.sha512 +microsoft.aspnetcore.diagnostics\2.1.1\microsoft.aspnetcore.diagnostics.nuspec +microsoft.aspnetcore.hostfiltering\2.1.1\.signature.p7s +microsoft.aspnetcore.hostfiltering\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.HostFiltering.dll +microsoft.aspnetcore.hostfiltering\2.1.1\microsoft.aspnetcore.hostfiltering.2.1.1.nupkg +microsoft.aspnetcore.hostfiltering\2.1.1\microsoft.aspnetcore.hostfiltering.2.1.1.nupkg.sha512 +microsoft.aspnetcore.hostfiltering\2.1.1\microsoft.aspnetcore.hostfiltering.nuspec +microsoft.aspnetcore.hosting.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.hosting.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll +microsoft.aspnetcore.hosting.abstractions\2.1.1\microsoft.aspnetcore.hosting.abstractions.2.1.1.nupkg +microsoft.aspnetcore.hosting.abstractions\2.1.1\microsoft.aspnetcore.hosting.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.hosting.abstractions\2.1.1\microsoft.aspnetcore.hosting.abstractions.nuspec +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\microsoft.aspnetcore.hosting.server.abstractions.2.1.1.nupkg +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\microsoft.aspnetcore.hosting.server.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\microsoft.aspnetcore.hosting.server.abstractions.nuspec +microsoft.aspnetcore.hosting\2.1.1\.signature.p7s +microsoft.aspnetcore.hosting\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.dll +microsoft.aspnetcore.hosting\2.1.1\microsoft.aspnetcore.hosting.2.1.1.nupkg +microsoft.aspnetcore.hosting\2.1.1\microsoft.aspnetcore.hosting.2.1.1.nupkg.sha512 +microsoft.aspnetcore.hosting\2.1.1\microsoft.aspnetcore.hosting.nuspec +microsoft.aspnetcore.html.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.html.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Html.Abstractions.dll +microsoft.aspnetcore.html.abstractions\2.1.1\microsoft.aspnetcore.html.abstractions.2.1.1.nupkg +microsoft.aspnetcore.html.abstractions\2.1.1\microsoft.aspnetcore.html.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.html.abstractions\2.1.1\microsoft.aspnetcore.html.abstractions.nuspec +microsoft.aspnetcore.http.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.http.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll +microsoft.aspnetcore.http.abstractions\2.1.1\microsoft.aspnetcore.http.abstractions.2.1.1.nupkg +microsoft.aspnetcore.http.abstractions\2.1.1\microsoft.aspnetcore.http.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.http.abstractions\2.1.1\microsoft.aspnetcore.http.abstractions.nuspec +microsoft.aspnetcore.http.connections.common\1.0.1\.signature.p7s +microsoft.aspnetcore.http.connections.common\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Connections.Common.dll +microsoft.aspnetcore.http.connections.common\1.0.1\microsoft.aspnetcore.http.connections.common.1.0.1.nupkg +microsoft.aspnetcore.http.connections.common\1.0.1\microsoft.aspnetcore.http.connections.common.1.0.1.nupkg.sha512 +microsoft.aspnetcore.http.connections.common\1.0.1\microsoft.aspnetcore.http.connections.common.nuspec +microsoft.aspnetcore.http.connections\1.0.1\.signature.p7s +microsoft.aspnetcore.http.connections\1.0.1\lib\netcoreapp2.1\Microsoft.AspNetCore.Http.Connections.dll +microsoft.aspnetcore.http.connections\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Connections.dll +microsoft.aspnetcore.http.connections\1.0.1\microsoft.aspnetcore.http.connections.1.0.1.nupkg +microsoft.aspnetcore.http.connections\1.0.1\microsoft.aspnetcore.http.connections.1.0.1.nupkg.sha512 +microsoft.aspnetcore.http.connections\1.0.1\microsoft.aspnetcore.http.connections.nuspec +microsoft.aspnetcore.http.extensions\2.1.1\.signature.p7s +microsoft.aspnetcore.http.extensions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll +microsoft.aspnetcore.http.extensions\2.1.1\microsoft.aspnetcore.http.extensions.2.1.1.nupkg +microsoft.aspnetcore.http.extensions\2.1.1\microsoft.aspnetcore.http.extensions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.http.extensions\2.1.1\microsoft.aspnetcore.http.extensions.nuspec +microsoft.aspnetcore.http.features\2.1.1\.signature.p7s +microsoft.aspnetcore.http.features\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll +microsoft.aspnetcore.http.features\2.1.1\microsoft.aspnetcore.http.features.2.1.1.nupkg +microsoft.aspnetcore.http.features\2.1.1\microsoft.aspnetcore.http.features.2.1.1.nupkg.sha512 +microsoft.aspnetcore.http.features\2.1.1\microsoft.aspnetcore.http.features.nuspec +microsoft.aspnetcore.http\2.1.1\.signature.p7s +microsoft.aspnetcore.http\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.dll +microsoft.aspnetcore.http\2.1.1\microsoft.aspnetcore.http.2.1.1.nupkg +microsoft.aspnetcore.http\2.1.1\microsoft.aspnetcore.http.2.1.1.nupkg.sha512 +microsoft.aspnetcore.http\2.1.1\microsoft.aspnetcore.http.nuspec +microsoft.aspnetcore.httpoverrides\2.1.1\.signature.p7s +microsoft.aspnetcore.httpoverrides\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.HttpOverrides.dll +microsoft.aspnetcore.httpoverrides\2.1.1\microsoft.aspnetcore.httpoverrides.2.1.1.nupkg +microsoft.aspnetcore.httpoverrides\2.1.1\microsoft.aspnetcore.httpoverrides.2.1.1.nupkg.sha512 +microsoft.aspnetcore.httpoverrides\2.1.1\microsoft.aspnetcore.httpoverrides.nuspec +microsoft.aspnetcore.httpspolicy\2.1.1\.signature.p7s +microsoft.aspnetcore.httpspolicy\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.HttpsPolicy.dll +microsoft.aspnetcore.httpspolicy\2.1.1\microsoft.aspnetcore.httpspolicy.2.1.1.nupkg +microsoft.aspnetcore.httpspolicy\2.1.1\microsoft.aspnetcore.httpspolicy.2.1.1.nupkg.sha512 +microsoft.aspnetcore.httpspolicy\2.1.1\microsoft.aspnetcore.httpspolicy.nuspec +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\.signature.p7s +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\microsoft.aspnetcore.identity.entityframeworkcore.2.1.1.nupkg +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\microsoft.aspnetcore.identity.entityframeworkcore.2.1.1.nupkg.sha512 +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\microsoft.aspnetcore.identity.entityframeworkcore.nuspec +microsoft.aspnetcore.identity.ui\2.1.1\.signature.p7s +microsoft.aspnetcore.identity.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.dll +microsoft.aspnetcore.identity.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.Views.dll +microsoft.aspnetcore.identity.ui\2.1.1\microsoft.aspnetcore.identity.ui.2.1.1.nupkg +microsoft.aspnetcore.identity.ui\2.1.1\microsoft.aspnetcore.identity.ui.2.1.1.nupkg.sha512 +microsoft.aspnetcore.identity.ui\2.1.1\microsoft.aspnetcore.identity.ui.nuspec +microsoft.aspnetcore.identity.ui\2.1.1\THIRD-PARTY-NOTICES +microsoft.aspnetcore.identity\2.1.1\.signature.p7s +microsoft.aspnetcore.identity\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Identity.dll +microsoft.aspnetcore.identity\2.1.1\microsoft.aspnetcore.identity.2.1.1.nupkg +microsoft.aspnetcore.identity\2.1.1\microsoft.aspnetcore.identity.2.1.1.nupkg.sha512 +microsoft.aspnetcore.identity\2.1.1\microsoft.aspnetcore.identity.nuspec +microsoft.aspnetcore.jsonpatch\2.1.1\.signature.p7s +microsoft.aspnetcore.jsonpatch\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.JsonPatch.dll +microsoft.aspnetcore.jsonpatch\2.1.1\microsoft.aspnetcore.jsonpatch.2.1.1.nupkg +microsoft.aspnetcore.jsonpatch\2.1.1\microsoft.aspnetcore.jsonpatch.2.1.1.nupkg.sha512 +microsoft.aspnetcore.jsonpatch\2.1.1\microsoft.aspnetcore.jsonpatch.nuspec +microsoft.aspnetcore.localization.routing\2.1.1\.signature.p7s +microsoft.aspnetcore.localization.routing\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Localization.Routing.dll +microsoft.aspnetcore.localization.routing\2.1.1\microsoft.aspnetcore.localization.routing.2.1.1.nupkg +microsoft.aspnetcore.localization.routing\2.1.1\microsoft.aspnetcore.localization.routing.2.1.1.nupkg.sha512 +microsoft.aspnetcore.localization.routing\2.1.1\microsoft.aspnetcore.localization.routing.nuspec +microsoft.aspnetcore.localization\2.1.1\.signature.p7s +microsoft.aspnetcore.localization\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Localization.dll +microsoft.aspnetcore.localization\2.1.1\microsoft.aspnetcore.localization.2.1.1.nupkg +microsoft.aspnetcore.localization\2.1.1\microsoft.aspnetcore.localization.2.1.1.nupkg.sha512 +microsoft.aspnetcore.localization\2.1.1\microsoft.aspnetcore.localization.nuspec +microsoft.aspnetcore.middlewareanalysis\2.1.1\.signature.p7s +microsoft.aspnetcore.middlewareanalysis\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.MiddlewareAnalysis.dll +microsoft.aspnetcore.middlewareanalysis\2.1.1\microsoft.aspnetcore.middlewareanalysis.2.1.1.nupkg +microsoft.aspnetcore.middlewareanalysis\2.1.1\microsoft.aspnetcore.middlewareanalysis.2.1.1.nupkg.sha512 +microsoft.aspnetcore.middlewareanalysis\2.1.1\microsoft.aspnetcore.middlewareanalysis.nuspec +microsoft.aspnetcore.mvc.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Abstractions.dll +microsoft.aspnetcore.mvc.abstractions\2.1.1\microsoft.aspnetcore.mvc.abstractions.2.1.1.nupkg +microsoft.aspnetcore.mvc.abstractions\2.1.1\microsoft.aspnetcore.mvc.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.abstractions\2.1.1\microsoft.aspnetcore.mvc.abstractions.nuspec +microsoft.aspnetcore.mvc.analyzers\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.analyzers\2.1.1\analyzers\dotnet\cs\Microsoft.AspNetCore.Mvc.Analyzers.dll +microsoft.aspnetcore.mvc.analyzers\2.1.1\microsoft.aspnetcore.mvc.analyzers.2.1.1.nupkg +microsoft.aspnetcore.mvc.analyzers\2.1.1\microsoft.aspnetcore.mvc.analyzers.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.analyzers\2.1.1\microsoft.aspnetcore.mvc.analyzers.nuspec +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ApiExplorer.dll +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\microsoft.aspnetcore.mvc.apiexplorer.2.1.1.nupkg +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\microsoft.aspnetcore.mvc.apiexplorer.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\microsoft.aspnetcore.mvc.apiexplorer.nuspec +microsoft.aspnetcore.mvc.core\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.core\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll +microsoft.aspnetcore.mvc.core\2.1.1\microsoft.aspnetcore.mvc.core.2.1.1.nupkg +microsoft.aspnetcore.mvc.core\2.1.1\microsoft.aspnetcore.mvc.core.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.core\2.1.1\microsoft.aspnetcore.mvc.core.nuspec +microsoft.aspnetcore.mvc.cors\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.cors\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Cors.dll +microsoft.aspnetcore.mvc.cors\2.1.1\microsoft.aspnetcore.mvc.cors.2.1.1.nupkg +microsoft.aspnetcore.mvc.cors\2.1.1\microsoft.aspnetcore.mvc.cors.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.cors\2.1.1\microsoft.aspnetcore.mvc.cors.nuspec +microsoft.aspnetcore.mvc.dataannotations\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.dataannotations\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.DataAnnotations.dll +microsoft.aspnetcore.mvc.dataannotations\2.1.1\microsoft.aspnetcore.mvc.dataannotations.2.1.1.nupkg +microsoft.aspnetcore.mvc.dataannotations\2.1.1\microsoft.aspnetcore.mvc.dataannotations.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.dataannotations\2.1.1\microsoft.aspnetcore.mvc.dataannotations.nuspec +microsoft.aspnetcore.mvc.formatters.json\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.formatters.json\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Formatters.Json.dll +microsoft.aspnetcore.mvc.formatters.json\2.1.1\microsoft.aspnetcore.mvc.formatters.json.2.1.1.nupkg +microsoft.aspnetcore.mvc.formatters.json\2.1.1\microsoft.aspnetcore.mvc.formatters.json.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.formatters.json\2.1.1\microsoft.aspnetcore.mvc.formatters.json.nuspec +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Formatters.Xml.dll +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\microsoft.aspnetcore.mvc.formatters.xml.2.1.1.nupkg +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\microsoft.aspnetcore.mvc.formatters.xml.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\microsoft.aspnetcore.mvc.formatters.xml.nuspec +microsoft.aspnetcore.mvc.localization\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.localization\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Localization.dll +microsoft.aspnetcore.mvc.localization\2.1.1\microsoft.aspnetcore.mvc.localization.2.1.1.nupkg +microsoft.aspnetcore.mvc.localization\2.1.1\microsoft.aspnetcore.mvc.localization.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.localization\2.1.1\microsoft.aspnetcore.mvc.localization.nuspec +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.props +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.targets +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\lib\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\microsoft.aspnetcore.mvc.razor.extensions.2.1.1.nupkg +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\microsoft.aspnetcore.mvc.razor.extensions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\microsoft.aspnetcore.mvc.razor.extensions.nuspec +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation-x64.exe +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation-x86.exe +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.dll +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.targets +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.Tasks.dll +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\microsoft.aspnetcore.mvc.razor.viewcompilation.2.1.1.nupkg +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\microsoft.aspnetcore.mvc.razor.viewcompilation.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\microsoft.aspnetcore.mvc.razor.viewcompilation.nuspec +microsoft.aspnetcore.mvc.razor\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.razor\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.dll +microsoft.aspnetcore.mvc.razor\2.1.1\microsoft.aspnetcore.mvc.razor.2.1.1.nupkg +microsoft.aspnetcore.mvc.razor\2.1.1\microsoft.aspnetcore.mvc.razor.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.razor\2.1.1\microsoft.aspnetcore.mvc.razor.nuspec +microsoft.aspnetcore.mvc.razorpages\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.razorpages\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.RazorPages.dll +microsoft.aspnetcore.mvc.razorpages\2.1.1\microsoft.aspnetcore.mvc.razorpages.2.1.1.nupkg +microsoft.aspnetcore.mvc.razorpages\2.1.1\microsoft.aspnetcore.mvc.razorpages.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.razorpages\2.1.1\microsoft.aspnetcore.mvc.razorpages.nuspec +microsoft.aspnetcore.mvc.taghelpers\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.taghelpers\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.TagHelpers.dll +microsoft.aspnetcore.mvc.taghelpers\2.1.1\microsoft.aspnetcore.mvc.taghelpers.2.1.1.nupkg +microsoft.aspnetcore.mvc.taghelpers\2.1.1\microsoft.aspnetcore.mvc.taghelpers.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.taghelpers\2.1.1\microsoft.aspnetcore.mvc.taghelpers.nuspec +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ViewFeatures.dll +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\microsoft.aspnetcore.mvc.viewfeatures.2.1.1.nupkg +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\microsoft.aspnetcore.mvc.viewfeatures.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\microsoft.aspnetcore.mvc.viewfeatures.nuspec +microsoft.aspnetcore.mvc\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.dll +microsoft.aspnetcore.mvc\2.1.1\microsoft.aspnetcore.mvc.2.1.1.nupkg +microsoft.aspnetcore.mvc\2.1.1\microsoft.aspnetcore.mvc.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc\2.1.1\microsoft.aspnetcore.mvc.nuspec +microsoft.aspnetcore.nodeservices\2.1.1\.signature.p7s +microsoft.aspnetcore.nodeservices\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.NodeServices.dll +microsoft.aspnetcore.nodeservices\2.1.1\microsoft.aspnetcore.nodeservices.2.1.1.nupkg +microsoft.aspnetcore.nodeservices\2.1.1\microsoft.aspnetcore.nodeservices.2.1.1.nupkg.sha512 +microsoft.aspnetcore.nodeservices\2.1.1\microsoft.aspnetcore.nodeservices.nuspec +microsoft.aspnetcore.owin\2.1.1\.signature.p7s +microsoft.aspnetcore.owin\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Owin.dll +microsoft.aspnetcore.owin\2.1.1\microsoft.aspnetcore.owin.2.1.1.nupkg +microsoft.aspnetcore.owin\2.1.1\microsoft.aspnetcore.owin.2.1.1.nupkg.sha512 +microsoft.aspnetcore.owin\2.1.1\microsoft.aspnetcore.owin.nuspec +microsoft.aspnetcore.razor.design\2.1.1\.signature.p7s +microsoft.aspnetcore.razor.design\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets +microsoft.aspnetcore.razor.design\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.1.1\buildMultiTargeting\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.1.1\microsoft.aspnetcore.razor.design.2.1.1.nupkg +microsoft.aspnetcore.razor.design\2.1.1\microsoft.aspnetcore.razor.design.2.1.1.nupkg.sha512 +microsoft.aspnetcore.razor.design\2.1.1\microsoft.aspnetcore.razor.design.nuspec +microsoft.aspnetcore.razor.design\2.1.1\tasks\net46\Microsoft.AspNetCore.Razor.Tasks.dll +microsoft.aspnetcore.razor.design\2.1.1\tasks\netstandard2.0\Microsoft.AspNetCore.Razor.Tasks.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Microsoft.CodeAnalysis.CSharp.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Microsoft.CodeAnalysis.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Microsoft.CodeAnalysis.Razor.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Newtonsoft.Json.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\runtimes\unix\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\rzc.deps.json +microsoft.aspnetcore.razor.design\2.1.1\tools\rzc.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\rzc.runtimeconfig.json +microsoft.aspnetcore.razor.language\2.1.1\.signature.p7s +microsoft.aspnetcore.razor.language\2.1.1\lib\net46\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.language\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.language\2.1.1\microsoft.aspnetcore.razor.language.2.1.1.nupkg +microsoft.aspnetcore.razor.language\2.1.1\microsoft.aspnetcore.razor.language.2.1.1.nupkg.sha512 +microsoft.aspnetcore.razor.language\2.1.1\microsoft.aspnetcore.razor.language.nuspec +microsoft.aspnetcore.razor.runtime\2.1.1\.signature.p7s +microsoft.aspnetcore.razor.runtime\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Razor.Runtime.dll +microsoft.aspnetcore.razor.runtime\2.1.1\microsoft.aspnetcore.razor.runtime.2.1.1.nupkg +microsoft.aspnetcore.razor.runtime\2.1.1\microsoft.aspnetcore.razor.runtime.2.1.1.nupkg.sha512 +microsoft.aspnetcore.razor.runtime\2.1.1\microsoft.aspnetcore.razor.runtime.nuspec +microsoft.aspnetcore.razor\2.1.1\.signature.p7s +microsoft.aspnetcore.razor\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Razor.dll +microsoft.aspnetcore.razor\2.1.1\microsoft.aspnetcore.razor.2.1.1.nupkg +microsoft.aspnetcore.razor\2.1.1\microsoft.aspnetcore.razor.2.1.1.nupkg.sha512 +microsoft.aspnetcore.razor\2.1.1\microsoft.aspnetcore.razor.nuspec +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCaching.Abstractions.dll +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\microsoft.aspnetcore.responsecaching.abstractions.2.1.1.nupkg +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\microsoft.aspnetcore.responsecaching.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\microsoft.aspnetcore.responsecaching.abstractions.nuspec +microsoft.aspnetcore.responsecaching\2.1.1\.signature.p7s +microsoft.aspnetcore.responsecaching\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCaching.dll +microsoft.aspnetcore.responsecaching\2.1.1\microsoft.aspnetcore.responsecaching.2.1.1.nupkg +microsoft.aspnetcore.responsecaching\2.1.1\microsoft.aspnetcore.responsecaching.2.1.1.nupkg.sha512 +microsoft.aspnetcore.responsecaching\2.1.1\microsoft.aspnetcore.responsecaching.nuspec +microsoft.aspnetcore.responsecompression\2.1.1\.signature.p7s +microsoft.aspnetcore.responsecompression\2.1.1\lib\net461\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.1.1\microsoft.aspnetcore.responsecompression.2.1.1.nupkg +microsoft.aspnetcore.responsecompression\2.1.1\microsoft.aspnetcore.responsecompression.2.1.1.nupkg.sha512 +microsoft.aspnetcore.responsecompression\2.1.1\microsoft.aspnetcore.responsecompression.nuspec +microsoft.aspnetcore.rewrite\2.1.1\.signature.p7s +microsoft.aspnetcore.rewrite\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Rewrite.dll +microsoft.aspnetcore.rewrite\2.1.1\microsoft.aspnetcore.rewrite.2.1.1.nupkg +microsoft.aspnetcore.rewrite\2.1.1\microsoft.aspnetcore.rewrite.2.1.1.nupkg.sha512 +microsoft.aspnetcore.rewrite\2.1.1\microsoft.aspnetcore.rewrite.nuspec +microsoft.aspnetcore.routing.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.routing.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Routing.Abstractions.dll +microsoft.aspnetcore.routing.abstractions\2.1.1\microsoft.aspnetcore.routing.abstractions.2.1.1.nupkg +microsoft.aspnetcore.routing.abstractions\2.1.1\microsoft.aspnetcore.routing.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.routing.abstractions\2.1.1\microsoft.aspnetcore.routing.abstractions.nuspec +microsoft.aspnetcore.routing\2.1.1\.signature.p7s +microsoft.aspnetcore.routing\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Routing.dll +microsoft.aspnetcore.routing\2.1.1\microsoft.aspnetcore.routing.2.1.1.nupkg +microsoft.aspnetcore.routing\2.1.1\microsoft.aspnetcore.routing.2.1.1.nupkg.sha512 +microsoft.aspnetcore.routing\2.1.1\microsoft.aspnetcore.routing.nuspec +microsoft.aspnetcore.server.httpsys\2.1.1\.signature.p7s +microsoft.aspnetcore.server.httpsys\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.HttpSys.dll +microsoft.aspnetcore.server.httpsys\2.1.1\microsoft.aspnetcore.server.httpsys.2.1.1.nupkg +microsoft.aspnetcore.server.httpsys\2.1.1\microsoft.aspnetcore.server.httpsys.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.httpsys\2.1.1\microsoft.aspnetcore.server.httpsys.nuspec +microsoft.aspnetcore.server.iisintegration\2.1.1\.signature.p7s +microsoft.aspnetcore.server.iisintegration\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.IISIntegration.dll +microsoft.aspnetcore.server.iisintegration\2.1.1\microsoft.aspnetcore.server.iisintegration.2.1.1.nupkg +microsoft.aspnetcore.server.iisintegration\2.1.1\microsoft.aspnetcore.server.iisintegration.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.iisintegration\2.1.1\microsoft.aspnetcore.server.iisintegration.nuspec +microsoft.aspnetcore.server.kestrel.core\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.core\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Core.dll +microsoft.aspnetcore.server.kestrel.core\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll +microsoft.aspnetcore.server.kestrel.core\2.1.1\microsoft.aspnetcore.server.kestrel.core.2.1.1.nupkg +microsoft.aspnetcore.server.kestrel.core\2.1.1\microsoft.aspnetcore.server.kestrel.core.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.core\2.1.1\microsoft.aspnetcore.server.kestrel.core.nuspec +microsoft.aspnetcore.server.kestrel.https\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.https\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Https.dll +microsoft.aspnetcore.server.kestrel.https\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Https.dll +microsoft.aspnetcore.server.kestrel.https\2.1.1\microsoft.aspnetcore.server.kestrel.https.2.1.1.nupkg +microsoft.aspnetcore.server.kestrel.https\2.1.1\microsoft.aspnetcore.server.kestrel.https.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.https\2.1.1\microsoft.aspnetcore.server.kestrel.https.nuspec +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\microsoft.aspnetcore.server.kestrel.transport.abstractions.2.1.1.nupkg +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\microsoft.aspnetcore.server.kestrel.transport.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\microsoft.aspnetcore.server.kestrel.transport.abstractions.nuspec +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\microsoft.aspnetcore.server.kestrel.transport.libuv.2.1.1.nupkg +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\microsoft.aspnetcore.server.kestrel.transport.libuv.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\microsoft.aspnetcore.server.kestrel.transport.libuv.nuspec +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\microsoft.aspnetcore.server.kestrel.transport.sockets.2.1.1.nupkg +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\microsoft.aspnetcore.server.kestrel.transport.sockets.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\microsoft.aspnetcore.server.kestrel.transport.sockets.nuspec +microsoft.aspnetcore.server.kestrel\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.dll +microsoft.aspnetcore.server.kestrel\2.1.1\microsoft.aspnetcore.server.kestrel.2.1.1.nupkg +microsoft.aspnetcore.server.kestrel\2.1.1\microsoft.aspnetcore.server.kestrel.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel\2.1.1\microsoft.aspnetcore.server.kestrel.nuspec +microsoft.aspnetcore.session\2.1.1\.signature.p7s +microsoft.aspnetcore.session\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Session.dll +microsoft.aspnetcore.session\2.1.1\microsoft.aspnetcore.session.2.1.1.nupkg +microsoft.aspnetcore.session\2.1.1\microsoft.aspnetcore.session.2.1.1.nupkg.sha512 +microsoft.aspnetcore.session\2.1.1\microsoft.aspnetcore.session.nuspec +microsoft.aspnetcore.signalr.common\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr.common\1.0.1\lib\netcoreapp2.1\Microsoft.AspNetCore.SignalR.Common.dll +microsoft.aspnetcore.signalr.common\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Common.dll +microsoft.aspnetcore.signalr.common\1.0.1\microsoft.aspnetcore.signalr.common.1.0.1.nupkg +microsoft.aspnetcore.signalr.common\1.0.1\microsoft.aspnetcore.signalr.common.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr.common\1.0.1\microsoft.aspnetcore.signalr.common.nuspec +microsoft.aspnetcore.signalr.core\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr.core\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Core.dll +microsoft.aspnetcore.signalr.core\1.0.1\microsoft.aspnetcore.signalr.core.1.0.1.nupkg +microsoft.aspnetcore.signalr.core\1.0.1\microsoft.aspnetcore.signalr.core.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr.core\1.0.1\microsoft.aspnetcore.signalr.core.nuspec +microsoft.aspnetcore.signalr.protocols.json\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr.protocols.json\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Protocols.Json.dll +microsoft.aspnetcore.signalr.protocols.json\1.0.1\microsoft.aspnetcore.signalr.protocols.json.1.0.1.nupkg +microsoft.aspnetcore.signalr.protocols.json\1.0.1\microsoft.aspnetcore.signalr.protocols.json.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr.protocols.json\1.0.1\microsoft.aspnetcore.signalr.protocols.json.nuspec +microsoft.aspnetcore.signalr.redis\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr.redis\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Redis.dll +microsoft.aspnetcore.signalr.redis\1.0.1\microsoft.aspnetcore.signalr.redis.1.0.1.nupkg +microsoft.aspnetcore.signalr.redis\1.0.1\microsoft.aspnetcore.signalr.redis.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr.redis\1.0.1\microsoft.aspnetcore.signalr.redis.nuspec +microsoft.aspnetcore.signalr\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.dll +microsoft.aspnetcore.signalr\1.0.1\microsoft.aspnetcore.signalr.1.0.1.nupkg +microsoft.aspnetcore.signalr\1.0.1\microsoft.aspnetcore.signalr.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr\1.0.1\microsoft.aspnetcore.signalr.nuspec +microsoft.aspnetcore.spaservices.extensions\2.1.1\.signature.p7s +microsoft.aspnetcore.spaservices.extensions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.SpaServices.Extensions.dll +microsoft.aspnetcore.spaservices.extensions\2.1.1\microsoft.aspnetcore.spaservices.extensions.2.1.1.nupkg +microsoft.aspnetcore.spaservices.extensions\2.1.1\microsoft.aspnetcore.spaservices.extensions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.spaservices.extensions\2.1.1\microsoft.aspnetcore.spaservices.extensions.nuspec +microsoft.aspnetcore.spaservices\2.1.1\.signature.p7s +microsoft.aspnetcore.spaservices\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.SpaServices.dll +microsoft.aspnetcore.spaservices\2.1.1\microsoft.aspnetcore.spaservices.2.1.1.nupkg +microsoft.aspnetcore.spaservices\2.1.1\microsoft.aspnetcore.spaservices.2.1.1.nupkg.sha512 +microsoft.aspnetcore.spaservices\2.1.1\microsoft.aspnetcore.spaservices.nuspec +microsoft.aspnetcore.staticfiles\2.1.1\.signature.p7s +microsoft.aspnetcore.staticfiles\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.StaticFiles.dll +microsoft.aspnetcore.staticfiles\2.1.1\microsoft.aspnetcore.staticfiles.2.1.1.nupkg +microsoft.aspnetcore.staticfiles\2.1.1\microsoft.aspnetcore.staticfiles.2.1.1.nupkg.sha512 +microsoft.aspnetcore.staticfiles\2.1.1\microsoft.aspnetcore.staticfiles.nuspec +microsoft.aspnetcore.websockets\2.1.1\.signature.p7s +microsoft.aspnetcore.websockets\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.WebSockets.dll +microsoft.aspnetcore.websockets\2.1.1\microsoft.aspnetcore.websockets.2.1.1.nupkg +microsoft.aspnetcore.websockets\2.1.1\microsoft.aspnetcore.websockets.2.1.1.nupkg.sha512 +microsoft.aspnetcore.websockets\2.1.1\microsoft.aspnetcore.websockets.nuspec +microsoft.aspnetcore.webutilities\2.1.1\.signature.p7s +microsoft.aspnetcore.webutilities\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.WebUtilities.dll +microsoft.aspnetcore.webutilities\2.1.1\microsoft.aspnetcore.webutilities.2.1.1.nupkg +microsoft.aspnetcore.webutilities\2.1.1\microsoft.aspnetcore.webutilities.2.1.1.nupkg.sha512 +microsoft.aspnetcore.webutilities\2.1.1\microsoft.aspnetcore.webutilities.nuspec +microsoft.aspnetcore\2.1.1\.signature.p7s +microsoft.aspnetcore\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.dll +microsoft.aspnetcore\2.1.1\microsoft.aspnetcore.2.1.1.nupkg +microsoft.aspnetcore\2.1.1\microsoft.aspnetcore.2.1.1.nupkg.sha512 +microsoft.aspnetcore\2.1.1\microsoft.aspnetcore.nuspec +microsoft.azure.keyvault.webkey\2.0.7\lib\net452\Microsoft.Azure.KeyVault.WebKey.dll +microsoft.azure.keyvault.webkey\2.0.7\lib\net452\Microsoft.Azure.KeyVault.WebKey.runtimeconfig.json +microsoft.azure.keyvault.webkey\2.0.7\lib\netstandard1.4\Microsoft.Azure.KeyVault.WebKey.dll +microsoft.azure.keyvault.webkey\2.0.7\lib\netstandard1.4\Microsoft.Azure.KeyVault.WebKey.runtimeconfig.json +microsoft.azure.keyvault.webkey\2.0.7\microsoft.azure.keyvault.webkey.2.0.7.nupkg +microsoft.azure.keyvault.webkey\2.0.7\microsoft.azure.keyvault.webkey.2.0.7.nupkg.sha512 +microsoft.azure.keyvault.webkey\2.0.7\microsoft.azure.keyvault.webkey.nuspec +microsoft.azure.keyvault\2.3.2\lib\net452\Microsoft.Azure.KeyVault.dll +microsoft.azure.keyvault\2.3.2\lib\net452\Microsoft.Azure.KeyVault.runtimeconfig.json +microsoft.azure.keyvault\2.3.2\lib\netstandard1.4\Microsoft.Azure.KeyVault.dll +microsoft.azure.keyvault\2.3.2\lib\netstandard1.4\Microsoft.Azure.KeyVault.runtimeconfig.json +microsoft.azure.keyvault\2.3.2\microsoft.azure.keyvault.2.3.2.nupkg +microsoft.azure.keyvault\2.3.2\microsoft.azure.keyvault.2.3.2.nupkg.sha512 +microsoft.azure.keyvault\2.3.2\microsoft.azure.keyvault.nuspec +microsoft.azure.services.appauthentication\1.0.1\build\Microsoft.Azure.Services.AppAuthentication.targets +microsoft.azure.services.appauthentication\1.0.1\lib\net452\Microsoft.Azure.Services.AppAuthentication.dll +microsoft.azure.services.appauthentication\1.0.1\lib\net452\Microsoft.Azure.Services.AppAuthentication.runtimeconfig.json +microsoft.azure.services.appauthentication\1.0.1\lib\netstandard1.4\Microsoft.Azure.Services.AppAuthentication.dll +microsoft.azure.services.appauthentication\1.0.1\lib\netstandard1.4\Microsoft.Azure.Services.AppAuthentication.runtimeconfig.json +microsoft.azure.services.appauthentication\1.0.1\microsoft.azure.services.appauthentication.1.0.1.nupkg +microsoft.azure.services.appauthentication\1.0.1\microsoft.azure.services.appauthentication.1.0.1.nupkg.sha512 +microsoft.azure.services.appauthentication\1.0.1\microsoft.azure.services.appauthentication.nuspec +microsoft.codeanalysis.analyzers\1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll +microsoft.codeanalysis.analyzers\1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll +microsoft.codeanalysis.analyzers\1.1.0\analyzers\dotnet\vb\Microsoft.CodeAnalysis.Analyzers.dll +microsoft.codeanalysis.analyzers\1.1.0\analyzers\dotnet\vb\Microsoft.CodeAnalysis.VisualBasic.Analyzers.dll +microsoft.codeanalysis.analyzers\1.1.0\microsoft.codeanalysis.analyzers.1.1.0.nupkg +microsoft.codeanalysis.analyzers\1.1.0\microsoft.codeanalysis.analyzers.1.1.0.nupkg.sha512 +microsoft.codeanalysis.analyzers\1.1.0\microsoft.codeanalysis.analyzers.nuspec +microsoft.codeanalysis.analyzers\1.1.0\ThirdPartyNotices.rtf +microsoft.codeanalysis.analyzers\1.1.0\tools\install.ps1 +microsoft.codeanalysis.analyzers\1.1.0\tools\uninstall.ps1 +microsoft.codeanalysis.common\2.8.0\.signature.p7s +microsoft.codeanalysis.common\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.dll +microsoft.codeanalysis.common\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.pdb +microsoft.codeanalysis.common\2.8.0\microsoft.codeanalysis.common.2.8.0.nupkg +microsoft.codeanalysis.common\2.8.0\microsoft.codeanalysis.common.2.8.0.nupkg.sha512 +microsoft.codeanalysis.common\2.8.0\microsoft.codeanalysis.common.nuspec +microsoft.codeanalysis.csharp.workspaces\2.8.0\.signature.p7s +microsoft.codeanalysis.csharp.workspaces\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Workspaces.dll +microsoft.codeanalysis.csharp.workspaces\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Workspaces.pdb +microsoft.codeanalysis.csharp.workspaces\2.8.0\microsoft.codeanalysis.csharp.workspaces.2.8.0.nupkg +microsoft.codeanalysis.csharp.workspaces\2.8.0\microsoft.codeanalysis.csharp.workspaces.2.8.0.nupkg.sha512 +microsoft.codeanalysis.csharp.workspaces\2.8.0\microsoft.codeanalysis.csharp.workspaces.nuspec +microsoft.codeanalysis.csharp\2.8.0\.signature.p7s +microsoft.codeanalysis.csharp\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll +microsoft.codeanalysis.csharp\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.pdb +microsoft.codeanalysis.csharp\2.8.0\microsoft.codeanalysis.csharp.2.8.0.nupkg +microsoft.codeanalysis.csharp\2.8.0\microsoft.codeanalysis.csharp.2.8.0.nupkg.sha512 +microsoft.codeanalysis.csharp\2.8.0\microsoft.codeanalysis.csharp.nuspec +microsoft.codeanalysis.razor\2.1.1\.signature.p7s +microsoft.codeanalysis.razor\2.1.1\lib\net46\Microsoft.CodeAnalysis.Razor.dll +microsoft.codeanalysis.razor\2.1.1\lib\netstandard2.0\Microsoft.CodeAnalysis.Razor.dll +microsoft.codeanalysis.razor\2.1.1\microsoft.codeanalysis.razor.2.1.1.nupkg +microsoft.codeanalysis.razor\2.1.1\microsoft.codeanalysis.razor.2.1.1.nupkg.sha512 +microsoft.codeanalysis.razor\2.1.1\microsoft.codeanalysis.razor.nuspec +microsoft.codeanalysis.workspaces.common\2.8.0\.signature.p7s +microsoft.codeanalysis.workspaces.common\2.8.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.Desktop.dll +microsoft.codeanalysis.workspaces.common\2.8.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.Desktop.pdb +microsoft.codeanalysis.workspaces.common\2.8.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.dll +microsoft.codeanalysis.workspaces.common\2.8.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.pdb +microsoft.codeanalysis.workspaces.common\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.Workspaces.dll +microsoft.codeanalysis.workspaces.common\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.Workspaces.pdb +microsoft.codeanalysis.workspaces.common\2.8.0\microsoft.codeanalysis.workspaces.common.2.8.0.nupkg +microsoft.codeanalysis.workspaces.common\2.8.0\microsoft.codeanalysis.workspaces.common.2.8.0.nupkg.sha512 +microsoft.codeanalysis.workspaces.common\2.8.0\microsoft.codeanalysis.workspaces.common.nuspec +microsoft.csharp\4.0.1\dotnet_library_license.txt +microsoft.csharp\4.0.1\lib\MonoAndroid10\_._ +microsoft.csharp\4.0.1\lib\MonoTouch10\_._ +microsoft.csharp\4.0.1\lib\net45\_._ +microsoft.csharp\4.0.1\lib\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.0.1\lib\netstandard1.3\Microsoft.CSharp.dll +microsoft.csharp\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.0.1\lib\win8\_._ +microsoft.csharp\4.0.1\lib\wp80\_._ +microsoft.csharp\4.0.1\lib\wpa81\_._ +microsoft.csharp\4.0.1\lib\xamarinios10\_._ +microsoft.csharp\4.0.1\lib\xamarinmac20\_._ +microsoft.csharp\4.0.1\lib\xamarintvos10\_._ +microsoft.csharp\4.0.1\lib\xamarinwatchos10\_._ +microsoft.csharp\4.0.1\microsoft.csharp.4.0.1.nupkg +microsoft.csharp\4.0.1\microsoft.csharp.4.0.1.nupkg.sha512 +microsoft.csharp\4.0.1\microsoft.csharp.nuspec +microsoft.csharp\4.0.1\ref\MonoAndroid10\_._ +microsoft.csharp\4.0.1\ref\MonoTouch10\_._ +microsoft.csharp\4.0.1\ref\net45\_._ +microsoft.csharp\4.0.1\ref\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.0.1\ref\netstandard1.0\Microsoft.CSharp.dll +microsoft.csharp\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.0.1\ref\win8\_._ +microsoft.csharp\4.0.1\ref\wp80\_._ +microsoft.csharp\4.0.1\ref\wpa81\_._ +microsoft.csharp\4.0.1\ref\xamarinios10\_._ +microsoft.csharp\4.0.1\ref\xamarinmac20\_._ +microsoft.csharp\4.0.1\ref\xamarintvos10\_._ +microsoft.csharp\4.0.1\ref\xamarinwatchos10\_._ +microsoft.csharp\4.0.1\ThirdPartyNotices.txt +microsoft.csharp\4.3.0\dotnet_library_license.txt +microsoft.csharp\4.3.0\lib\MonoAndroid10\_._ +microsoft.csharp\4.3.0\lib\MonoTouch10\_._ +microsoft.csharp\4.3.0\lib\net45\_._ +microsoft.csharp\4.3.0\lib\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.3.0\lib\netstandard1.3\Microsoft.CSharp.dll +microsoft.csharp\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.3.0\lib\win8\_._ +microsoft.csharp\4.3.0\lib\wp80\_._ +microsoft.csharp\4.3.0\lib\wpa81\_._ +microsoft.csharp\4.3.0\lib\xamarinios10\_._ +microsoft.csharp\4.3.0\lib\xamarinmac20\_._ +microsoft.csharp\4.3.0\lib\xamarintvos10\_._ +microsoft.csharp\4.3.0\lib\xamarinwatchos10\_._ +microsoft.csharp\4.3.0\microsoft.csharp.4.3.0.nupkg +microsoft.csharp\4.3.0\microsoft.csharp.4.3.0.nupkg.sha512 +microsoft.csharp\4.3.0\microsoft.csharp.nuspec +microsoft.csharp\4.3.0\ref\MonoAndroid10\_._ +microsoft.csharp\4.3.0\ref\MonoTouch10\_._ +microsoft.csharp\4.3.0\ref\net45\_._ +microsoft.csharp\4.3.0\ref\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.3.0\ref\netstandard1.0\Microsoft.CSharp.dll +microsoft.csharp\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.3.0\ref\win8\_._ +microsoft.csharp\4.3.0\ref\wp80\_._ +microsoft.csharp\4.3.0\ref\wpa81\_._ +microsoft.csharp\4.3.0\ref\xamarinios10\_._ +microsoft.csharp\4.3.0\ref\xamarinmac20\_._ +microsoft.csharp\4.3.0\ref\xamarintvos10\_._ +microsoft.csharp\4.3.0\ref\xamarinwatchos10\_._ +microsoft.csharp\4.3.0\ThirdPartyNotices.txt +microsoft.csharp\4.5.0\.signature.p7s +microsoft.csharp\4.5.0\lib\MonoAndroid10\_._ +microsoft.csharp\4.5.0\lib\MonoTouch10\_._ +microsoft.csharp\4.5.0\lib\net45\_._ +microsoft.csharp\4.5.0\lib\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\lib\netcoreapp2.0\_._ +microsoft.csharp\4.5.0\lib\netstandard1.3\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\lib\netstandard2.0\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\lib\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.5.0\lib\uap10.0.16299\_._ +microsoft.csharp\4.5.0\lib\win8\_._ +microsoft.csharp\4.5.0\lib\wp80\_._ +microsoft.csharp\4.5.0\lib\wpa81\_._ +microsoft.csharp\4.5.0\lib\xamarinios10\_._ +microsoft.csharp\4.5.0\lib\xamarinmac20\_._ +microsoft.csharp\4.5.0\lib\xamarintvos10\_._ +microsoft.csharp\4.5.0\lib\xamarinwatchos10\_._ +microsoft.csharp\4.5.0\LICENSE.TXT +microsoft.csharp\4.5.0\microsoft.csharp.4.5.0.nupkg +microsoft.csharp\4.5.0\microsoft.csharp.4.5.0.nupkg.sha512 +microsoft.csharp\4.5.0\microsoft.csharp.nuspec +microsoft.csharp\4.5.0\ref\MonoAndroid10\_._ +microsoft.csharp\4.5.0\ref\MonoTouch10\_._ +microsoft.csharp\4.5.0\ref\net45\_._ +microsoft.csharp\4.5.0\ref\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\ref\netcoreapp2.0\_._ +microsoft.csharp\4.5.0\ref\netstandard1.0\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\ref\netstandard2.0\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\ref\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.5.0\ref\uap10.0.16299\_._ +microsoft.csharp\4.5.0\ref\win8\_._ +microsoft.csharp\4.5.0\ref\wp80\_._ +microsoft.csharp\4.5.0\ref\wpa81\_._ +microsoft.csharp\4.5.0\ref\xamarinios10\_._ +microsoft.csharp\4.5.0\ref\xamarinmac20\_._ +microsoft.csharp\4.5.0\ref\xamarintvos10\_._ +microsoft.csharp\4.5.0\ref\xamarinwatchos10\_._ +microsoft.csharp\4.5.0\THIRD-PARTY-NOTICES.TXT +microsoft.csharp\4.5.0\useSharedDesignerContext.txt +microsoft.csharp\4.5.0\version.txt +microsoft.data.edm\5.8.2\lib\net40\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\net40\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\sl4\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\microsoft.data.edm.5.8.2.nupkg +microsoft.data.edm\5.8.2\microsoft.data.edm.5.8.2.nupkg.sha512 +microsoft.data.edm\5.8.2\microsoft.data.edm.nuspec +microsoft.data.odata\5.8.2\lib\net40\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\net40\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\sl4\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\microsoft.data.odata.5.8.2.nupkg +microsoft.data.odata\5.8.2\microsoft.data.odata.5.8.2.nupkg.sha512 +microsoft.data.odata\5.8.2\microsoft.data.odata.nuspec +microsoft.data.sqlite.core\2.1.0\.signature.p7s +microsoft.data.sqlite.core\2.1.0\lib\netstandard2.0\Microsoft.Data.Sqlite.dll +microsoft.data.sqlite.core\2.1.0\microsoft.data.sqlite.core.2.1.0.nupkg +microsoft.data.sqlite.core\2.1.0\microsoft.data.sqlite.core.2.1.0.nupkg.sha512 +microsoft.data.sqlite.core\2.1.0\microsoft.data.sqlite.core.nuspec +microsoft.data.sqlite\2.1.0\.signature.p7s +microsoft.data.sqlite\2.1.0\lib\netstandard2.0\_._ +microsoft.data.sqlite\2.1.0\microsoft.data.sqlite.2.1.0.nupkg +microsoft.data.sqlite\2.1.0\microsoft.data.sqlite.2.1.0.nupkg.sha512 +microsoft.data.sqlite\2.1.0\microsoft.data.sqlite.nuspec +microsoft.dotnet.platformabstractions\2.1.0\.signature.p7s +microsoft.dotnet.platformabstractions\2.1.0\lib\net45\Microsoft.DotNet.PlatformAbstractions.dll +microsoft.dotnet.platformabstractions\2.1.0\lib\netstandard1.3\Microsoft.DotNet.PlatformAbstractions.dll +microsoft.dotnet.platformabstractions\2.1.0\LICENSE.TXT +microsoft.dotnet.platformabstractions\2.1.0\microsoft.dotnet.platformabstractions.2.1.0.nupkg +microsoft.dotnet.platformabstractions\2.1.0\microsoft.dotnet.platformabstractions.2.1.0.nupkg.sha512 +microsoft.dotnet.platformabstractions\2.1.0\microsoft.dotnet.platformabstractions.nuspec +microsoft.dotnet.platformabstractions\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.entityframeworkcore.abstractions\2.1.1\.signature.p7s +microsoft.entityframeworkcore.abstractions\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Abstractions.dll +microsoft.entityframeworkcore.abstractions\2.1.1\microsoft.entityframeworkcore.abstractions.2.1.1.nupkg +microsoft.entityframeworkcore.abstractions\2.1.1\microsoft.entityframeworkcore.abstractions.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.abstractions\2.1.1\microsoft.entityframeworkcore.abstractions.nuspec +microsoft.entityframeworkcore.analyzers\2.1.1\.signature.p7s +microsoft.entityframeworkcore.analyzers\2.1.1\analyzers\dotnet\cs\Microsoft.EntityFrameworkCore.Analyzers.dll +microsoft.entityframeworkcore.analyzers\2.1.1\microsoft.entityframeworkcore.analyzers.2.1.1.nupkg +microsoft.entityframeworkcore.analyzers\2.1.1\microsoft.entityframeworkcore.analyzers.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.analyzers\2.1.1\microsoft.entityframeworkcore.analyzers.nuspec +microsoft.entityframeworkcore.design\2.1.1\.signature.p7s +microsoft.entityframeworkcore.design\2.1.1\build\net461\Microsoft.EntityFrameworkCore.Design.props +microsoft.entityframeworkcore.design\2.1.1\build\netcoreapp2.0\Microsoft.EntityFrameworkCore.Design.props +microsoft.entityframeworkcore.design\2.1.1\lib\net461\Microsoft.EntityFrameworkCore.Design.dll +microsoft.entityframeworkcore.design\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Design.dll +microsoft.entityframeworkcore.design\2.1.1\microsoft.entityframeworkcore.design.2.1.1.nupkg +microsoft.entityframeworkcore.design\2.1.1\microsoft.entityframeworkcore.design.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.design\2.1.1\microsoft.entityframeworkcore.design.nuspec +microsoft.entityframeworkcore.inmemory\2.1.1\.signature.p7s +microsoft.entityframeworkcore.inmemory\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.InMemory.dll +microsoft.entityframeworkcore.inmemory\2.1.1\microsoft.entityframeworkcore.inmemory.2.1.1.nupkg +microsoft.entityframeworkcore.inmemory\2.1.1\microsoft.entityframeworkcore.inmemory.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.inmemory\2.1.1\microsoft.entityframeworkcore.inmemory.nuspec +microsoft.entityframeworkcore.relational\2.1.1\.signature.p7s +microsoft.entityframeworkcore.relational\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Relational.dll +microsoft.entityframeworkcore.relational\2.1.1\microsoft.entityframeworkcore.relational.2.1.1.nupkg +microsoft.entityframeworkcore.relational\2.1.1\microsoft.entityframeworkcore.relational.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.relational\2.1.1\microsoft.entityframeworkcore.relational.nuspec +microsoft.entityframeworkcore.sqlite.core\2.1.1\.signature.p7s +microsoft.entityframeworkcore.sqlite.core\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Sqlite.dll +microsoft.entityframeworkcore.sqlite.core\2.1.1\microsoft.entityframeworkcore.sqlite.core.2.1.1.nupkg +microsoft.entityframeworkcore.sqlite.core\2.1.1\microsoft.entityframeworkcore.sqlite.core.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.sqlite.core\2.1.1\microsoft.entityframeworkcore.sqlite.core.nuspec +microsoft.entityframeworkcore.sqlite\2.1.1\.signature.p7s +microsoft.entityframeworkcore.sqlite\2.1.1\lib\netstandard2.0\_._ +microsoft.entityframeworkcore.sqlite\2.1.1\microsoft.entityframeworkcore.sqlite.2.1.1.nupkg +microsoft.entityframeworkcore.sqlite\2.1.1\microsoft.entityframeworkcore.sqlite.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.sqlite\2.1.1\microsoft.entityframeworkcore.sqlite.nuspec +microsoft.entityframeworkcore.sqlserver\2.1.1\.signature.p7s +microsoft.entityframeworkcore.sqlserver\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.SqlServer.dll +microsoft.entityframeworkcore.sqlserver\2.1.1\microsoft.entityframeworkcore.sqlserver.2.1.1.nupkg +microsoft.entityframeworkcore.sqlserver\2.1.1\microsoft.entityframeworkcore.sqlserver.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.sqlserver\2.1.1\microsoft.entityframeworkcore.sqlserver.nuspec +microsoft.entityframeworkcore.tools\2.1.1\.signature.p7s +microsoft.entityframeworkcore.tools\2.1.1\lib\netstandard2.0\_._ +microsoft.entityframeworkcore.tools\2.1.1\microsoft.entityframeworkcore.tools.2.1.1.nupkg +microsoft.entityframeworkcore.tools\2.1.1\microsoft.entityframeworkcore.tools.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.tools\2.1.1\microsoft.entityframeworkcore.tools.nuspec +microsoft.entityframeworkcore.tools\2.1.1\tools\about_EntityFrameworkCore.help.txt +microsoft.entityframeworkcore.tools\2.1.1\tools\EntityFrameworkCore.PowerShell2.psd1 +microsoft.entityframeworkcore.tools\2.1.1\tools\EntityFrameworkCore.PowerShell2.psm1 +microsoft.entityframeworkcore.tools\2.1.1\tools\EntityFrameworkCore.psd1 +microsoft.entityframeworkcore.tools\2.1.1\tools\EntityFrameworkCore.psm1 +microsoft.entityframeworkcore.tools\2.1.1\tools\init.ps1 +microsoft.entityframeworkcore.tools\2.1.1\tools\install.ps1 +microsoft.entityframeworkcore.tools\2.1.1\tools\net461\any\ef.exe +microsoft.entityframeworkcore.tools\2.1.1\tools\net461\win-x86\ef.exe +microsoft.entityframeworkcore.tools\2.1.1\tools\netcoreapp2.0\any\ef.dll +microsoft.entityframeworkcore.tools\2.1.1\tools\netcoreapp2.0\any\ef.runtimeconfig.json +microsoft.entityframeworkcore\2.1.1\.signature.p7s +microsoft.entityframeworkcore\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.dll +microsoft.entityframeworkcore\2.1.1\microsoft.entityframeworkcore.2.1.1.nupkg +microsoft.entityframeworkcore\2.1.1\microsoft.entityframeworkcore.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore\2.1.1\microsoft.entityframeworkcore.nuspec +microsoft.extensions.caching.abstractions\2.1.1\.signature.p7s +microsoft.extensions.caching.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Caching.Abstractions.dll +microsoft.extensions.caching.abstractions\2.1.1\microsoft.extensions.caching.abstractions.2.1.1.nupkg +microsoft.extensions.caching.abstractions\2.1.1\microsoft.extensions.caching.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.caching.abstractions\2.1.1\microsoft.extensions.caching.abstractions.nuspec +microsoft.extensions.caching.memory\2.1.1\.signature.p7s +microsoft.extensions.caching.memory\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Caching.Memory.dll +microsoft.extensions.caching.memory\2.1.1\microsoft.extensions.caching.memory.2.1.1.nupkg +microsoft.extensions.caching.memory\2.1.1\microsoft.extensions.caching.memory.2.1.1.nupkg.sha512 +microsoft.extensions.caching.memory\2.1.1\microsoft.extensions.caching.memory.nuspec +microsoft.extensions.caching.redis\2.1.1\.signature.p7s +microsoft.extensions.caching.redis\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Caching.Redis.dll +microsoft.extensions.caching.redis\2.1.1\microsoft.extensions.caching.redis.2.1.1.nupkg +microsoft.extensions.caching.redis\2.1.1\microsoft.extensions.caching.redis.2.1.1.nupkg.sha512 +microsoft.extensions.caching.redis\2.1.1\microsoft.extensions.caching.redis.nuspec +microsoft.extensions.caching.sqlserver\2.1.1\.signature.p7s +microsoft.extensions.caching.sqlserver\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Caching.SqlServer.dll +microsoft.extensions.caching.sqlserver\2.1.1\microsoft.extensions.caching.sqlserver.2.1.1.nupkg +microsoft.extensions.caching.sqlserver\2.1.1\microsoft.extensions.caching.sqlserver.2.1.1.nupkg.sha512 +microsoft.extensions.caching.sqlserver\2.1.1\microsoft.extensions.caching.sqlserver.nuspec +microsoft.extensions.configuration.abstractions\2.1.1\.signature.p7s +microsoft.extensions.configuration.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll +microsoft.extensions.configuration.abstractions\2.1.1\microsoft.extensions.configuration.abstractions.2.1.1.nupkg +microsoft.extensions.configuration.abstractions\2.1.1\microsoft.extensions.configuration.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.abstractions\2.1.1\microsoft.extensions.configuration.abstractions.nuspec +microsoft.extensions.configuration.azurekeyvault\2.1.1\.signature.p7s +microsoft.extensions.configuration.azurekeyvault\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.AzureKeyVault.dll +microsoft.extensions.configuration.azurekeyvault\2.1.1\microsoft.extensions.configuration.azurekeyvault.2.1.1.nupkg +microsoft.extensions.configuration.azurekeyvault\2.1.1\microsoft.extensions.configuration.azurekeyvault.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.azurekeyvault\2.1.1\microsoft.extensions.configuration.azurekeyvault.nuspec +microsoft.extensions.configuration.binder\2.1.1\.signature.p7s +microsoft.extensions.configuration.binder\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll +microsoft.extensions.configuration.binder\2.1.1\microsoft.extensions.configuration.binder.2.1.1.nupkg +microsoft.extensions.configuration.binder\2.1.1\microsoft.extensions.configuration.binder.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.binder\2.1.1\microsoft.extensions.configuration.binder.nuspec +microsoft.extensions.configuration.commandline\2.1.1\.signature.p7s +microsoft.extensions.configuration.commandline\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.CommandLine.dll +microsoft.extensions.configuration.commandline\2.1.1\microsoft.extensions.configuration.commandline.2.1.1.nupkg +microsoft.extensions.configuration.commandline\2.1.1\microsoft.extensions.configuration.commandline.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.commandline\2.1.1\microsoft.extensions.configuration.commandline.nuspec +microsoft.extensions.configuration.environmentvariables\2.1.1\.signature.p7s +microsoft.extensions.configuration.environmentvariables\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll +microsoft.extensions.configuration.environmentvariables\2.1.1\microsoft.extensions.configuration.environmentvariables.2.1.1.nupkg +microsoft.extensions.configuration.environmentvariables\2.1.1\microsoft.extensions.configuration.environmentvariables.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.environmentvariables\2.1.1\microsoft.extensions.configuration.environmentvariables.nuspec +microsoft.extensions.configuration.fileextensions\2.1.1\.signature.p7s +microsoft.extensions.configuration.fileextensions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.FileExtensions.dll +microsoft.extensions.configuration.fileextensions\2.1.1\microsoft.extensions.configuration.fileextensions.2.1.1.nupkg +microsoft.extensions.configuration.fileextensions\2.1.1\microsoft.extensions.configuration.fileextensions.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.fileextensions\2.1.1\microsoft.extensions.configuration.fileextensions.nuspec +microsoft.extensions.configuration.ini\2.1.1\.signature.p7s +microsoft.extensions.configuration.ini\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Ini.dll +microsoft.extensions.configuration.ini\2.1.1\microsoft.extensions.configuration.ini.2.1.1.nupkg +microsoft.extensions.configuration.ini\2.1.1\microsoft.extensions.configuration.ini.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.ini\2.1.1\microsoft.extensions.configuration.ini.nuspec +microsoft.extensions.configuration.json\2.1.1\.signature.p7s +microsoft.extensions.configuration.json\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Json.dll +microsoft.extensions.configuration.json\2.1.1\microsoft.extensions.configuration.json.2.1.1.nupkg +microsoft.extensions.configuration.json\2.1.1\microsoft.extensions.configuration.json.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.json\2.1.1\microsoft.extensions.configuration.json.nuspec +microsoft.extensions.configuration.keyperfile\2.1.1\.signature.p7s +microsoft.extensions.configuration.keyperfile\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.KeyPerFile.dll +microsoft.extensions.configuration.keyperfile\2.1.1\microsoft.extensions.configuration.keyperfile.2.1.1.nupkg +microsoft.extensions.configuration.keyperfile\2.1.1\microsoft.extensions.configuration.keyperfile.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.keyperfile\2.1.1\microsoft.extensions.configuration.keyperfile.nuspec +microsoft.extensions.configuration.usersecrets\2.1.1\.signature.p7s +microsoft.extensions.configuration.usersecrets\2.1.1\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.props +microsoft.extensions.configuration.usersecrets\2.1.1\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.targets +microsoft.extensions.configuration.usersecrets\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.dll +microsoft.extensions.configuration.usersecrets\2.1.1\microsoft.extensions.configuration.usersecrets.2.1.1.nupkg +microsoft.extensions.configuration.usersecrets\2.1.1\microsoft.extensions.configuration.usersecrets.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.usersecrets\2.1.1\microsoft.extensions.configuration.usersecrets.nuspec +microsoft.extensions.configuration.xml\2.1.1\.signature.p7s +microsoft.extensions.configuration.xml\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Xml.dll +microsoft.extensions.configuration.xml\2.1.1\microsoft.extensions.configuration.xml.2.1.1.nupkg +microsoft.extensions.configuration.xml\2.1.1\microsoft.extensions.configuration.xml.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.xml\2.1.1\microsoft.extensions.configuration.xml.nuspec +microsoft.extensions.configuration\2.1.1\.signature.p7s +microsoft.extensions.configuration\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll +microsoft.extensions.configuration\2.1.1\microsoft.extensions.configuration.2.1.1.nupkg +microsoft.extensions.configuration\2.1.1\microsoft.extensions.configuration.2.1.1.nupkg.sha512 +microsoft.extensions.configuration\2.1.1\microsoft.extensions.configuration.nuspec +microsoft.extensions.dependencyinjection.abstractions\2.1.1\.signature.p7s +microsoft.extensions.dependencyinjection.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll +microsoft.extensions.dependencyinjection.abstractions\2.1.1\microsoft.extensions.dependencyinjection.abstractions.2.1.1.nupkg +microsoft.extensions.dependencyinjection.abstractions\2.1.1\microsoft.extensions.dependencyinjection.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.dependencyinjection.abstractions\2.1.1\microsoft.extensions.dependencyinjection.abstractions.nuspec +microsoft.extensions.dependencyinjection\2.1.1\.signature.p7s +microsoft.extensions.dependencyinjection\2.1.1\lib\net461\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.1.1\lib\netcoreapp2.0\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.1.1\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.1.1\microsoft.extensions.dependencyinjection.2.1.1.nupkg +microsoft.extensions.dependencyinjection\2.1.1\microsoft.extensions.dependencyinjection.2.1.1.nupkg.sha512 +microsoft.extensions.dependencyinjection\2.1.1\microsoft.extensions.dependencyinjection.nuspec +microsoft.extensions.dependencymodel\2.1.0\.signature.p7s +microsoft.extensions.dependencymodel\2.1.0\lib\net451\Microsoft.Extensions.DependencyModel.dll +microsoft.extensions.dependencymodel\2.1.0\lib\netstandard1.3\Microsoft.Extensions.DependencyModel.dll +microsoft.extensions.dependencymodel\2.1.0\lib\netstandard1.6\Microsoft.Extensions.DependencyModel.dll +microsoft.extensions.dependencymodel\2.1.0\LICENSE.TXT +microsoft.extensions.dependencymodel\2.1.0\microsoft.extensions.dependencymodel.2.1.0.nupkg +microsoft.extensions.dependencymodel\2.1.0\microsoft.extensions.dependencymodel.2.1.0.nupkg.sha512 +microsoft.extensions.dependencymodel\2.1.0\microsoft.extensions.dependencymodel.nuspec +microsoft.extensions.dependencymodel\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.extensions.diagnosticadapter\2.1.0\.signature.p7s +microsoft.extensions.diagnosticadapter\2.1.0\lib\net461\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.1.0\lib\netcoreapp2.0\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.1.0\lib\netstandard2.0\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.1.0\microsoft.extensions.diagnosticadapter.2.1.0.nupkg +microsoft.extensions.diagnosticadapter\2.1.0\microsoft.extensions.diagnosticadapter.2.1.0.nupkg.sha512 +microsoft.extensions.diagnosticadapter\2.1.0\microsoft.extensions.diagnosticadapter.nuspec +microsoft.extensions.fileproviders.abstractions\2.1.1\.signature.p7s +microsoft.extensions.fileproviders.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Abstractions.dll +microsoft.extensions.fileproviders.abstractions\2.1.1\microsoft.extensions.fileproviders.abstractions.2.1.1.nupkg +microsoft.extensions.fileproviders.abstractions\2.1.1\microsoft.extensions.fileproviders.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.fileproviders.abstractions\2.1.1\microsoft.extensions.fileproviders.abstractions.nuspec +microsoft.extensions.fileproviders.composite\2.1.1\.signature.p7s +microsoft.extensions.fileproviders.composite\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Composite.dll +microsoft.extensions.fileproviders.composite\2.1.1\microsoft.extensions.fileproviders.composite.2.1.1.nupkg +microsoft.extensions.fileproviders.composite\2.1.1\microsoft.extensions.fileproviders.composite.2.1.1.nupkg.sha512 +microsoft.extensions.fileproviders.composite\2.1.1\microsoft.extensions.fileproviders.composite.nuspec +microsoft.extensions.fileproviders.embedded\2.1.1\.signature.p7s +microsoft.extensions.fileproviders.embedded\2.1.1\build\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.props +microsoft.extensions.fileproviders.embedded\2.1.1\build\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.targets +microsoft.extensions.fileproviders.embedded\2.1.1\buildMultiTargeting\Microsoft.Extensions.FileProviders.Embedded.props +microsoft.extensions.fileproviders.embedded\2.1.1\buildMultiTargeting\Microsoft.Extensions.FileProviders.Embedded.targets +microsoft.extensions.fileproviders.embedded\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.dll +microsoft.extensions.fileproviders.embedded\2.1.1\microsoft.extensions.fileproviders.embedded.2.1.1.nupkg +microsoft.extensions.fileproviders.embedded\2.1.1\microsoft.extensions.fileproviders.embedded.2.1.1.nupkg.sha512 +microsoft.extensions.fileproviders.embedded\2.1.1\microsoft.extensions.fileproviders.embedded.nuspec +microsoft.extensions.fileproviders.embedded\2.1.1\tasks\net461\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll +microsoft.extensions.fileproviders.embedded\2.1.1\tasks\netstandard1.5\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll +microsoft.extensions.fileproviders.physical\2.1.1\.signature.p7s +microsoft.extensions.fileproviders.physical\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Physical.dll +microsoft.extensions.fileproviders.physical\2.1.1\microsoft.extensions.fileproviders.physical.2.1.1.nupkg +microsoft.extensions.fileproviders.physical\2.1.1\microsoft.extensions.fileproviders.physical.2.1.1.nupkg.sha512 +microsoft.extensions.fileproviders.physical\2.1.1\microsoft.extensions.fileproviders.physical.nuspec +microsoft.extensions.filesystemglobbing\2.1.1\.signature.p7s +microsoft.extensions.filesystemglobbing\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileSystemGlobbing.dll +microsoft.extensions.filesystemglobbing\2.1.1\microsoft.extensions.filesystemglobbing.2.1.1.nupkg +microsoft.extensions.filesystemglobbing\2.1.1\microsoft.extensions.filesystemglobbing.2.1.1.nupkg.sha512 +microsoft.extensions.filesystemglobbing\2.1.1\microsoft.extensions.filesystemglobbing.nuspec +microsoft.extensions.hosting.abstractions\2.1.1\.signature.p7s +microsoft.extensions.hosting.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Hosting.Abstractions.dll +microsoft.extensions.hosting.abstractions\2.1.1\microsoft.extensions.hosting.abstractions.2.1.1.nupkg +microsoft.extensions.hosting.abstractions\2.1.1\microsoft.extensions.hosting.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.hosting.abstractions\2.1.1\microsoft.extensions.hosting.abstractions.nuspec +microsoft.extensions.hosting\2.1.1\.signature.p7s +microsoft.extensions.hosting\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Hosting.dll +microsoft.extensions.hosting\2.1.1\microsoft.extensions.hosting.2.1.1.nupkg +microsoft.extensions.hosting\2.1.1\microsoft.extensions.hosting.2.1.1.nupkg.sha512 +microsoft.extensions.hosting\2.1.1\microsoft.extensions.hosting.nuspec +microsoft.extensions.http\2.1.1\.signature.p7s +microsoft.extensions.http\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Http.dll +microsoft.extensions.http\2.1.1\microsoft.extensions.http.2.1.1.nupkg +microsoft.extensions.http\2.1.1\microsoft.extensions.http.2.1.1.nupkg.sha512 +microsoft.extensions.http\2.1.1\microsoft.extensions.http.nuspec +microsoft.extensions.identity.core\2.1.1\.signature.p7s +microsoft.extensions.identity.core\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Identity.Core.dll +microsoft.extensions.identity.core\2.1.1\microsoft.extensions.identity.core.2.1.1.nupkg +microsoft.extensions.identity.core\2.1.1\microsoft.extensions.identity.core.2.1.1.nupkg.sha512 +microsoft.extensions.identity.core\2.1.1\microsoft.extensions.identity.core.nuspec +microsoft.extensions.identity.stores\2.1.1\.signature.p7s +microsoft.extensions.identity.stores\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Identity.Stores.dll +microsoft.extensions.identity.stores\2.1.1\microsoft.extensions.identity.stores.2.1.1.nupkg +microsoft.extensions.identity.stores\2.1.1\microsoft.extensions.identity.stores.2.1.1.nupkg.sha512 +microsoft.extensions.identity.stores\2.1.1\microsoft.extensions.identity.stores.nuspec +microsoft.extensions.localization.abstractions\2.1.1\.signature.p7s +microsoft.extensions.localization.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Localization.Abstractions.dll +microsoft.extensions.localization.abstractions\2.1.1\microsoft.extensions.localization.abstractions.2.1.1.nupkg +microsoft.extensions.localization.abstractions\2.1.1\microsoft.extensions.localization.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.localization.abstractions\2.1.1\microsoft.extensions.localization.abstractions.nuspec +microsoft.extensions.localization\2.1.1\.signature.p7s +microsoft.extensions.localization\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Localization.dll +microsoft.extensions.localization\2.1.1\microsoft.extensions.localization.2.1.1.nupkg +microsoft.extensions.localization\2.1.1\microsoft.extensions.localization.2.1.1.nupkg.sha512 +microsoft.extensions.localization\2.1.1\microsoft.extensions.localization.nuspec +microsoft.extensions.logging.abstractions\2.1.1\.signature.p7s +microsoft.extensions.logging.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll +microsoft.extensions.logging.abstractions\2.1.1\microsoft.extensions.logging.abstractions.2.1.1.nupkg +microsoft.extensions.logging.abstractions\2.1.1\microsoft.extensions.logging.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.logging.abstractions\2.1.1\microsoft.extensions.logging.abstractions.nuspec +microsoft.extensions.logging.azureappservices\2.1.1\.signature.p7s +microsoft.extensions.logging.azureappservices\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.AzureAppServices.dll +microsoft.extensions.logging.azureappservices\2.1.1\microsoft.extensions.logging.azureappservices.2.1.1.nupkg +microsoft.extensions.logging.azureappservices\2.1.1\microsoft.extensions.logging.azureappservices.2.1.1.nupkg.sha512 +microsoft.extensions.logging.azureappservices\2.1.1\microsoft.extensions.logging.azureappservices.nuspec +microsoft.extensions.logging.configuration\2.1.1\.signature.p7s +microsoft.extensions.logging.configuration\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Configuration.dll +microsoft.extensions.logging.configuration\2.1.1\microsoft.extensions.logging.configuration.2.1.1.nupkg +microsoft.extensions.logging.configuration\2.1.1\microsoft.extensions.logging.configuration.2.1.1.nupkg.sha512 +microsoft.extensions.logging.configuration\2.1.1\microsoft.extensions.logging.configuration.nuspec +microsoft.extensions.logging.console\2.1.1\.signature.p7s +microsoft.extensions.logging.console\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Console.dll +microsoft.extensions.logging.console\2.1.1\microsoft.extensions.logging.console.2.1.1.nupkg +microsoft.extensions.logging.console\2.1.1\microsoft.extensions.logging.console.2.1.1.nupkg.sha512 +microsoft.extensions.logging.console\2.1.1\microsoft.extensions.logging.console.nuspec +microsoft.extensions.logging.debug\2.1.1\.signature.p7s +microsoft.extensions.logging.debug\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Debug.dll +microsoft.extensions.logging.debug\2.1.1\microsoft.extensions.logging.debug.2.1.1.nupkg +microsoft.extensions.logging.debug\2.1.1\microsoft.extensions.logging.debug.2.1.1.nupkg.sha512 +microsoft.extensions.logging.debug\2.1.1\microsoft.extensions.logging.debug.nuspec +microsoft.extensions.logging.eventsource\2.1.1\.signature.p7s +microsoft.extensions.logging.eventsource\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.EventSource.dll +microsoft.extensions.logging.eventsource\2.1.1\microsoft.extensions.logging.eventsource.2.1.1.nupkg +microsoft.extensions.logging.eventsource\2.1.1\microsoft.extensions.logging.eventsource.2.1.1.nupkg.sha512 +microsoft.extensions.logging.eventsource\2.1.1\microsoft.extensions.logging.eventsource.nuspec +microsoft.extensions.logging.tracesource\2.1.1\.signature.p7s +microsoft.extensions.logging.tracesource\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.TraceSource.dll +microsoft.extensions.logging.tracesource\2.1.1\microsoft.extensions.logging.tracesource.2.1.1.nupkg +microsoft.extensions.logging.tracesource\2.1.1\microsoft.extensions.logging.tracesource.2.1.1.nupkg.sha512 +microsoft.extensions.logging.tracesource\2.1.1\microsoft.extensions.logging.tracesource.nuspec +microsoft.extensions.logging\2.1.1\.signature.p7s +microsoft.extensions.logging\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.dll +microsoft.extensions.logging\2.1.1\microsoft.extensions.logging.2.1.1.nupkg +microsoft.extensions.logging\2.1.1\microsoft.extensions.logging.2.1.1.nupkg.sha512 +microsoft.extensions.logging\2.1.1\microsoft.extensions.logging.nuspec +microsoft.extensions.objectpool\2.1.1\.signature.p7s +microsoft.extensions.objectpool\2.1.1\lib\netstandard2.0\Microsoft.Extensions.ObjectPool.dll +microsoft.extensions.objectpool\2.1.1\microsoft.extensions.objectpool.2.1.1.nupkg +microsoft.extensions.objectpool\2.1.1\microsoft.extensions.objectpool.2.1.1.nupkg.sha512 +microsoft.extensions.objectpool\2.1.1\microsoft.extensions.objectpool.nuspec +microsoft.extensions.options.configurationextensions\2.1.1\.signature.p7s +microsoft.extensions.options.configurationextensions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll +microsoft.extensions.options.configurationextensions\2.1.1\microsoft.extensions.options.configurationextensions.2.1.1.nupkg +microsoft.extensions.options.configurationextensions\2.1.1\microsoft.extensions.options.configurationextensions.2.1.1.nupkg.sha512 +microsoft.extensions.options.configurationextensions\2.1.1\microsoft.extensions.options.configurationextensions.nuspec +microsoft.extensions.options\2.1.1\.signature.p7s +microsoft.extensions.options\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Options.dll +microsoft.extensions.options\2.1.1\microsoft.extensions.options.2.1.1.nupkg +microsoft.extensions.options\2.1.1\microsoft.extensions.options.2.1.1.nupkg.sha512 +microsoft.extensions.options\2.1.1\microsoft.extensions.options.nuspec +microsoft.extensions.platformabstractions\1.1.0\lib\net451\Microsoft.Extensions.PlatformAbstractions.dll +microsoft.extensions.platformabstractions\1.1.0\lib\netstandard1.3\Microsoft.Extensions.PlatformAbstractions.dll +microsoft.extensions.platformabstractions\1.1.0\microsoft.extensions.platformabstractions.1.1.0.nupkg +microsoft.extensions.platformabstractions\1.1.0\microsoft.extensions.platformabstractions.1.1.0.nupkg.sha512 +microsoft.extensions.platformabstractions\1.1.0\microsoft.extensions.platformabstractions.nuspec +microsoft.extensions.primitives\2.1.1\.signature.p7s +microsoft.extensions.primitives\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll +microsoft.extensions.primitives\2.1.1\microsoft.extensions.primitives.2.1.1.nupkg +microsoft.extensions.primitives\2.1.1\microsoft.extensions.primitives.2.1.1.nupkg.sha512 +microsoft.extensions.primitives\2.1.1\microsoft.extensions.primitives.nuspec +microsoft.extensions.webencoders\2.1.1\.signature.p7s +microsoft.extensions.webencoders\2.1.1\lib\netstandard2.0\Microsoft.Extensions.WebEncoders.dll +microsoft.extensions.webencoders\2.1.1\microsoft.extensions.webencoders.2.1.1.nupkg +microsoft.extensions.webencoders\2.1.1\microsoft.extensions.webencoders.2.1.1.nupkg.sha512 +microsoft.extensions.webencoders\2.1.1\microsoft.extensions.webencoders.nuspec +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\MonoAndroid10\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\MonoAndroid10\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\netcore45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\netcore45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\netstandard1.3\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\netstandard1.3\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\portable-net45+win\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\Xamarin.iOS10\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\Xamarin.iOS10\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\microsoft.identitymodel.clients.activedirectory.3.14.2.nupkg +microsoft.identitymodel.clients.activedirectory\3.14.2\microsoft.identitymodel.clients.activedirectory.3.14.2.nupkg.sha512 +microsoft.identitymodel.clients.activedirectory\3.14.2\microsoft.identitymodel.clients.activedirectory.nuspec +microsoft.identitymodel.logging\5.2.0\lib\net45\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.2.0\lib\net451\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.2.0\microsoft.identitymodel.logging.5.2.0.nupkg +microsoft.identitymodel.logging\5.2.0\microsoft.identitymodel.logging.5.2.0.nupkg.sha512 +microsoft.identitymodel.logging\5.2.0\microsoft.identitymodel.logging.nuspec +microsoft.identitymodel.protocols.openidconnect\5.2.0\lib\net45\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.2.0\lib\net451\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.2.0\microsoft.identitymodel.protocols.openidconnect.5.2.0.nupkg +microsoft.identitymodel.protocols.openidconnect\5.2.0\microsoft.identitymodel.protocols.openidconnect.5.2.0.nupkg.sha512 +microsoft.identitymodel.protocols.openidconnect\5.2.0\microsoft.identitymodel.protocols.openidconnect.nuspec +microsoft.identitymodel.protocols.wsfederation\5.2.0\lib\net45\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.2.0\lib\net451\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.2.0\microsoft.identitymodel.protocols.wsfederation.5.2.0.nupkg +microsoft.identitymodel.protocols.wsfederation\5.2.0\microsoft.identitymodel.protocols.wsfederation.5.2.0.nupkg.sha512 +microsoft.identitymodel.protocols.wsfederation\5.2.0\microsoft.identitymodel.protocols.wsfederation.nuspec +microsoft.identitymodel.protocols\5.2.0\lib\net45\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.2.0\lib\net451\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.2.0\microsoft.identitymodel.protocols.5.2.0.nupkg +microsoft.identitymodel.protocols\5.2.0\microsoft.identitymodel.protocols.5.2.0.nupkg.sha512 +microsoft.identitymodel.protocols\5.2.0\microsoft.identitymodel.protocols.nuspec +microsoft.identitymodel.tokens.saml\5.2.0\lib\net45\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.2.0\lib\net451\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.2.0\microsoft.identitymodel.tokens.saml.5.2.0.nupkg +microsoft.identitymodel.tokens.saml\5.2.0\microsoft.identitymodel.tokens.saml.5.2.0.nupkg.sha512 +microsoft.identitymodel.tokens.saml\5.2.0\microsoft.identitymodel.tokens.saml.nuspec +microsoft.identitymodel.tokens\5.2.0\lib\net45\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.2.0\lib\net451\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.2.0\microsoft.identitymodel.tokens.5.2.0.nupkg +microsoft.identitymodel.tokens\5.2.0\microsoft.identitymodel.tokens.5.2.0.nupkg.sha512 +microsoft.identitymodel.tokens\5.2.0\microsoft.identitymodel.tokens.nuspec +microsoft.identitymodel.xml\5.2.0\lib\net45\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.2.0\lib\net451\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.2.0\microsoft.identitymodel.xml.5.2.0.nupkg +microsoft.identitymodel.xml\5.2.0\microsoft.identitymodel.xml.5.2.0.nupkg.sha512 +microsoft.identitymodel.xml\5.2.0\microsoft.identitymodel.xml.nuspec +microsoft.net.http.headers\2.1.1\.signature.p7s +microsoft.net.http.headers\2.1.1\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll +microsoft.net.http.headers\2.1.1\microsoft.net.http.headers.2.1.1.nupkg +microsoft.net.http.headers\2.1.1\microsoft.net.http.headers.2.1.1.nupkg.sha512 +microsoft.net.http.headers\2.1.1\microsoft.net.http.headers.nuspec +microsoft.netcore.app\2.1.1\.signature.p7s +microsoft.netcore.app\2.1.1\build\netcoreapp2.1\Microsoft.NETCore.App.PlatformManifest.txt +microsoft.netcore.app\2.1.1\build\netcoreapp2.1\Microsoft.NETCore.App.props +microsoft.netcore.app\2.1.1\build\netcoreapp2.1\Microsoft.NETCore.App.targets +microsoft.netcore.app\2.1.1\LICENSE.TXT +microsoft.netcore.app\2.1.1\microsoft.netcore.app.2.1.1.nupkg +microsoft.netcore.app\2.1.1\microsoft.netcore.app.2.1.1.nupkg.sha512 +microsoft.netcore.app\2.1.1\microsoft.netcore.app.nuspec +microsoft.netcore.app\2.1.1\Microsoft.NETCore.App.versions.txt +microsoft.netcore.app\2.1.1\ref\netcoreapp\_._ +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\Microsoft.CSharp.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\Microsoft.VisualBasic.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\Microsoft.Win32.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\mscorlib.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\netstandard.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.AppContext.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Buffers.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.Concurrent.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.Immutable.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.NonGeneric.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.Specialized.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.Annotations.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.DataAnnotations.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.EventBasedAsync.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.TypeConverter.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Configuration.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Console.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Core.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Data.Common.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Data.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Contracts.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Debug.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.DiagnosticSource.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.FileVersionInfo.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Process.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.StackTrace.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.TextWriterTraceListener.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Tools.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.TraceSource.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Tracing.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Drawing.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Drawing.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Dynamic.Runtime.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Globalization.Calendars.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Globalization.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Globalization.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Compression.Brotli.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Compression.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Compression.FileSystem.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Compression.ZipFile.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.FileSystem.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.FileSystem.DriveInfo.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.FileSystem.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.FileSystem.Watcher.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.IsolatedStorage.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.MemoryMappedFiles.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Pipes.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.UnmanagedMemoryStream.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Linq.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Linq.Expressions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Linq.Parallel.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Linq.Queryable.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Memory.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Http.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.HttpListener.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Mail.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.NameResolution.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.NetworkInformation.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Ping.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Requests.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Security.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.ServicePoint.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Sockets.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebClient.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebHeaderCollection.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebProxy.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebSockets.Client.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebSockets.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Numerics.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Numerics.Vectors.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ObjectModel.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.DispatchProxy.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Emit.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Emit.ILGeneration.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Emit.Lightweight.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Metadata.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.TypeExtensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Resources.Reader.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Resources.ResourceManager.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Resources.Writer.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.CompilerServices.VisualC.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Handles.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.InteropServices.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.InteropServices.RuntimeInformation.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.InteropServices.WindowsRuntime.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Loader.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Numerics.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.Formatters.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.Json.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.Xml.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Claims.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.Algorithms.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.Csp.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.Encoding.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.X509Certificates.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Principal.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.SecureString.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ServiceModel.Web.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ServiceProcess.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Text.Encoding.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Text.Encoding.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Text.RegularExpressions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Overlapped.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Tasks.Dataflow.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Tasks.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Tasks.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Tasks.Parallel.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Thread.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.ThreadPool.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Timer.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Transactions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Transactions.Local.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ValueTuple.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Web.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Web.HttpUtility.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Windows.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.Linq.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.ReaderWriter.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.Serialization.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XDocument.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XmlDocument.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XmlSerializer.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XPath.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XPath.XDocument.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\WindowsBase.dll +microsoft.netcore.app\2.1.1\runtime.json +microsoft.netcore.app\2.1.1\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnetapphost\2.1.1\.signature.p7s +microsoft.netcore.dotnetapphost\2.1.1\LICENSE.TXT +microsoft.netcore.dotnetapphost\2.1.1\microsoft.netcore.dotnetapphost.2.1.1.nupkg +microsoft.netcore.dotnetapphost\2.1.1\microsoft.netcore.dotnetapphost.2.1.1.nupkg.sha512 +microsoft.netcore.dotnetapphost\2.1.1\microsoft.netcore.dotnetapphost.nuspec +microsoft.netcore.dotnetapphost\2.1.1\runtime.json +microsoft.netcore.dotnetapphost\2.1.1\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostpolicy\2.1.1\.signature.p7s +microsoft.netcore.dotnethostpolicy\2.1.1\LICENSE.TXT +microsoft.netcore.dotnethostpolicy\2.1.1\microsoft.netcore.dotnethostpolicy.2.1.1.nupkg +microsoft.netcore.dotnethostpolicy\2.1.1\microsoft.netcore.dotnethostpolicy.2.1.1.nupkg.sha512 +microsoft.netcore.dotnethostpolicy\2.1.1\microsoft.netcore.dotnethostpolicy.nuspec +microsoft.netcore.dotnethostpolicy\2.1.1\runtime.json +microsoft.netcore.dotnethostpolicy\2.1.1\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostresolver\2.1.1\.signature.p7s +microsoft.netcore.dotnethostresolver\2.1.1\LICENSE.TXT +microsoft.netcore.dotnethostresolver\2.1.1\microsoft.netcore.dotnethostresolver.2.1.1.nupkg +microsoft.netcore.dotnethostresolver\2.1.1\microsoft.netcore.dotnethostresolver.2.1.1.nupkg.sha512 +microsoft.netcore.dotnethostresolver\2.1.1\microsoft.netcore.dotnethostresolver.nuspec +microsoft.netcore.dotnethostresolver\2.1.1\runtime.json +microsoft.netcore.dotnethostresolver\2.1.1\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\1.0.1\dotnet_library_license.txt +microsoft.netcore.platforms\1.0.1\lib\netstandard1.0\_._ +microsoft.netcore.platforms\1.0.1\microsoft.netcore.platforms.1.0.1.nupkg +microsoft.netcore.platforms\1.0.1\microsoft.netcore.platforms.1.0.1.nupkg.sha512 +microsoft.netcore.platforms\1.0.1\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\1.0.1\runtime.json +microsoft.netcore.platforms\1.0.1\ThirdPartyNotices.txt +microsoft.netcore.platforms\1.0.2\dotnet_library_license.txt +microsoft.netcore.platforms\1.0.2\lib\netstandard1.0\_._ +microsoft.netcore.platforms\1.0.2\microsoft.netcore.platforms.1.0.2.nupkg +microsoft.netcore.platforms\1.0.2\microsoft.netcore.platforms.1.0.2.nupkg.sha512 +microsoft.netcore.platforms\1.0.2\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\1.0.2\runtime.json +microsoft.netcore.platforms\1.0.2\ThirdPartyNotices.txt +microsoft.netcore.platforms\1.1.0\dotnet_library_license.txt +microsoft.netcore.platforms\1.1.0\lib\netstandard1.0\_._ +microsoft.netcore.platforms\1.1.0\microsoft.netcore.platforms.1.1.0.nupkg +microsoft.netcore.platforms\1.1.0\microsoft.netcore.platforms.1.1.0.nupkg.sha512 +microsoft.netcore.platforms\1.1.0\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\1.1.0\runtime.json +microsoft.netcore.platforms\1.1.0\ThirdPartyNotices.txt +microsoft.netcore.platforms\2.0.0\lib\netstandard1.0\_._ +microsoft.netcore.platforms\2.0.0\LICENSE.TXT +microsoft.netcore.platforms\2.0.0\microsoft.netcore.platforms.2.0.0.nupkg +microsoft.netcore.platforms\2.0.0\microsoft.netcore.platforms.2.0.0.nupkg.sha512 +microsoft.netcore.platforms\2.0.0\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\2.0.0\runtime.json +microsoft.netcore.platforms\2.0.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\2.0.0\useSharedDesignerContext.txt +microsoft.netcore.platforms\2.0.0\version.txt +microsoft.netcore.platforms\2.1.0\.signature.p7s +microsoft.netcore.platforms\2.1.0\lib\netstandard1.0\_._ +microsoft.netcore.platforms\2.1.0\LICENSE.TXT +microsoft.netcore.platforms\2.1.0\microsoft.netcore.platforms.2.1.0.nupkg +microsoft.netcore.platforms\2.1.0\microsoft.netcore.platforms.2.1.0.nupkg.sha512 +microsoft.netcore.platforms\2.1.0\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\2.1.0\runtime.json +microsoft.netcore.platforms\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\2.1.0\useSharedDesignerContext.txt +microsoft.netcore.platforms\2.1.0\version.txt +microsoft.netcore.targets\1.0.1\dotnet_library_license.txt +microsoft.netcore.targets\1.0.1\lib\netstandard1.0\_._ +microsoft.netcore.targets\1.0.1\microsoft.netcore.targets.1.0.1.nupkg +microsoft.netcore.targets\1.0.1\microsoft.netcore.targets.1.0.1.nupkg.sha512 +microsoft.netcore.targets\1.0.1\microsoft.netcore.targets.nuspec +microsoft.netcore.targets\1.0.1\runtime.json +microsoft.netcore.targets\1.0.1\ThirdPartyNotices.txt +microsoft.netcore.targets\1.1.0\dotnet_library_license.txt +microsoft.netcore.targets\1.1.0\lib\netstandard1.0\_._ +microsoft.netcore.targets\1.1.0\microsoft.netcore.targets.1.1.0.nupkg +microsoft.netcore.targets\1.1.0\microsoft.netcore.targets.1.1.0.nupkg.sha512 +microsoft.netcore.targets\1.1.0\microsoft.netcore.targets.nuspec +microsoft.netcore.targets\1.1.0\runtime.json +microsoft.netcore.targets\1.1.0\ThirdPartyNotices.txt +microsoft.netcore.targets\2.0.0\lib\netstandard1.0\_._ +microsoft.netcore.targets\2.0.0\LICENSE.TXT +microsoft.netcore.targets\2.0.0\microsoft.netcore.targets.2.0.0.nupkg +microsoft.netcore.targets\2.0.0\microsoft.netcore.targets.2.0.0.nupkg.sha512 +microsoft.netcore.targets\2.0.0\microsoft.netcore.targets.nuspec +microsoft.netcore.targets\2.0.0\runtime.json +microsoft.netcore.targets\2.0.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.targets\2.0.0\useSharedDesignerContext.txt +microsoft.netcore.targets\2.0.0\version.txt +microsoft.rest.clientruntime.azure\3.3.7\lib\net452\Microsoft.Rest.ClientRuntime.Azure.dll +microsoft.rest.clientruntime.azure\3.3.7\lib\net452\Microsoft.Rest.ClientRuntime.Azure.runtimeconfig.json +microsoft.rest.clientruntime.azure\3.3.7\lib\netstandard1.4\Microsoft.Rest.ClientRuntime.Azure.dll +microsoft.rest.clientruntime.azure\3.3.7\lib\netstandard1.4\Microsoft.Rest.ClientRuntime.Azure.runtimeconfig.json +microsoft.rest.clientruntime.azure\3.3.7\microsoft.rest.clientruntime.azure.3.3.7.nupkg +microsoft.rest.clientruntime.azure\3.3.7\microsoft.rest.clientruntime.azure.3.3.7.nupkg.sha512 +microsoft.rest.clientruntime.azure\3.3.7\microsoft.rest.clientruntime.azure.nuspec +microsoft.rest.clientruntime\2.3.8\lib\net452\Microsoft.Rest.ClientRuntime.dll +microsoft.rest.clientruntime\2.3.8\lib\net452\Microsoft.Rest.ClientRuntime.runtimeconfig.json +microsoft.rest.clientruntime\2.3.8\lib\netstandard1.4\Microsoft.Rest.ClientRuntime.dll +microsoft.rest.clientruntime\2.3.8\lib\netstandard1.4\Microsoft.Rest.ClientRuntime.runtimeconfig.json +microsoft.rest.clientruntime\2.3.8\microsoft.rest.clientruntime.2.3.8.nupkg +microsoft.rest.clientruntime\2.3.8\microsoft.rest.clientruntime.2.3.8.nupkg.sha512 +microsoft.rest.clientruntime\2.3.8\microsoft.rest.clientruntime.nuspec +microsoft.visualstudio.web.browserlink\2.1.1\.signature.p7s +microsoft.visualstudio.web.browserlink\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.BrowserLink.dll +microsoft.visualstudio.web.browserlink\2.1.1\microsoft.visualstudio.web.browserlink.2.1.1.nupkg +microsoft.visualstudio.web.browserlink\2.1.1\microsoft.visualstudio.web.browserlink.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.browserlink\2.1.1\microsoft.visualstudio.web.browserlink.nuspec +microsoft.visualstudio.web.codegeneration.contracts\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.1\microsoft.visualstudio.web.codegeneration.contracts.2.1.1.nupkg +microsoft.visualstudio.web.codegeneration.contracts\2.1.1\microsoft.visualstudio.web.codegeneration.contracts.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.1\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.1\microsoft.visualstudio.web.codegeneration.core.2.1.1.nupkg +microsoft.visualstudio.web.codegeneration.core\2.1.1\microsoft.visualstudio.web.codegeneration.core.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.1\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.1\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.design\2.1.1\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.1\microsoft.visualstudio.web.codegeneration.design.2.1.1.nupkg +microsoft.visualstudio.web.codegeneration.design\2.1.1\microsoft.visualstudio.web.codegeneration.design.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.1\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.1.nupkg +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.1\microsoft.visualstudio.web.codegeneration.templating.2.1.1.nupkg +microsoft.visualstudio.web.codegeneration.templating\2.1.1\microsoft.visualstudio.web.codegeneration.templating.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.1\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.1\microsoft.visualstudio.web.codegeneration.utils.2.1.1.nupkg +microsoft.visualstudio.web.codegeneration.utils\2.1.1\microsoft.visualstudio.web.codegeneration.utils.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.1\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.1\microsoft.visualstudio.web.codegeneration.2.1.1.nupkg +microsoft.visualstudio.web.codegeneration\2.1.1\microsoft.visualstudio.web.codegeneration.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.1\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\microsoft.visualstudio.web.codegenerators.mvc.2.1.1.nupkg +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\microsoft.visualstudio.web.codegenerators.mvc.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\List.cshtml +microsoft.win32.primitives\4.0.1\dotnet_library_license.txt +microsoft.win32.primitives\4.0.1\lib\MonoAndroid10\_._ +microsoft.win32.primitives\4.0.1\lib\MonoTouch10\_._ +microsoft.win32.primitives\4.0.1\lib\net46\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.0.1\lib\xamarinios10\_._ +microsoft.win32.primitives\4.0.1\lib\xamarinmac20\_._ +microsoft.win32.primitives\4.0.1\lib\xamarintvos10\_._ +microsoft.win32.primitives\4.0.1\lib\xamarinwatchos10\_._ +microsoft.win32.primitives\4.0.1\microsoft.win32.primitives.4.0.1.nupkg +microsoft.win32.primitives\4.0.1\microsoft.win32.primitives.4.0.1.nupkg.sha512 +microsoft.win32.primitives\4.0.1\microsoft.win32.primitives.nuspec +microsoft.win32.primitives\4.0.1\ref\MonoAndroid10\_._ +microsoft.win32.primitives\4.0.1\ref\MonoTouch10\_._ +microsoft.win32.primitives\4.0.1\ref\net46\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.0.1\ref\netstandard1.3\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.0.1\ref\xamarinios10\_._ +microsoft.win32.primitives\4.0.1\ref\xamarinmac20\_._ +microsoft.win32.primitives\4.0.1\ref\xamarintvos10\_._ +microsoft.win32.primitives\4.0.1\ref\xamarinwatchos10\_._ +microsoft.win32.primitives\4.0.1\ThirdPartyNotices.txt +microsoft.win32.primitives\4.3.0\dotnet_library_license.txt +microsoft.win32.primitives\4.3.0\lib\MonoAndroid10\_._ +microsoft.win32.primitives\4.3.0\lib\MonoTouch10\_._ +microsoft.win32.primitives\4.3.0\lib\net46\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.3.0\lib\xamarinios10\_._ +microsoft.win32.primitives\4.3.0\lib\xamarinmac20\_._ +microsoft.win32.primitives\4.3.0\lib\xamarintvos10\_._ +microsoft.win32.primitives\4.3.0\lib\xamarinwatchos10\_._ +microsoft.win32.primitives\4.3.0\microsoft.win32.primitives.4.3.0.nupkg +microsoft.win32.primitives\4.3.0\microsoft.win32.primitives.4.3.0.nupkg.sha512 +microsoft.win32.primitives\4.3.0\microsoft.win32.primitives.nuspec +microsoft.win32.primitives\4.3.0\ref\MonoAndroid10\_._ +microsoft.win32.primitives\4.3.0\ref\MonoTouch10\_._ +microsoft.win32.primitives\4.3.0\ref\net46\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.3.0\ref\netstandard1.3\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.3.0\ref\xamarinios10\_._ +microsoft.win32.primitives\4.3.0\ref\xamarinmac20\_._ +microsoft.win32.primitives\4.3.0\ref\xamarintvos10\_._ +microsoft.win32.primitives\4.3.0\ref\xamarinwatchos10\_._ +microsoft.win32.primitives\4.3.0\ThirdPartyNotices.txt +microsoft.win32.registry\4.3.0\dotnet_library_license.txt +microsoft.win32.registry\4.3.0\lib\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\microsoft.win32.registry.4.3.0.nupkg +microsoft.win32.registry\4.3.0\microsoft.win32.registry.4.3.0.nupkg.sha512 +microsoft.win32.registry\4.3.0\microsoft.win32.registry.nuspec +microsoft.win32.registry\4.3.0\ref\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\ref\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\runtimes\unix\lib\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\runtimes\win\lib\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\runtimes\win\lib\netcore50\_._ +microsoft.win32.registry\4.3.0\runtimes\win\lib\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\ThirdPartyNotices.txt +microsoft.win32.registry\4.5.0\.signature.p7s +microsoft.win32.registry\4.5.0\lib\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\lib\net461\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\lib\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\lib\netstandard2.0\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\LICENSE.TXT +microsoft.win32.registry\4.5.0\microsoft.win32.registry.4.5.0.nupkg +microsoft.win32.registry\4.5.0\microsoft.win32.registry.4.5.0.nupkg.sha512 +microsoft.win32.registry\4.5.0\microsoft.win32.registry.nuspec +microsoft.win32.registry\4.5.0\ref\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\ref\net461\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\ref\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\ref\netstandard2.0\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\unix\lib\netstandard2.0\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\win\lib\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\win\lib\net461\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\win\lib\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\win\lib\netstandard2.0\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\THIRD-PARTY-NOTICES.TXT +microsoft.win32.registry\4.5.0\useSharedDesignerContext.txt +microsoft.win32.registry\4.5.0\version.txt +netstandard.library\1.6.0\dotnet_library_license.txt +netstandard.library\1.6.0\netstandard.library.1.6.0.nupkg +netstandard.library\1.6.0\netstandard.library.1.6.0.nupkg.sha512 +netstandard.library\1.6.0\netstandard.library.nuspec +netstandard.library\1.6.0\ThirdPartyNotices.txt +netstandard.library\1.6.1\dotnet_library_license.txt +netstandard.library\1.6.1\netstandard.library.1.6.1.nupkg +netstandard.library\1.6.1\netstandard.library.1.6.1.nupkg.sha512 +netstandard.library\1.6.1\netstandard.library.nuspec +netstandard.library\1.6.1\ThirdPartyNotices.txt +netstandard.library\2.0.3\build\netstandard2.0\NETStandard.Library.targets +netstandard.library\2.0.3\build\netstandard2.0\ref\Microsoft.Win32.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\mscorlib.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.AppContext.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Concurrent.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.NonGeneric.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Specialized.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.Composition.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.EventBasedAsync.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.TypeConverter.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Console.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Core.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Data.Common.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Data.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Contracts.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Debug.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.FileVersionInfo.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Process.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.StackTrace.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.TextWriterTraceListener.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Tools.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.TraceSource.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Tracing.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Drawing.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Drawing.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Dynamic.Runtime.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.Calendars.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.Extensions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.FileSystem.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.ZipFile.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.DriveInfo.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.Watcher.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.IsolatedStorage.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.MemoryMappedFiles.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Pipes.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.UnmanagedMemoryStream.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Expressions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Parallel.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Queryable.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Http.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.NameResolution.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.NetworkInformation.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Ping.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Requests.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Security.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Sockets.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebHeaderCollection.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebSockets.Client.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebSockets.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Numerics.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ObjectModel.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Reflection.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Reflection.Extensions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Reflection.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.Reader.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.ResourceManager.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.Writer.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.CompilerServices.VisualC.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Extensions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Handles.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.InteropServices.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.InteropServices.RuntimeInformation.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Numerics.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Formatters.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Json.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Xml.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Claims.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Algorithms.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Csp.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Encoding.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.X509Certificates.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Principal.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.SecureString.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ServiceModel.Web.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Text.Encoding.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Text.Encoding.Extensions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Text.RegularExpressions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Overlapped.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Tasks.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Tasks.Parallel.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Thread.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.ThreadPool.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Timer.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Transactions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ValueTuple.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Web.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Windows.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.Linq.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.ReaderWriter.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.Serialization.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XDocument.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XmlDocument.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XmlSerializer.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XPath.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XPath.XDocument.dll +netstandard.library\2.0.3\lib\netstandard1.0\_._ +netstandard.library\2.0.3\LICENSE.TXT +netstandard.library\2.0.3\netstandard.library.2.0.3.nupkg +netstandard.library\2.0.3\netstandard.library.2.0.3.nupkg.sha512 +netstandard.library\2.0.3\netstandard.library.nuspec +netstandard.library\2.0.3\THIRD-PARTY-NOTICES.TXT +newtonsoft.json.bson\1.0.1\lib\net45\Newtonsoft.Json.Bson.dll +newtonsoft.json.bson\1.0.1\lib\netstandard1.3\Newtonsoft.Json.Bson.dll +newtonsoft.json.bson\1.0.1\newtonsoft.json.bson.1.0.1.nupkg +newtonsoft.json.bson\1.0.1\newtonsoft.json.bson.1.0.1.nupkg.sha512 +newtonsoft.json.bson\1.0.1\newtonsoft.json.bson.nuspec +newtonsoft.json\10.0.1\lib\net20\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\net35\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\net40\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\net45\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\netstandard1.0\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\netstandard1.3\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\portable-net45+win8+wpa81+wp8\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\newtonsoft.json.10.0.1.nupkg +newtonsoft.json\10.0.1\newtonsoft.json.10.0.1.nupkg.sha512 +newtonsoft.json\10.0.1\newtonsoft.json.nuspec +newtonsoft.json\10.0.1\tools\install.ps1 +newtonsoft.json\11.0.2\lib\net20\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\net35\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\net40\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\net45\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\netstandard1.0\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\netstandard1.3\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\netstandard2.0\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\portable-net40+sl5+win8+wp8+wpa81\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\portable-net45+win8+wp8+wpa81\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\LICENSE.md +newtonsoft.json\11.0.2\newtonsoft.json.11.0.2.nupkg +newtonsoft.json\11.0.2\newtonsoft.json.11.0.2.nupkg.sha512 +newtonsoft.json\11.0.2\newtonsoft.json.nuspec +newtonsoft.json\9.0.1\lib\net20\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\net35\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\net40\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\net45\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\netstandard1.0\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\newtonsoft.json.9.0.1.nupkg +newtonsoft.json\9.0.1\newtonsoft.json.9.0.1.nupkg.sha512 +newtonsoft.json\9.0.1\newtonsoft.json.nuspec +newtonsoft.json\9.0.1\tools\install.ps1 +nuget.frameworks\4.7.0\.signature.p7s +nuget.frameworks\4.7.0\lib\net40\NuGet.Frameworks.dll +nuget.frameworks\4.7.0\lib\net46\NuGet.Frameworks.dll +nuget.frameworks\4.7.0\lib\netstandard1.6\NuGet.Frameworks.dll +nuget.frameworks\4.7.0\nuget.frameworks.4.7.0.nupkg +nuget.frameworks\4.7.0\nuget.frameworks.4.7.0.nupkg.sha512 +nuget.frameworks\4.7.0\nuget.frameworks.nuspec +remotion.linq\2.2.0\lib\net35\Remotion.Linq.dll +remotion.linq\2.2.0\lib\net40\Remotion.Linq.dll +remotion.linq\2.2.0\lib\net45\Remotion.Linq.dll +remotion.linq\2.2.0\lib\netstandard1.0\Remotion.Linq.dll +remotion.linq\2.2.0\lib\portable-net45+win+wpa81+wp80\Remotion.Linq.dll +remotion.linq\2.2.0\remotion.linq.2.2.0.nupkg +remotion.linq\2.2.0\remotion.linq.2.2.0.nupkg.sha512 +remotion.linq\2.2.0\remotion.linq.nuspec +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\debian.8-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\fedora.23-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\fedora.24-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.native.system.data.sqlclient.sni\4.4.0\LICENSE.TXT +runtime.native.system.data.sqlclient.sni\4.4.0\runtime.native.system.data.sqlclient.sni.4.4.0.nupkg +runtime.native.system.data.sqlclient.sni\4.4.0\runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512 +runtime.native.system.data.sqlclient.sni\4.4.0\runtime.native.system.data.sqlclient.sni.nuspec +runtime.native.system.data.sqlclient.sni\4.4.0\THIRD-PARTY-NOTICES.TXT +runtime.native.system.data.sqlclient.sni\4.4.0\useSharedDesignerContext.txt +runtime.native.system.data.sqlclient.sni\4.4.0\version.txt +runtime.native.system.io.compression\4.1.0\dotnet_library_license.txt +runtime.native.system.io.compression\4.1.0\lib\netstandard1.0\_._ +runtime.native.system.io.compression\4.1.0\runtime.native.system.io.compression.4.1.0.nupkg +runtime.native.system.io.compression\4.1.0\runtime.native.system.io.compression.4.1.0.nupkg.sha512 +runtime.native.system.io.compression\4.1.0\runtime.native.system.io.compression.nuspec +runtime.native.system.io.compression\4.1.0\ThirdPartyNotices.txt +runtime.native.system.io.compression\4.3.0\dotnet_library_license.txt +runtime.native.system.io.compression\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.io.compression\4.3.0\runtime.native.system.io.compression.4.3.0.nupkg +runtime.native.system.io.compression\4.3.0\runtime.native.system.io.compression.4.3.0.nupkg.sha512 +runtime.native.system.io.compression\4.3.0\runtime.native.system.io.compression.nuspec +runtime.native.system.io.compression\4.3.0\ThirdPartyNotices.txt +runtime.native.system.net.http\4.0.1\dotnet_library_license.txt +runtime.native.system.net.http\4.0.1\lib\netstandard1.0\_._ +runtime.native.system.net.http\4.0.1\runtime.native.system.net.http.4.0.1.nupkg +runtime.native.system.net.http\4.0.1\runtime.native.system.net.http.4.0.1.nupkg.sha512 +runtime.native.system.net.http\4.0.1\runtime.native.system.net.http.nuspec +runtime.native.system.net.http\4.0.1\ThirdPartyNotices.txt +runtime.native.system.net.http\4.3.0\dotnet_library_license.txt +runtime.native.system.net.http\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.net.http\4.3.0\runtime.native.system.net.http.4.3.0.nupkg +runtime.native.system.net.http\4.3.0\runtime.native.system.net.http.4.3.0.nupkg.sha512 +runtime.native.system.net.http\4.3.0\runtime.native.system.net.http.nuspec +runtime.native.system.net.http\4.3.0\ThirdPartyNotices.txt +runtime.native.system.net.security\4.3.0\dotnet_library_license.txt +runtime.native.system.net.security\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.net.security\4.3.0\runtime.native.system.net.security.4.3.0.nupkg +runtime.native.system.net.security\4.3.0\runtime.native.system.net.security.4.3.0.nupkg.sha512 +runtime.native.system.net.security\4.3.0\runtime.native.system.net.security.nuspec +runtime.native.system.net.security\4.3.0\ThirdPartyNotices.txt +runtime.native.system.security.cryptography.apple\4.3.0\dotnet_library_license.txt +runtime.native.system.security.cryptography.apple\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.security.cryptography.apple\4.3.0\runtime.native.system.security.cryptography.apple.4.3.0.nupkg +runtime.native.system.security.cryptography.apple\4.3.0\runtime.native.system.security.cryptography.apple.4.3.0.nupkg.sha512 +runtime.native.system.security.cryptography.apple\4.3.0\runtime.native.system.security.cryptography.apple.nuspec +runtime.native.system.security.cryptography.apple\4.3.0\ThirdPartyNotices.txt +runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.native.system.security.cryptography.openssl\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.security.cryptography.openssl\4.3.0\runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.native.system.security.cryptography.openssl\4.3.0\runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.native.system.security.cryptography.openssl\4.3.0\runtime.native.system.security.cryptography.openssl.nuspec +runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.native.system.security.cryptography\4.0.0\dotnet_library_license.txt +runtime.native.system.security.cryptography\4.0.0\lib\netstandard1.0\_._ +runtime.native.system.security.cryptography\4.0.0\runtime.native.system.security.cryptography.4.0.0.nupkg +runtime.native.system.security.cryptography\4.0.0\runtime.native.system.security.cryptography.4.0.0.nupkg.sha512 +runtime.native.system.security.cryptography\4.0.0\runtime.native.system.security.cryptography.nuspec +runtime.native.system.security.cryptography\4.0.0\ThirdPartyNotices.txt +runtime.native.system\4.0.0\dotnet_library_license.txt +runtime.native.system\4.0.0\lib\netstandard1.0\_._ +runtime.native.system\4.0.0\runtime.native.system.4.0.0.nupkg +runtime.native.system\4.0.0\runtime.native.system.4.0.0.nupkg.sha512 +runtime.native.system\4.0.0\runtime.native.system.nuspec +runtime.native.system\4.0.0\ThirdPartyNotices.txt +runtime.native.system\4.3.0\dotnet_library_license.txt +runtime.native.system\4.3.0\lib\netstandard1.0\_._ +runtime.native.system\4.3.0\runtime.native.system.4.3.0.nupkg +runtime.native.system\4.3.0\runtime.native.system.4.3.0.nupkg.sha512 +runtime.native.system\4.3.0\runtime.native.system.nuspec +runtime.native.system\4.3.0\ThirdPartyNotices.txt +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\opensuse.13.2-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\opensuse.42.1-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\dotnet_library_license.txt +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.4.3.0.nupkg +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.4.3.0.nupkg.sha512 +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.nuspec +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\runtimes\osx.10.10-x64\native\System.Security.Cryptography.Native.Apple.dylib +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\ThirdPartyNotices.txt +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\osx.10.10-x64\native\System.Security.Cryptography.Native.OpenSsl.dylib +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\rhel.7-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\ubuntu.14.04-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\ubuntu.16.04-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\ubuntu.16.10-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\dotnet_library_license.txt +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-arm64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-arm64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512 +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-arm64.runtime.native.system.data.sqlclient.sni.nuspec +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\runtimes\win-arm64\native\sni.dll +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\ThirdPartyNotices.txt +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\useSharedDesignerContext.txt +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\version.txt +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\dotnet_library_license.txt +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512 +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x64.runtime.native.system.data.sqlclient.sni.nuspec +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\runtimes\win-x64\native\sni.dll +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\ThirdPartyNotices.txt +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\useSharedDesignerContext.txt +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\version.txt +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\dotnet_library_license.txt +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x86.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x86.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512 +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x86.runtime.native.system.data.sqlclient.sni.nuspec +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\runtimes\win-x86\native\sni.dll +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\ThirdPartyNotices.txt +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\useSharedDesignerContext.txt +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\version.txt +sqlitepclraw.bundle_green\1.1.11\build\wp8\SQLitePCLRaw.bundle_green.targets +sqlitepclraw.bundle_green\1.1.11\build\wp80\arm\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\build\wp80\arm\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\build\wp80\x86\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\build\wp80\x86\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\MonoAndroid\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\MonoAndroid\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\net35\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\net35\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\net40\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\net40\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\net45\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\net45\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\netcoreapp\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\netcoreapp\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\netstandard1.1\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\netstandard1.1\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net40+sl5+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net40+sl5+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\uap10.0\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\uap10.0\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\win8\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\win8\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\win81\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\win81\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\wp8\_._ +sqlitepclraw.bundle_green\1.1.11\lib\wpa81\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\wpa81\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\Xamarin.iOS10\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\Xamarin.iOS10\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\Xamarin.Mac20\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\Xamarin.Mac20\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\sqlitepclraw.bundle_green.1.1.11.nupkg +sqlitepclraw.bundle_green\1.1.11\sqlitepclraw.bundle_green.1.1.11.nupkg.sha512 +sqlitepclraw.bundle_green\1.1.11\sqlitepclraw.bundle_green.nuspec +sqlitepclraw.core\1.1.11\lib\MonoAndroid\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\net35\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\net40\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\net45\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\netstandard1.0\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\netstandard1.1\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\portable-net40+sl5+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\uap10.0\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\win8\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\win81\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\wpa81\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\Xamarin.iOS10\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\Xamarin.Mac20\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\sqlitepclraw.core.1.1.11.nupkg +sqlitepclraw.core\1.1.11\sqlitepclraw.core.1.1.11.nupkg.sha512 +sqlitepclraw.core\1.1.11\sqlitepclraw.core.nuspec +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\build\net35\SQLitePCLRaw.lib.e_sqlite3.linux.targets +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\lib\net35\_._ +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\lib\netstandard1.0\_._ +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\lib\netstandard2.0\_._ +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\alpine-x64\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-arm\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-arm64\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-armel\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-musl-x64\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-x64\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-x86\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\sqlitepclraw.lib.e_sqlite3.linux.1.1.11.nupkg +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\sqlitepclraw.lib.e_sqlite3.linux.1.1.11.nupkg.sha512 +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\sqlitepclraw.lib.e_sqlite3.linux.nuspec +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\build\net35\SQLitePCLRaw.lib.e_sqlite3.osx.targets +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\build\Xamarin.Mac20\SQLitePCLRaw.lib.e_sqlite3.osx.targets +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\lib\net35\_._ +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\lib\netstandard1.0\_._ +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\lib\netstandard2.0\_._ +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\lib\Xamarin.Mac20\_._ +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\runtimes\osx-x64\native\libe_sqlite3.dylib +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\sqlitepclraw.lib.e_sqlite3.osx.1.1.11.nupkg +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\sqlitepclraw.lib.e_sqlite3.osx.1.1.11.nupkg.sha512 +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\sqlitepclraw.lib.e_sqlite3.osx.nuspec +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\build\net35\SQLitePCLRaw.lib.e_sqlite3.v110_xp.targets +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\lib\net35\_._ +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\lib\netstandard1.0\_._ +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\lib\netstandard2.0\_._ +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\runtimes\win-x64\native\e_sqlite3.dll +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\runtimes\win-x86\native\e_sqlite3.dll +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\runtimes\win8-arm\native\e_sqlite3.dll +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\sqlitepclraw.lib.e_sqlite3.v110_xp.1.1.11.nupkg +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\sqlitepclraw.lib.e_sqlite3.v110_xp.1.1.11.nupkg.sha512 +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\sqlitepclraw.lib.e_sqlite3.v110_xp.nuspec +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\lib\netstandard1.1\SQLitePCLRaw.provider.e_sqlite3.dll +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\sqlitepclraw.provider.e_sqlite3.netstandard11.1.1.11.nupkg +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\sqlitepclraw.provider.e_sqlite3.netstandard11.1.1.11.nupkg.sha512 +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\sqlitepclraw.provider.e_sqlite3.netstandard11.nuspec +stackexchange.redis.strongname\1.2.4\lib\net45\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.4\lib\net46\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.4\lib\netstandard1.5\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.4\stackexchange.redis.strongname.1.2.4.nupkg +stackexchange.redis.strongname\1.2.4\stackexchange.redis.strongname.1.2.4.nupkg.sha512 +stackexchange.redis.strongname\1.2.4\stackexchange.redis.strongname.nuspec +system.appcontext\4.1.0\dotnet_library_license.txt +system.appcontext\4.1.0\lib\MonoAndroid10\_._ +system.appcontext\4.1.0\lib\MonoTouch10\_._ +system.appcontext\4.1.0\lib\net46\System.AppContext.dll +system.appcontext\4.1.0\lib\net463\System.AppContext.dll +system.appcontext\4.1.0\lib\netcore50\System.AppContext.dll +system.appcontext\4.1.0\lib\netstandard1.6\System.AppContext.dll +system.appcontext\4.1.0\lib\xamarinios10\_._ +system.appcontext\4.1.0\lib\xamarinmac20\_._ +system.appcontext\4.1.0\lib\xamarintvos10\_._ +system.appcontext\4.1.0\lib\xamarinwatchos10\_._ +system.appcontext\4.1.0\ref\MonoAndroid10\_._ +system.appcontext\4.1.0\ref\MonoTouch10\_._ +system.appcontext\4.1.0\ref\net46\System.AppContext.dll +system.appcontext\4.1.0\ref\net463\System.AppContext.dll +system.appcontext\4.1.0\ref\netstandard\_._ +system.appcontext\4.1.0\ref\netstandard1.3\System.AppContext.dll +system.appcontext\4.1.0\ref\netstandard1.6\System.AppContext.dll +system.appcontext\4.1.0\ref\xamarinios10\_._ +system.appcontext\4.1.0\ref\xamarinmac20\_._ +system.appcontext\4.1.0\ref\xamarintvos10\_._ +system.appcontext\4.1.0\ref\xamarinwatchos10\_._ +system.appcontext\4.1.0\runtimes\aot\lib\netcore50\System.AppContext.dll +system.appcontext\4.1.0\system.appcontext.4.1.0.nupkg +system.appcontext\4.1.0\system.appcontext.4.1.0.nupkg.sha512 +system.appcontext\4.1.0\system.appcontext.nuspec +system.appcontext\4.1.0\ThirdPartyNotices.txt +system.appcontext\4.3.0\dotnet_library_license.txt +system.appcontext\4.3.0\lib\MonoAndroid10\_._ +system.appcontext\4.3.0\lib\MonoTouch10\_._ +system.appcontext\4.3.0\lib\net46\System.AppContext.dll +system.appcontext\4.3.0\lib\net463\System.AppContext.dll +system.appcontext\4.3.0\lib\netcore50\System.AppContext.dll +system.appcontext\4.3.0\lib\netstandard1.6\System.AppContext.dll +system.appcontext\4.3.0\lib\xamarinios10\_._ +system.appcontext\4.3.0\lib\xamarinmac20\_._ +system.appcontext\4.3.0\lib\xamarintvos10\_._ +system.appcontext\4.3.0\lib\xamarinwatchos10\_._ +system.appcontext\4.3.0\ref\MonoAndroid10\_._ +system.appcontext\4.3.0\ref\MonoTouch10\_._ +system.appcontext\4.3.0\ref\net46\System.AppContext.dll +system.appcontext\4.3.0\ref\net463\System.AppContext.dll +system.appcontext\4.3.0\ref\netstandard\_._ +system.appcontext\4.3.0\ref\netstandard1.3\System.AppContext.dll +system.appcontext\4.3.0\ref\netstandard1.6\System.AppContext.dll +system.appcontext\4.3.0\ref\xamarinios10\_._ +system.appcontext\4.3.0\ref\xamarinmac20\_._ +system.appcontext\4.3.0\ref\xamarintvos10\_._ +system.appcontext\4.3.0\ref\xamarinwatchos10\_._ +system.appcontext\4.3.0\runtimes\aot\lib\netcore50\System.AppContext.dll +system.appcontext\4.3.0\system.appcontext.4.3.0.nupkg +system.appcontext\4.3.0\system.appcontext.4.3.0.nupkg.sha512 +system.appcontext\4.3.0\system.appcontext.nuspec +system.appcontext\4.3.0\ThirdPartyNotices.txt +system.buffers\4.0.0\dotnet_library_license.txt +system.buffers\4.0.0\lib\netstandard1.1\.xml +system.buffers\4.0.0\lib\netstandard1.1\System.Buffers.dll +system.buffers\4.0.0\system.buffers.4.0.0.nupkg +system.buffers\4.0.0\system.buffers.4.0.0.nupkg.sha512 +system.buffers\4.0.0\system.buffers.nuspec +system.buffers\4.0.0\ThirdPartyNotices.txt +system.buffers\4.3.0\dotnet_library_license.txt +system.buffers\4.3.0\lib\netstandard1.1\.xml +system.buffers\4.3.0\lib\netstandard1.1\System.Buffers.dll +system.buffers\4.3.0\system.buffers.4.3.0.nupkg +system.buffers\4.3.0\system.buffers.4.3.0.nupkg.sha512 +system.buffers\4.3.0\system.buffers.nuspec +system.buffers\4.3.0\ThirdPartyNotices.txt +system.buffers\4.5.0\.signature.p7s +system.buffers\4.5.0\lib\netcoreapp2.0\_._ +system.buffers\4.5.0\lib\netstandard1.1\System.Buffers.dll +system.buffers\4.5.0\lib\netstandard2.0\System.Buffers.dll +system.buffers\4.5.0\lib\uap10.0.16299\_._ +system.buffers\4.5.0\LICENSE.TXT +system.buffers\4.5.0\ref\net45\System.Buffers.dll +system.buffers\4.5.0\ref\netcoreapp2.0\_._ +system.buffers\4.5.0\ref\netstandard1.1\System.Buffers.dll +system.buffers\4.5.0\ref\netstandard2.0\System.Buffers.dll +system.buffers\4.5.0\ref\uap10.0.16299\_._ +system.buffers\4.5.0\system.buffers.4.5.0.nupkg +system.buffers\4.5.0\system.buffers.4.5.0.nupkg.sha512 +system.buffers\4.5.0\system.buffers.nuspec +system.buffers\4.5.0\THIRD-PARTY-NOTICES.TXT +system.buffers\4.5.0\useSharedDesignerContext.txt +system.buffers\4.5.0\version.txt +system.collections.concurrent\4.0.12\dotnet_library_license.txt +system.collections.concurrent\4.0.12\lib\MonoAndroid10\_._ +system.collections.concurrent\4.0.12\lib\MonoTouch10\_._ +system.collections.concurrent\4.0.12\lib\net45\_._ +system.collections.concurrent\4.0.12\lib\netcore50\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\lib\netstandard1.3\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\lib\portable-net45+win8+wpa81\_._ +system.collections.concurrent\4.0.12\lib\win8\_._ +system.collections.concurrent\4.0.12\lib\wpa81\_._ +system.collections.concurrent\4.0.12\lib\xamarinios10\_._ +system.collections.concurrent\4.0.12\lib\xamarinmac20\_._ +system.collections.concurrent\4.0.12\lib\xamarintvos10\_._ +system.collections.concurrent\4.0.12\lib\xamarinwatchos10\_._ +system.collections.concurrent\4.0.12\ref\MonoAndroid10\_._ +system.collections.concurrent\4.0.12\ref\MonoTouch10\_._ +system.collections.concurrent\4.0.12\ref\net45\_._ +system.collections.concurrent\4.0.12\ref\netcore50\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\ref\netstandard1.1\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\ref\netstandard1.3\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\ref\portable-net45+win8+wpa81\_._ +system.collections.concurrent\4.0.12\ref\win8\_._ +system.collections.concurrent\4.0.12\ref\wpa81\_._ +system.collections.concurrent\4.0.12\ref\xamarinios10\_._ +system.collections.concurrent\4.0.12\ref\xamarinmac20\_._ +system.collections.concurrent\4.0.12\ref\xamarintvos10\_._ +system.collections.concurrent\4.0.12\ref\xamarinwatchos10\_._ +system.collections.concurrent\4.0.12\system.collections.concurrent.4.0.12.nupkg +system.collections.concurrent\4.0.12\system.collections.concurrent.4.0.12.nupkg.sha512 +system.collections.concurrent\4.0.12\system.collections.concurrent.nuspec +system.collections.concurrent\4.0.12\ThirdPartyNotices.txt +system.collections.concurrent\4.3.0\dotnet_library_license.txt +system.collections.concurrent\4.3.0\lib\MonoAndroid10\_._ +system.collections.concurrent\4.3.0\lib\MonoTouch10\_._ +system.collections.concurrent\4.3.0\lib\net45\_._ +system.collections.concurrent\4.3.0\lib\netcore50\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\lib\netstandard1.3\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.collections.concurrent\4.3.0\lib\win8\_._ +system.collections.concurrent\4.3.0\lib\wpa81\_._ +system.collections.concurrent\4.3.0\lib\xamarinios10\_._ +system.collections.concurrent\4.3.0\lib\xamarinmac20\_._ +system.collections.concurrent\4.3.0\lib\xamarintvos10\_._ +system.collections.concurrent\4.3.0\lib\xamarinwatchos10\_._ +system.collections.concurrent\4.3.0\ref\MonoAndroid10\_._ +system.collections.concurrent\4.3.0\ref\MonoTouch10\_._ +system.collections.concurrent\4.3.0\ref\net45\_._ +system.collections.concurrent\4.3.0\ref\netcore50\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\ref\netstandard1.1\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\ref\netstandard1.3\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.collections.concurrent\4.3.0\ref\win8\_._ +system.collections.concurrent\4.3.0\ref\wpa81\_._ +system.collections.concurrent\4.3.0\ref\xamarinios10\_._ +system.collections.concurrent\4.3.0\ref\xamarinmac20\_._ +system.collections.concurrent\4.3.0\ref\xamarintvos10\_._ +system.collections.concurrent\4.3.0\ref\xamarinwatchos10\_._ +system.collections.concurrent\4.3.0\system.collections.concurrent.4.3.0.nupkg +system.collections.concurrent\4.3.0\system.collections.concurrent.4.3.0.nupkg.sha512 +system.collections.concurrent\4.3.0\system.collections.concurrent.nuspec +system.collections.concurrent\4.3.0\ThirdPartyNotices.txt +system.collections.immutable\1.3.0\dotnet_library_license.txt +system.collections.immutable\1.3.0\lib\netstandard1.0\System.Collections.Immutable.dll +system.collections.immutable\1.3.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll +system.collections.immutable\1.3.0\system.collections.immutable.1.3.0.nupkg +system.collections.immutable\1.3.0\system.collections.immutable.1.3.0.nupkg.sha512 +system.collections.immutable\1.3.0\system.collections.immutable.nuspec +system.collections.immutable\1.3.0\ThirdPartyNotices.txt +system.collections.immutable\1.3.1\dotnet_library_license.txt +system.collections.immutable\1.3.1\lib\netstandard1.0\System.Collections.Immutable.dll +system.collections.immutable\1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll +system.collections.immutable\1.3.1\system.collections.immutable.1.3.1.nupkg +system.collections.immutable\1.3.1\system.collections.immutable.1.3.1.nupkg.sha512 +system.collections.immutable\1.3.1\system.collections.immutable.nuspec +system.collections.immutable\1.3.1\ThirdPartyNotices.txt +system.collections.immutable\1.5.0\.signature.p7s +system.collections.immutable\1.5.0\lib\netstandard1.0\System.Collections.Immutable.dll +system.collections.immutable\1.5.0\lib\netstandard1.3\System.Collections.Immutable.dll +system.collections.immutable\1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll +system.collections.immutable\1.5.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll +system.collections.immutable\1.5.0\LICENSE.TXT +system.collections.immutable\1.5.0\system.collections.immutable.1.5.0.nupkg +system.collections.immutable\1.5.0\system.collections.immutable.1.5.0.nupkg.sha512 +system.collections.immutable\1.5.0\system.collections.immutable.nuspec +system.collections.immutable\1.5.0\THIRD-PARTY-NOTICES.TXT +system.collections.immutable\1.5.0\useSharedDesignerContext.txt +system.collections.immutable\1.5.0\version.txt +system.collections.nongeneric\4.3.0\dotnet_library_license.txt +system.collections.nongeneric\4.3.0\lib\MonoAndroid10\_._ +system.collections.nongeneric\4.3.0\lib\MonoTouch10\_._ +system.collections.nongeneric\4.3.0\lib\net46\System.Collections.NonGeneric.dll +system.collections.nongeneric\4.3.0\lib\netstandard1.3\System.Collections.NonGeneric.dll +system.collections.nongeneric\4.3.0\lib\xamarinios10\_._ +system.collections.nongeneric\4.3.0\lib\xamarinmac20\_._ +system.collections.nongeneric\4.3.0\lib\xamarintvos10\_._ +system.collections.nongeneric\4.3.0\lib\xamarinwatchos10\_._ +system.collections.nongeneric\4.3.0\ref\MonoAndroid10\_._ +system.collections.nongeneric\4.3.0\ref\MonoTouch10\_._ +system.collections.nongeneric\4.3.0\ref\net46\System.Collections.NonGeneric.dll +system.collections.nongeneric\4.3.0\ref\netstandard1.3\System.Collections.NonGeneric.dll +system.collections.nongeneric\4.3.0\ref\xamarinios10\_._ +system.collections.nongeneric\4.3.0\ref\xamarinmac20\_._ +system.collections.nongeneric\4.3.0\ref\xamarintvos10\_._ +system.collections.nongeneric\4.3.0\ref\xamarinwatchos10\_._ +system.collections.nongeneric\4.3.0\system.collections.nongeneric.4.3.0.nupkg +system.collections.nongeneric\4.3.0\system.collections.nongeneric.4.3.0.nupkg.sha512 +system.collections.nongeneric\4.3.0\system.collections.nongeneric.nuspec +system.collections.nongeneric\4.3.0\ThirdPartyNotices.txt +system.collections.specialized\4.3.0\dotnet_library_license.txt +system.collections.specialized\4.3.0\lib\MonoAndroid10\_._ +system.collections.specialized\4.3.0\lib\MonoTouch10\_._ +system.collections.specialized\4.3.0\lib\net46\System.Collections.Specialized.dll +system.collections.specialized\4.3.0\lib\netstandard1.3\System.Collections.Specialized.dll +system.collections.specialized\4.3.0\lib\xamarinios10\_._ +system.collections.specialized\4.3.0\lib\xamarinmac20\_._ +system.collections.specialized\4.3.0\lib\xamarintvos10\_._ +system.collections.specialized\4.3.0\lib\xamarinwatchos10\_._ +system.collections.specialized\4.3.0\ref\MonoAndroid10\_._ +system.collections.specialized\4.3.0\ref\MonoTouch10\_._ +system.collections.specialized\4.3.0\ref\net46\System.Collections.Specialized.dll +system.collections.specialized\4.3.0\ref\netstandard1.3\System.Collections.Specialized.dll +system.collections.specialized\4.3.0\ref\xamarinios10\_._ +system.collections.specialized\4.3.0\ref\xamarinmac20\_._ +system.collections.specialized\4.3.0\ref\xamarintvos10\_._ +system.collections.specialized\4.3.0\ref\xamarinwatchos10\_._ +system.collections.specialized\4.3.0\system.collections.specialized.4.3.0.nupkg +system.collections.specialized\4.3.0\system.collections.specialized.4.3.0.nupkg.sha512 +system.collections.specialized\4.3.0\system.collections.specialized.nuspec +system.collections.specialized\4.3.0\ThirdPartyNotices.txt +system.collections\4.0.11\dotnet_library_license.txt +system.collections\4.0.11\lib\MonoAndroid10\_._ +system.collections\4.0.11\lib\MonoTouch10\_._ +system.collections\4.0.11\lib\net45\_._ +system.collections\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.collections\4.0.11\lib\win8\_._ +system.collections\4.0.11\lib\wp80\_._ +system.collections\4.0.11\lib\wpa81\_._ +system.collections\4.0.11\lib\xamarinios10\_._ +system.collections\4.0.11\lib\xamarinmac20\_._ +system.collections\4.0.11\lib\xamarintvos10\_._ +system.collections\4.0.11\lib\xamarinwatchos10\_._ +system.collections\4.0.11\ref\MonoAndroid10\_._ +system.collections\4.0.11\ref\MonoTouch10\_._ +system.collections\4.0.11\ref\net45\_._ +system.collections\4.0.11\ref\netcore50\System.Collections.dll +system.collections\4.0.11\ref\netstandard1.0\System.Collections.dll +system.collections\4.0.11\ref\netstandard1.3\System.Collections.dll +system.collections\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.collections\4.0.11\ref\win8\_._ +system.collections\4.0.11\ref\wp80\_._ +system.collections\4.0.11\ref\wpa81\_._ +system.collections\4.0.11\ref\xamarinios10\_._ +system.collections\4.0.11\ref\xamarinmac20\_._ +system.collections\4.0.11\ref\xamarintvos10\_._ +system.collections\4.0.11\ref\xamarinwatchos10\_._ +system.collections\4.0.11\system.collections.4.0.11.nupkg +system.collections\4.0.11\system.collections.4.0.11.nupkg.sha512 +system.collections\4.0.11\system.collections.nuspec +system.collections\4.0.11\ThirdPartyNotices.txt +system.collections\4.3.0\dotnet_library_license.txt +system.collections\4.3.0\lib\MonoAndroid10\_._ +system.collections\4.3.0\lib\MonoTouch10\_._ +system.collections\4.3.0\lib\net45\_._ +system.collections\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.collections\4.3.0\lib\win8\_._ +system.collections\4.3.0\lib\wp80\_._ +system.collections\4.3.0\lib\wpa81\_._ +system.collections\4.3.0\lib\xamarinios10\_._ +system.collections\4.3.0\lib\xamarinmac20\_._ +system.collections\4.3.0\lib\xamarintvos10\_._ +system.collections\4.3.0\lib\xamarinwatchos10\_._ +system.collections\4.3.0\ref\MonoAndroid10\_._ +system.collections\4.3.0\ref\MonoTouch10\_._ +system.collections\4.3.0\ref\net45\_._ +system.collections\4.3.0\ref\netcore50\System.Collections.dll +system.collections\4.3.0\ref\netstandard1.0\System.Collections.dll +system.collections\4.3.0\ref\netstandard1.3\System.Collections.dll +system.collections\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.collections\4.3.0\ref\win8\_._ +system.collections\4.3.0\ref\wp80\_._ +system.collections\4.3.0\ref\wpa81\_._ +system.collections\4.3.0\ref\xamarinios10\_._ +system.collections\4.3.0\ref\xamarinmac20\_._ +system.collections\4.3.0\ref\xamarintvos10\_._ +system.collections\4.3.0\ref\xamarinwatchos10\_._ +system.collections\4.3.0\system.collections.4.3.0.nupkg +system.collections\4.3.0\system.collections.4.3.0.nupkg.sha512 +system.collections\4.3.0\system.collections.nuspec +system.collections\4.3.0\ThirdPartyNotices.txt +system.componentmodel.annotations\4.5.0\.signature.p7s +system.componentmodel.annotations\4.5.0\lib\MonoAndroid10\_._ +system.componentmodel.annotations\4.5.0\lib\MonoTouch10\_._ +system.componentmodel.annotations\4.5.0\lib\net45\_._ +system.componentmodel.annotations\4.5.0\lib\net461\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\lib\netcore50\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\lib\netcoreapp2.0\_._ +system.componentmodel.annotations\4.5.0\lib\netstandard1.4\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\lib\netstandard2.0\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\lib\portable-net45+win8\_._ +system.componentmodel.annotations\4.5.0\lib\uap10.0.16299\_._ +system.componentmodel.annotations\4.5.0\lib\win8\_._ +system.componentmodel.annotations\4.5.0\lib\xamarinios10\_._ +system.componentmodel.annotations\4.5.0\lib\xamarinmac20\_._ +system.componentmodel.annotations\4.5.0\lib\xamarintvos10\_._ +system.componentmodel.annotations\4.5.0\lib\xamarinwatchos10\_._ +system.componentmodel.annotations\4.5.0\LICENSE.TXT +system.componentmodel.annotations\4.5.0\ref\MonoAndroid10\_._ +system.componentmodel.annotations\4.5.0\ref\MonoTouch10\_._ +system.componentmodel.annotations\4.5.0\ref\net45\_._ +system.componentmodel.annotations\4.5.0\ref\net461\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netcore50\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netcoreapp2.0\_._ +system.componentmodel.annotations\4.5.0\ref\netstandard1.1\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netstandard1.3\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netstandard1.4\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netstandard2.0\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\portable-net45+win8\_._ +system.componentmodel.annotations\4.5.0\ref\uap10.0.16299\_._ +system.componentmodel.annotations\4.5.0\ref\win8\_._ +system.componentmodel.annotations\4.5.0\ref\xamarinios10\_._ +system.componentmodel.annotations\4.5.0\ref\xamarinmac20\_._ +system.componentmodel.annotations\4.5.0\ref\xamarintvos10\_._ +system.componentmodel.annotations\4.5.0\ref\xamarinwatchos10\_._ +system.componentmodel.annotations\4.5.0\system.componentmodel.annotations.4.5.0.nupkg +system.componentmodel.annotations\4.5.0\system.componentmodel.annotations.4.5.0.nupkg.sha512 +system.componentmodel.annotations\4.5.0\system.componentmodel.annotations.nuspec +system.componentmodel.annotations\4.5.0\THIRD-PARTY-NOTICES.TXT +system.componentmodel.annotations\4.5.0\useSharedDesignerContext.txt +system.componentmodel.annotations\4.5.0\version.txt +system.componentmodel.primitives\4.3.0\dotnet_library_license.txt +system.componentmodel.primitives\4.3.0\lib\MonoAndroid10\_._ +system.componentmodel.primitives\4.3.0\lib\MonoTouch10\_._ +system.componentmodel.primitives\4.3.0\lib\net45\System.ComponentModel.Primitives.dll +system.componentmodel.primitives\4.3.0\lib\netstandard1.0\System.ComponentModel.Primitives.dll +system.componentmodel.primitives\4.3.0\lib\xamarinios10\_._ +system.componentmodel.primitives\4.3.0\lib\xamarinmac20\_._ +system.componentmodel.primitives\4.3.0\lib\xamarintvos10\_._ +system.componentmodel.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.componentmodel.primitives\4.3.0\ref\MonoAndroid10\_._ +system.componentmodel.primitives\4.3.0\ref\MonoTouch10\_._ +system.componentmodel.primitives\4.3.0\ref\net45\System.ComponentModel.Primitives.dll +system.componentmodel.primitives\4.3.0\ref\netstandard1.0\System.ComponentModel.Primitives.dll +system.componentmodel.primitives\4.3.0\ref\xamarinios10\_._ +system.componentmodel.primitives\4.3.0\ref\xamarinmac20\_._ +system.componentmodel.primitives\4.3.0\ref\xamarintvos10\_._ +system.componentmodel.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.componentmodel.primitives\4.3.0\system.componentmodel.primitives.4.3.0.nupkg +system.componentmodel.primitives\4.3.0\system.componentmodel.primitives.4.3.0.nupkg.sha512 +system.componentmodel.primitives\4.3.0\system.componentmodel.primitives.nuspec +system.componentmodel.primitives\4.3.0\ThirdPartyNotices.txt +system.componentmodel.typeconverter\4.3.0\dotnet_library_license.txt +system.componentmodel.typeconverter\4.3.0\lib\MonoAndroid10\_._ +system.componentmodel.typeconverter\4.3.0\lib\MonoTouch10\_._ +system.componentmodel.typeconverter\4.3.0\lib\net45\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\lib\net462\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\lib\netstandard1.0\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\lib\netstandard1.5\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\lib\xamarinios10\_._ +system.componentmodel.typeconverter\4.3.0\lib\xamarinmac20\_._ +system.componentmodel.typeconverter\4.3.0\lib\xamarintvos10\_._ +system.componentmodel.typeconverter\4.3.0\lib\xamarinwatchos10\_._ +system.componentmodel.typeconverter\4.3.0\ref\MonoAndroid10\_._ +system.componentmodel.typeconverter\4.3.0\ref\MonoTouch10\_._ +system.componentmodel.typeconverter\4.3.0\ref\net45\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\ref\net462\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\ref\netstandard1.0\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\ref\netstandard1.5\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\ref\xamarinios10\_._ +system.componentmodel.typeconverter\4.3.0\ref\xamarinmac20\_._ +system.componentmodel.typeconverter\4.3.0\ref\xamarintvos10\_._ +system.componentmodel.typeconverter\4.3.0\ref\xamarinwatchos10\_._ +system.componentmodel.typeconverter\4.3.0\system.componentmodel.typeconverter.4.3.0.nupkg +system.componentmodel.typeconverter\4.3.0\system.componentmodel.typeconverter.4.3.0.nupkg.sha512 +system.componentmodel.typeconverter\4.3.0\system.componentmodel.typeconverter.nuspec +system.componentmodel.typeconverter\4.3.0\ThirdPartyNotices.txt +system.componentmodel\4.3.0\dotnet_library_license.txt +system.componentmodel\4.3.0\lib\MonoAndroid10\_._ +system.componentmodel\4.3.0\lib\MonoTouch10\_._ +system.componentmodel\4.3.0\lib\net45\_._ +system.componentmodel\4.3.0\lib\netcore50\System.ComponentModel.dll +system.componentmodel\4.3.0\lib\netstandard1.3\System.ComponentModel.dll +system.componentmodel\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.componentmodel\4.3.0\lib\win8\_._ +system.componentmodel\4.3.0\lib\wp80\_._ +system.componentmodel\4.3.0\lib\wpa81\_._ +system.componentmodel\4.3.0\lib\xamarinios10\_._ +system.componentmodel\4.3.0\lib\xamarinmac20\_._ +system.componentmodel\4.3.0\lib\xamarintvos10\_._ +system.componentmodel\4.3.0\lib\xamarinwatchos10\_._ +system.componentmodel\4.3.0\ref\MonoAndroid10\_._ +system.componentmodel\4.3.0\ref\MonoTouch10\_._ +system.componentmodel\4.3.0\ref\net45\_._ +system.componentmodel\4.3.0\ref\netcore50\System.ComponentModel.dll +system.componentmodel\4.3.0\ref\netstandard1.0\System.ComponentModel.dll +system.componentmodel\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.componentmodel\4.3.0\ref\win8\_._ +system.componentmodel\4.3.0\ref\wp80\_._ +system.componentmodel\4.3.0\ref\wpa81\_._ +system.componentmodel\4.3.0\ref\xamarinios10\_._ +system.componentmodel\4.3.0\ref\xamarinmac20\_._ +system.componentmodel\4.3.0\ref\xamarintvos10\_._ +system.componentmodel\4.3.0\ref\xamarinwatchos10\_._ +system.componentmodel\4.3.0\system.componentmodel.4.3.0.nupkg +system.componentmodel\4.3.0\system.componentmodel.4.3.0.nupkg.sha512 +system.componentmodel\4.3.0\system.componentmodel.nuspec +system.componentmodel\4.3.0\ThirdPartyNotices.txt +system.composition.attributedmodel\1.0.31\dotnet_library_license.txt +system.composition.attributedmodel\1.0.31\lib\netstandard1.0\System.Composition.AttributedModel.dll +system.composition.attributedmodel\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll +system.composition.attributedmodel\1.0.31\system.composition.attributedmodel.1.0.31.nupkg +system.composition.attributedmodel\1.0.31\system.composition.attributedmodel.1.0.31.nupkg.sha512 +system.composition.attributedmodel\1.0.31\system.composition.attributedmodel.nuspec +system.composition.attributedmodel\1.0.31\ThirdPartyNotices.txt +system.composition.convention\1.0.31\dotnet_library_license.txt +system.composition.convention\1.0.31\lib\netstandard1.0\System.Composition.Convention.dll +system.composition.convention\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll +system.composition.convention\1.0.31\system.composition.convention.1.0.31.nupkg +system.composition.convention\1.0.31\system.composition.convention.1.0.31.nupkg.sha512 +system.composition.convention\1.0.31\system.composition.convention.nuspec +system.composition.convention\1.0.31\ThirdPartyNotices.txt +system.composition.hosting\1.0.31\dotnet_library_license.txt +system.composition.hosting\1.0.31\lib\netstandard1.0\System.Composition.Hosting.dll +system.composition.hosting\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll +system.composition.hosting\1.0.31\system.composition.hosting.1.0.31.nupkg +system.composition.hosting\1.0.31\system.composition.hosting.1.0.31.nupkg.sha512 +system.composition.hosting\1.0.31\system.composition.hosting.nuspec +system.composition.hosting\1.0.31\ThirdPartyNotices.txt +system.composition.runtime\1.0.31\dotnet_library_license.txt +system.composition.runtime\1.0.31\lib\netstandard1.0\System.Composition.Runtime.dll +system.composition.runtime\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll +system.composition.runtime\1.0.31\system.composition.runtime.1.0.31.nupkg +system.composition.runtime\1.0.31\system.composition.runtime.1.0.31.nupkg.sha512 +system.composition.runtime\1.0.31\system.composition.runtime.nuspec +system.composition.runtime\1.0.31\ThirdPartyNotices.txt +system.composition.typedparts\1.0.31\dotnet_library_license.txt +system.composition.typedparts\1.0.31\lib\netstandard1.0\System.Composition.TypedParts.dll +system.composition.typedparts\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll +system.composition.typedparts\1.0.31\system.composition.typedparts.1.0.31.nupkg +system.composition.typedparts\1.0.31\system.composition.typedparts.1.0.31.nupkg.sha512 +system.composition.typedparts\1.0.31\system.composition.typedparts.nuspec +system.composition.typedparts\1.0.31\ThirdPartyNotices.txt +system.composition\1.0.31\dotnet_library_license.txt +system.composition\1.0.31\system.composition.1.0.31.nupkg +system.composition\1.0.31\system.composition.1.0.31.nupkg.sha512 +system.composition\1.0.31\system.composition.nuspec +system.composition\1.0.31\ThirdPartyNotices.txt +system.console\4.0.0\dotnet_library_license.txt +system.console\4.0.0\lib\MonoAndroid10\_._ +system.console\4.0.0\lib\MonoTouch10\_._ +system.console\4.0.0\lib\net46\System.Console.dll +system.console\4.0.0\lib\xamarinios10\_._ +system.console\4.0.0\lib\xamarinmac20\_._ +system.console\4.0.0\lib\xamarintvos10\_._ +system.console\4.0.0\lib\xamarinwatchos10\_._ +system.console\4.0.0\ref\MonoAndroid10\_._ +system.console\4.0.0\ref\MonoTouch10\_._ +system.console\4.0.0\ref\net46\System.Console.dll +system.console\4.0.0\ref\netstandard1.3\System.Console.dll +system.console\4.0.0\ref\xamarinios10\_._ +system.console\4.0.0\ref\xamarinmac20\_._ +system.console\4.0.0\ref\xamarintvos10\_._ +system.console\4.0.0\ref\xamarinwatchos10\_._ +system.console\4.0.0\system.console.4.0.0.nupkg +system.console\4.0.0\system.console.4.0.0.nupkg.sha512 +system.console\4.0.0\system.console.nuspec +system.console\4.0.0\ThirdPartyNotices.txt +system.console\4.3.0\dotnet_library_license.txt +system.console\4.3.0\lib\MonoAndroid10\_._ +system.console\4.3.0\lib\MonoTouch10\_._ +system.console\4.3.0\lib\net46\System.Console.dll +system.console\4.3.0\lib\xamarinios10\_._ +system.console\4.3.0\lib\xamarinmac20\_._ +system.console\4.3.0\lib\xamarintvos10\_._ +system.console\4.3.0\lib\xamarinwatchos10\_._ +system.console\4.3.0\ref\MonoAndroid10\_._ +system.console\4.3.0\ref\MonoTouch10\_._ +system.console\4.3.0\ref\net46\System.Console.dll +system.console\4.3.0\ref\netstandard1.3\System.Console.dll +system.console\4.3.0\ref\xamarinios10\_._ +system.console\4.3.0\ref\xamarinmac20\_._ +system.console\4.3.0\ref\xamarintvos10\_._ +system.console\4.3.0\ref\xamarinwatchos10\_._ +system.console\4.3.0\system.console.4.3.0.nupkg +system.console\4.3.0\system.console.4.3.0.nupkg.sha512 +system.console\4.3.0\system.console.nuspec +system.console\4.3.0\ThirdPartyNotices.txt +system.data.sqlclient\4.5.1\.signature.p7s +system.data.sqlclient\4.5.1\lib\MonoAndroid10\_._ +system.data.sqlclient\4.5.1\lib\MonoTouch10\_._ +system.data.sqlclient\4.5.1\lib\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\netstandard1.2\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\xamarinios10\_._ +system.data.sqlclient\4.5.1\lib\xamarinmac20\_._ +system.data.sqlclient\4.5.1\lib\xamarintvos10\_._ +system.data.sqlclient\4.5.1\lib\xamarinwatchos10\_._ +system.data.sqlclient\4.5.1\LICENSE.TXT +system.data.sqlclient\4.5.1\ref\MonoAndroid10\_._ +system.data.sqlclient\4.5.1\ref\MonoTouch10\_._ +system.data.sqlclient\4.5.1\ref\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\netstandard1.2\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\xamarinios10\_._ +system.data.sqlclient\4.5.1\ref\xamarinmac20\_._ +system.data.sqlclient\4.5.1\ref\xamarintvos10\_._ +system.data.sqlclient\4.5.1\ref\xamarinwatchos10\_._ +system.data.sqlclient\4.5.1\runtimes\unix\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\unix\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\unix\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\uap10.0.16299\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\system.data.sqlclient.4.5.1.nupkg +system.data.sqlclient\4.5.1\system.data.sqlclient.4.5.1.nupkg.sha512 +system.data.sqlclient\4.5.1\system.data.sqlclient.nuspec +system.data.sqlclient\4.5.1\THIRD-PARTY-NOTICES.TXT +system.data.sqlclient\4.5.1\useSharedDesignerContext.txt +system.data.sqlclient\4.5.1\version.txt +system.diagnostics.contracts\4.3.0\dotnet_library_license.txt +system.diagnostics.contracts\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.contracts\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.contracts\4.3.0\lib\net45\_._ +system.diagnostics.contracts\4.3.0\lib\netcore50\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\lib\netstandard1.0\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.contracts\4.3.0\lib\win8\_._ +system.diagnostics.contracts\4.3.0\lib\wp80\_._ +system.diagnostics.contracts\4.3.0\lib\wpa81\_._ +system.diagnostics.contracts\4.3.0\lib\xamarinios10\_._ +system.diagnostics.contracts\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.contracts\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.contracts\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.contracts\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.contracts\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.contracts\4.3.0\ref\net45\_._ +system.diagnostics.contracts\4.3.0\ref\netcore50\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\ref\netstandard1.0\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.contracts\4.3.0\ref\win8\_._ +system.diagnostics.contracts\4.3.0\ref\wp80\_._ +system.diagnostics.contracts\4.3.0\ref\wpa81\_._ +system.diagnostics.contracts\4.3.0\ref\xamarinios10\_._ +system.diagnostics.contracts\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.contracts\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.contracts\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.contracts\4.3.0\runtimes\aot\lib\netcore50\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\system.diagnostics.contracts.4.3.0.nupkg +system.diagnostics.contracts\4.3.0\system.diagnostics.contracts.4.3.0.nupkg.sha512 +system.diagnostics.contracts\4.3.0\system.diagnostics.contracts.nuspec +system.diagnostics.contracts\4.3.0\ThirdPartyNotices.txt +system.diagnostics.debug\4.0.11\dotnet_library_license.txt +system.diagnostics.debug\4.0.11\lib\MonoAndroid10\_._ +system.diagnostics.debug\4.0.11\lib\MonoTouch10\_._ +system.diagnostics.debug\4.0.11\lib\net45\_._ +system.diagnostics.debug\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.debug\4.0.11\lib\win8\_._ +system.diagnostics.debug\4.0.11\lib\wp80\_._ +system.diagnostics.debug\4.0.11\lib\wpa81\_._ +system.diagnostics.debug\4.0.11\lib\xamarinios10\_._ +system.diagnostics.debug\4.0.11\lib\xamarinmac20\_._ +system.diagnostics.debug\4.0.11\lib\xamarintvos10\_._ +system.diagnostics.debug\4.0.11\lib\xamarinwatchos10\_._ +system.diagnostics.debug\4.0.11\ref\MonoAndroid10\_._ +system.diagnostics.debug\4.0.11\ref\MonoTouch10\_._ +system.diagnostics.debug\4.0.11\ref\net45\_._ +system.diagnostics.debug\4.0.11\ref\netcore50\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.0.11\ref\netstandard1.0\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.0.11\ref\netstandard1.3\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.debug\4.0.11\ref\win8\_._ +system.diagnostics.debug\4.0.11\ref\wp80\_._ +system.diagnostics.debug\4.0.11\ref\wpa81\_._ +system.diagnostics.debug\4.0.11\ref\xamarinios10\_._ +system.diagnostics.debug\4.0.11\ref\xamarinmac20\_._ +system.diagnostics.debug\4.0.11\ref\xamarintvos10\_._ +system.diagnostics.debug\4.0.11\ref\xamarinwatchos10\_._ +system.diagnostics.debug\4.0.11\system.diagnostics.debug.4.0.11.nupkg +system.diagnostics.debug\4.0.11\system.diagnostics.debug.4.0.11.nupkg.sha512 +system.diagnostics.debug\4.0.11\system.diagnostics.debug.nuspec +system.diagnostics.debug\4.0.11\ThirdPartyNotices.txt +system.diagnostics.debug\4.3.0\dotnet_library_license.txt +system.diagnostics.debug\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.debug\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.debug\4.3.0\lib\net45\_._ +system.diagnostics.debug\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.debug\4.3.0\lib\win8\_._ +system.diagnostics.debug\4.3.0\lib\wp80\_._ +system.diagnostics.debug\4.3.0\lib\wpa81\_._ +system.diagnostics.debug\4.3.0\lib\xamarinios10\_._ +system.diagnostics.debug\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.debug\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.debug\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.debug\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.debug\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.debug\4.3.0\ref\net45\_._ +system.diagnostics.debug\4.3.0\ref\netcore50\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.3.0\ref\netstandard1.0\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.3.0\ref\netstandard1.3\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.debug\4.3.0\ref\win8\_._ +system.diagnostics.debug\4.3.0\ref\wp80\_._ +system.diagnostics.debug\4.3.0\ref\wpa81\_._ +system.diagnostics.debug\4.3.0\ref\xamarinios10\_._ +system.diagnostics.debug\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.debug\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.debug\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.debug\4.3.0\system.diagnostics.debug.4.3.0.nupkg +system.diagnostics.debug\4.3.0\system.diagnostics.debug.4.3.0.nupkg.sha512 +system.diagnostics.debug\4.3.0\system.diagnostics.debug.nuspec +system.diagnostics.debug\4.3.0\ThirdPartyNotices.txt +system.diagnostics.diagnosticsource\4.0.0\dotnet_library_license.txt +system.diagnostics.diagnosticsource\4.0.0\lib\net46\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.0.0\lib\netstandard1.1\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.0.0\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.0.0\lib\portable-net45+win8+wpa81\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.0.0\system.diagnostics.diagnosticsource.4.0.0.nupkg +system.diagnostics.diagnosticsource\4.0.0\system.diagnostics.diagnosticsource.4.0.0.nupkg.sha512 +system.diagnostics.diagnosticsource\4.0.0\system.diagnostics.diagnosticsource.nuspec +system.diagnostics.diagnosticsource\4.0.0\ThirdPartyNotices.txt +system.diagnostics.diagnosticsource\4.3.0\dotnet_library_license.txt +system.diagnostics.diagnosticsource\4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.3.0\lib\netstandard1.1\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.3.0\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.3.0\lib\portable-net45+win8+wpa81\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.3.0\system.diagnostics.diagnosticsource.4.3.0.nupkg +system.diagnostics.diagnosticsource\4.3.0\system.diagnostics.diagnosticsource.4.3.0.nupkg.sha512 +system.diagnostics.diagnosticsource\4.3.0\system.diagnostics.diagnosticsource.nuspec +system.diagnostics.diagnosticsource\4.3.0\ThirdPartyNotices.txt +system.diagnostics.diagnosticsource\4.4.0\lib\net45\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\lib\net46\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\lib\netcoreapp2.0\_._ +system.diagnostics.diagnosticsource\4.4.0\lib\netstandard1.1\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\lib\portable-net45+win8+wpa81\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\LICENSE.TXT +system.diagnostics.diagnosticsource\4.4.0\ref\netcoreapp2.0\_._ +system.diagnostics.diagnosticsource\4.4.0\system.diagnostics.diagnosticsource.4.4.0.nupkg +system.diagnostics.diagnosticsource\4.4.0\system.diagnostics.diagnosticsource.4.4.0.nupkg.sha512 +system.diagnostics.diagnosticsource\4.4.0\system.diagnostics.diagnosticsource.nuspec +system.diagnostics.diagnosticsource\4.4.0\THIRD-PARTY-NOTICES.TXT +system.diagnostics.diagnosticsource\4.4.0\useSharedDesignerContext.txt +system.diagnostics.diagnosticsource\4.4.0\version.txt +system.diagnostics.diagnosticsource\4.5.0\.signature.p7s +system.diagnostics.diagnosticsource\4.5.0\lib\net45\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\lib\net46\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\lib\netstandard1.1\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\lib\portable-net45+win8+wpa81\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\LICENSE.TXT +system.diagnostics.diagnosticsource\4.5.0\system.diagnostics.diagnosticsource.4.5.0.nupkg +system.diagnostics.diagnosticsource\4.5.0\system.diagnostics.diagnosticsource.4.5.0.nupkg.sha512 +system.diagnostics.diagnosticsource\4.5.0\system.diagnostics.diagnosticsource.nuspec +system.diagnostics.diagnosticsource\4.5.0\THIRD-PARTY-NOTICES.TXT +system.diagnostics.diagnosticsource\4.5.0\useSharedDesignerContext.txt +system.diagnostics.diagnosticsource\4.5.0\version.txt +system.diagnostics.fileversioninfo\4.3.0\dotnet_library_license.txt +system.diagnostics.fileversioninfo\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\lib\xamarinios10\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\net46\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\ref\netstandard1.3\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\ref\xamarinios10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.fileversioninfo\4.3.0\runtimes\unix\lib\netstandard1.3\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\runtimes\win\lib\net46\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\runtimes\win\lib\netcore50\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\runtimes\win\lib\netstandard1.3\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\system.diagnostics.fileversioninfo.4.3.0.nupkg +system.diagnostics.fileversioninfo\4.3.0\system.diagnostics.fileversioninfo.4.3.0.nupkg.sha512 +system.diagnostics.fileversioninfo\4.3.0\system.diagnostics.fileversioninfo.nuspec +system.diagnostics.fileversioninfo\4.3.0\ThirdPartyNotices.txt +system.diagnostics.process\4.3.0\dotnet_library_license.txt +system.diagnostics.process\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.process\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.process\4.3.0\lib\net46\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\lib\net461\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\lib\xamarinios10\_._ +system.diagnostics.process\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.process\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.process\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.process\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.process\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.process\4.3.0\ref\net46\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\ref\net461\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\ref\netstandard1.3\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\ref\netstandard1.4\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\ref\xamarinios10\_._ +system.diagnostics.process\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.process\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.process\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.process\4.3.0\runtimes\linux\lib\netstandard1.4\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\osx\lib\netstandard1.4\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\win\lib\net46\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\win\lib\net461\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\win\lib\netstandard1.4\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\win7\lib\netcore50\_._ +system.diagnostics.process\4.3.0\system.diagnostics.process.4.3.0.nupkg +system.diagnostics.process\4.3.0\system.diagnostics.process.4.3.0.nupkg.sha512 +system.diagnostics.process\4.3.0\system.diagnostics.process.nuspec +system.diagnostics.process\4.3.0\ThirdPartyNotices.txt +system.diagnostics.stacktrace\4.3.0\dotnet_library_license.txt +system.diagnostics.stacktrace\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.stacktrace\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.stacktrace\4.3.0\lib\net46\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\lib\netstandard1.3\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\lib\xamarinios10\_._ +system.diagnostics.stacktrace\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.stacktrace\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.stacktrace\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.stacktrace\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.stacktrace\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.stacktrace\4.3.0\ref\net46\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\ref\netstandard1.3\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\ref\xamarinios10\_._ +system.diagnostics.stacktrace\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.stacktrace\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.stacktrace\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.stacktrace\4.3.0\runtimes\aot\lib\netcore50\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\system.diagnostics.stacktrace.4.3.0.nupkg +system.diagnostics.stacktrace\4.3.0\system.diagnostics.stacktrace.4.3.0.nupkg.sha512 +system.diagnostics.stacktrace\4.3.0\system.diagnostics.stacktrace.nuspec +system.diagnostics.stacktrace\4.3.0\ThirdPartyNotices.txt +system.diagnostics.tools\4.0.1\dotnet_library_license.txt +system.diagnostics.tools\4.0.1\lib\MonoAndroid10\_._ +system.diagnostics.tools\4.0.1\lib\MonoTouch10\_._ +system.diagnostics.tools\4.0.1\lib\net45\_._ +system.diagnostics.tools\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.tools\4.0.1\lib\win8\_._ +system.diagnostics.tools\4.0.1\lib\wp80\_._ +system.diagnostics.tools\4.0.1\lib\wpa81\_._ +system.diagnostics.tools\4.0.1\lib\xamarinios10\_._ +system.diagnostics.tools\4.0.1\lib\xamarinmac20\_._ +system.diagnostics.tools\4.0.1\lib\xamarintvos10\_._ +system.diagnostics.tools\4.0.1\lib\xamarinwatchos10\_._ +system.diagnostics.tools\4.0.1\ref\MonoAndroid10\_._ +system.diagnostics.tools\4.0.1\ref\MonoTouch10\_._ +system.diagnostics.tools\4.0.1\ref\net45\_._ +system.diagnostics.tools\4.0.1\ref\netcore50\System.Diagnostics.Tools.dll +system.diagnostics.tools\4.0.1\ref\netstandard1.0\System.Diagnostics.Tools.dll +system.diagnostics.tools\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.tools\4.0.1\ref\win8\_._ +system.diagnostics.tools\4.0.1\ref\wp80\_._ +system.diagnostics.tools\4.0.1\ref\wpa81\_._ +system.diagnostics.tools\4.0.1\ref\xamarinios10\_._ +system.diagnostics.tools\4.0.1\ref\xamarinmac20\_._ +system.diagnostics.tools\4.0.1\ref\xamarintvos10\_._ +system.diagnostics.tools\4.0.1\ref\xamarinwatchos10\_._ +system.diagnostics.tools\4.0.1\system.diagnostics.tools.4.0.1.nupkg +system.diagnostics.tools\4.0.1\system.diagnostics.tools.4.0.1.nupkg.sha512 +system.diagnostics.tools\4.0.1\system.diagnostics.tools.nuspec +system.diagnostics.tools\4.0.1\ThirdPartyNotices.txt +system.diagnostics.tools\4.3.0\dotnet_library_license.txt +system.diagnostics.tools\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.tools\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.tools\4.3.0\lib\net45\_._ +system.diagnostics.tools\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.tools\4.3.0\lib\win8\_._ +system.diagnostics.tools\4.3.0\lib\wp80\_._ +system.diagnostics.tools\4.3.0\lib\wpa81\_._ +system.diagnostics.tools\4.3.0\lib\xamarinios10\_._ +system.diagnostics.tools\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.tools\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.tools\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.tools\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.tools\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.tools\4.3.0\ref\net45\_._ +system.diagnostics.tools\4.3.0\ref\netcore50\System.Diagnostics.Tools.dll +system.diagnostics.tools\4.3.0\ref\netstandard1.0\System.Diagnostics.Tools.dll +system.diagnostics.tools\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.tools\4.3.0\ref\win8\_._ +system.diagnostics.tools\4.3.0\ref\wp80\_._ +system.diagnostics.tools\4.3.0\ref\wpa81\_._ +system.diagnostics.tools\4.3.0\ref\xamarinios10\_._ +system.diagnostics.tools\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.tools\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.tools\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.tools\4.3.0\system.diagnostics.tools.4.3.0.nupkg +system.diagnostics.tools\4.3.0\system.diagnostics.tools.4.3.0.nupkg.sha512 +system.diagnostics.tools\4.3.0\system.diagnostics.tools.nuspec +system.diagnostics.tools\4.3.0\ThirdPartyNotices.txt +system.diagnostics.tracing\4.1.0\dotnet_library_license.txt +system.diagnostics.tracing\4.1.0\lib\MonoAndroid10\_._ +system.diagnostics.tracing\4.1.0\lib\MonoTouch10\_._ +system.diagnostics.tracing\4.1.0\lib\net45\_._ +system.diagnostics.tracing\4.1.0\lib\net462\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\lib\portable-net45+win8+wpa81\_._ +system.diagnostics.tracing\4.1.0\lib\win8\_._ +system.diagnostics.tracing\4.1.0\lib\wpa81\_._ +system.diagnostics.tracing\4.1.0\lib\xamarinios10\_._ +system.diagnostics.tracing\4.1.0\lib\xamarinmac20\_._ +system.diagnostics.tracing\4.1.0\lib\xamarintvos10\_._ +system.diagnostics.tracing\4.1.0\lib\xamarinwatchos10\_._ +system.diagnostics.tracing\4.1.0\ref\MonoAndroid10\_._ +system.diagnostics.tracing\4.1.0\ref\MonoTouch10\_._ +system.diagnostics.tracing\4.1.0\ref\net45\_._ +system.diagnostics.tracing\4.1.0\ref\net462\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netcore50\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netstandard1.1\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netstandard1.2\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netstandard1.3\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netstandard1.5\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\portable-net45+win8+wpa81\_._ +system.diagnostics.tracing\4.1.0\ref\win8\_._ +system.diagnostics.tracing\4.1.0\ref\wpa81\_._ +system.diagnostics.tracing\4.1.0\ref\xamarinios10\_._ +system.diagnostics.tracing\4.1.0\ref\xamarinmac20\_._ +system.diagnostics.tracing\4.1.0\ref\xamarintvos10\_._ +system.diagnostics.tracing\4.1.0\ref\xamarinwatchos10\_._ +system.diagnostics.tracing\4.1.0\system.diagnostics.tracing.4.1.0.nupkg +system.diagnostics.tracing\4.1.0\system.diagnostics.tracing.4.1.0.nupkg.sha512 +system.diagnostics.tracing\4.1.0\system.diagnostics.tracing.nuspec +system.diagnostics.tracing\4.1.0\ThirdPartyNotices.txt +system.diagnostics.tracing\4.3.0\dotnet_library_license.txt +system.diagnostics.tracing\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.tracing\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.tracing\4.3.0\lib\net45\_._ +system.diagnostics.tracing\4.3.0\lib\net462\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.diagnostics.tracing\4.3.0\lib\win8\_._ +system.diagnostics.tracing\4.3.0\lib\wpa81\_._ +system.diagnostics.tracing\4.3.0\lib\xamarinios10\_._ +system.diagnostics.tracing\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.tracing\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.tracing\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.tracing\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.tracing\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.tracing\4.3.0\ref\net45\_._ +system.diagnostics.tracing\4.3.0\ref\net462\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netcore50\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netstandard1.1\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netstandard1.2\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netstandard1.3\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netstandard1.5\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.diagnostics.tracing\4.3.0\ref\win8\_._ +system.diagnostics.tracing\4.3.0\ref\wpa81\_._ +system.diagnostics.tracing\4.3.0\ref\xamarinios10\_._ +system.diagnostics.tracing\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.tracing\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.tracing\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.tracing\4.3.0\system.diagnostics.tracing.4.3.0.nupkg +system.diagnostics.tracing\4.3.0\system.diagnostics.tracing.4.3.0.nupkg.sha512 +system.diagnostics.tracing\4.3.0\system.diagnostics.tracing.nuspec +system.diagnostics.tracing\4.3.0\ThirdPartyNotices.txt +system.dynamic.runtime\4.0.11\dotnet_library_license.txt +system.dynamic.runtime\4.0.11\lib\MonoAndroid10\_._ +system.dynamic.runtime\4.0.11\lib\MonoTouch10\_._ +system.dynamic.runtime\4.0.11\lib\net45\_._ +system.dynamic.runtime\4.0.11\lib\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\lib\netstandard1.3\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.dynamic.runtime\4.0.11\lib\win8\_._ +system.dynamic.runtime\4.0.11\lib\wp80\_._ +system.dynamic.runtime\4.0.11\lib\wpa81\_._ +system.dynamic.runtime\4.0.11\lib\xamarinios10\_._ +system.dynamic.runtime\4.0.11\lib\xamarinmac20\_._ +system.dynamic.runtime\4.0.11\lib\xamarintvos10\_._ +system.dynamic.runtime\4.0.11\lib\xamarinwatchos10\_._ +system.dynamic.runtime\4.0.11\ref\MonoAndroid10\_._ +system.dynamic.runtime\4.0.11\ref\MonoTouch10\_._ +system.dynamic.runtime\4.0.11\ref\net45\_._ +system.dynamic.runtime\4.0.11\ref\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\ref\netstandard1.0\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\ref\netstandard1.3\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.dynamic.runtime\4.0.11\ref\win8\_._ +system.dynamic.runtime\4.0.11\ref\wp80\_._ +system.dynamic.runtime\4.0.11\ref\wpa81\_._ +system.dynamic.runtime\4.0.11\ref\xamarinios10\_._ +system.dynamic.runtime\4.0.11\ref\xamarinmac20\_._ +system.dynamic.runtime\4.0.11\ref\xamarintvos10\_._ +system.dynamic.runtime\4.0.11\ref\xamarinwatchos10\_._ +system.dynamic.runtime\4.0.11\runtimes\aot\lib\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\system.dynamic.runtime.4.0.11.nupkg +system.dynamic.runtime\4.0.11\system.dynamic.runtime.4.0.11.nupkg.sha512 +system.dynamic.runtime\4.0.11\system.dynamic.runtime.nuspec +system.dynamic.runtime\4.0.11\ThirdPartyNotices.txt +system.dynamic.runtime\4.3.0\dotnet_library_license.txt +system.dynamic.runtime\4.3.0\lib\MonoAndroid10\_._ +system.dynamic.runtime\4.3.0\lib\MonoTouch10\_._ +system.dynamic.runtime\4.3.0\lib\net45\_._ +system.dynamic.runtime\4.3.0\lib\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\lib\netstandard1.3\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.dynamic.runtime\4.3.0\lib\win8\_._ +system.dynamic.runtime\4.3.0\lib\wp80\_._ +system.dynamic.runtime\4.3.0\lib\wpa81\_._ +system.dynamic.runtime\4.3.0\lib\xamarinios10\_._ +system.dynamic.runtime\4.3.0\lib\xamarinmac20\_._ +system.dynamic.runtime\4.3.0\lib\xamarintvos10\_._ +system.dynamic.runtime\4.3.0\lib\xamarinwatchos10\_._ +system.dynamic.runtime\4.3.0\ref\MonoAndroid10\_._ +system.dynamic.runtime\4.3.0\ref\MonoTouch10\_._ +system.dynamic.runtime\4.3.0\ref\net45\_._ +system.dynamic.runtime\4.3.0\ref\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\ref\netstandard1.0\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\ref\netstandard1.3\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.dynamic.runtime\4.3.0\ref\win8\_._ +system.dynamic.runtime\4.3.0\ref\wp80\_._ +system.dynamic.runtime\4.3.0\ref\wpa81\_._ +system.dynamic.runtime\4.3.0\ref\xamarinios10\_._ +system.dynamic.runtime\4.3.0\ref\xamarinmac20\_._ +system.dynamic.runtime\4.3.0\ref\xamarintvos10\_._ +system.dynamic.runtime\4.3.0\ref\xamarinwatchos10\_._ +system.dynamic.runtime\4.3.0\runtimes\aot\lib\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\system.dynamic.runtime.4.3.0.nupkg +system.dynamic.runtime\4.3.0\system.dynamic.runtime.4.3.0.nupkg.sha512 +system.dynamic.runtime\4.3.0\system.dynamic.runtime.nuspec +system.dynamic.runtime\4.3.0\ThirdPartyNotices.txt +system.globalization.calendars\4.0.1\dotnet_library_license.txt +system.globalization.calendars\4.0.1\lib\MonoAndroid10\_._ +system.globalization.calendars\4.0.1\lib\MonoTouch10\_._ +system.globalization.calendars\4.0.1\lib\net46\System.Globalization.Calendars.dll +system.globalization.calendars\4.0.1\lib\xamarinios10\_._ +system.globalization.calendars\4.0.1\lib\xamarinmac20\_._ +system.globalization.calendars\4.0.1\lib\xamarintvos10\_._ +system.globalization.calendars\4.0.1\lib\xamarinwatchos10\_._ +system.globalization.calendars\4.0.1\ref\MonoAndroid10\_._ +system.globalization.calendars\4.0.1\ref\MonoTouch10\_._ +system.globalization.calendars\4.0.1\ref\net46\System.Globalization.Calendars.dll +system.globalization.calendars\4.0.1\ref\netstandard1.3\System.Globalization.Calendars.dll +system.globalization.calendars\4.0.1\ref\xamarinios10\_._ +system.globalization.calendars\4.0.1\ref\xamarinmac20\_._ +system.globalization.calendars\4.0.1\ref\xamarintvos10\_._ +system.globalization.calendars\4.0.1\ref\xamarinwatchos10\_._ +system.globalization.calendars\4.0.1\system.globalization.calendars.4.0.1.nupkg +system.globalization.calendars\4.0.1\system.globalization.calendars.4.0.1.nupkg.sha512 +system.globalization.calendars\4.0.1\system.globalization.calendars.nuspec +system.globalization.calendars\4.0.1\ThirdPartyNotices.txt +system.globalization.calendars\4.3.0\dotnet_library_license.txt +system.globalization.calendars\4.3.0\lib\MonoAndroid10\_._ +system.globalization.calendars\4.3.0\lib\MonoTouch10\_._ +system.globalization.calendars\4.3.0\lib\net46\System.Globalization.Calendars.dll +system.globalization.calendars\4.3.0\lib\xamarinios10\_._ +system.globalization.calendars\4.3.0\lib\xamarinmac20\_._ +system.globalization.calendars\4.3.0\lib\xamarintvos10\_._ +system.globalization.calendars\4.3.0\lib\xamarinwatchos10\_._ +system.globalization.calendars\4.3.0\ref\MonoAndroid10\_._ +system.globalization.calendars\4.3.0\ref\MonoTouch10\_._ +system.globalization.calendars\4.3.0\ref\net46\System.Globalization.Calendars.dll +system.globalization.calendars\4.3.0\ref\netstandard1.3\System.Globalization.Calendars.dll +system.globalization.calendars\4.3.0\ref\xamarinios10\_._ +system.globalization.calendars\4.3.0\ref\xamarinmac20\_._ +system.globalization.calendars\4.3.0\ref\xamarintvos10\_._ +system.globalization.calendars\4.3.0\ref\xamarinwatchos10\_._ +system.globalization.calendars\4.3.0\system.globalization.calendars.4.3.0.nupkg +system.globalization.calendars\4.3.0\system.globalization.calendars.4.3.0.nupkg.sha512 +system.globalization.calendars\4.3.0\system.globalization.calendars.nuspec +system.globalization.calendars\4.3.0\ThirdPartyNotices.txt +system.globalization.extensions\4.0.1\dotnet_library_license.txt +system.globalization.extensions\4.0.1\lib\MonoAndroid10\_._ +system.globalization.extensions\4.0.1\lib\MonoTouch10\_._ +system.globalization.extensions\4.0.1\lib\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\lib\xamarinios10\_._ +system.globalization.extensions\4.0.1\lib\xamarinmac20\_._ +system.globalization.extensions\4.0.1\lib\xamarintvos10\_._ +system.globalization.extensions\4.0.1\lib\xamarinwatchos10\_._ +system.globalization.extensions\4.0.1\ref\MonoAndroid10\_._ +system.globalization.extensions\4.0.1\ref\MonoTouch10\_._ +system.globalization.extensions\4.0.1\ref\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\ref\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\ref\xamarinios10\_._ +system.globalization.extensions\4.0.1\ref\xamarinmac20\_._ +system.globalization.extensions\4.0.1\ref\xamarintvos10\_._ +system.globalization.extensions\4.0.1\ref\xamarinwatchos10\_._ +system.globalization.extensions\4.0.1\runtimes\unix\lib\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\runtimes\win\lib\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\runtimes\win\lib\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\system.globalization.extensions.4.0.1.nupkg +system.globalization.extensions\4.0.1\system.globalization.extensions.4.0.1.nupkg.sha512 +system.globalization.extensions\4.0.1\system.globalization.extensions.nuspec +system.globalization.extensions\4.0.1\ThirdPartyNotices.txt +system.globalization.extensions\4.3.0\dotnet_library_license.txt +system.globalization.extensions\4.3.0\lib\MonoAndroid10\_._ +system.globalization.extensions\4.3.0\lib\MonoTouch10\_._ +system.globalization.extensions\4.3.0\lib\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\lib\xamarinios10\_._ +system.globalization.extensions\4.3.0\lib\xamarinmac20\_._ +system.globalization.extensions\4.3.0\lib\xamarintvos10\_._ +system.globalization.extensions\4.3.0\lib\xamarinwatchos10\_._ +system.globalization.extensions\4.3.0\ref\MonoAndroid10\_._ +system.globalization.extensions\4.3.0\ref\MonoTouch10\_._ +system.globalization.extensions\4.3.0\ref\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\ref\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\ref\xamarinios10\_._ +system.globalization.extensions\4.3.0\ref\xamarinmac20\_._ +system.globalization.extensions\4.3.0\ref\xamarintvos10\_._ +system.globalization.extensions\4.3.0\ref\xamarinwatchos10\_._ +system.globalization.extensions\4.3.0\runtimes\unix\lib\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\runtimes\win\lib\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\runtimes\win\lib\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\system.globalization.extensions.4.3.0.nupkg +system.globalization.extensions\4.3.0\system.globalization.extensions.4.3.0.nupkg.sha512 +system.globalization.extensions\4.3.0\system.globalization.extensions.nuspec +system.globalization.extensions\4.3.0\ThirdPartyNotices.txt +system.globalization\4.0.11\dotnet_library_license.txt +system.globalization\4.0.11\lib\MonoAndroid10\_._ +system.globalization\4.0.11\lib\MonoTouch10\_._ +system.globalization\4.0.11\lib\net45\_._ +system.globalization\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.globalization\4.0.11\lib\win8\_._ +system.globalization\4.0.11\lib\wp80\_._ +system.globalization\4.0.11\lib\wpa81\_._ +system.globalization\4.0.11\lib\xamarinios10\_._ +system.globalization\4.0.11\lib\xamarinmac20\_._ +system.globalization\4.0.11\lib\xamarintvos10\_._ +system.globalization\4.0.11\lib\xamarinwatchos10\_._ +system.globalization\4.0.11\ref\MonoAndroid10\_._ +system.globalization\4.0.11\ref\MonoTouch10\_._ +system.globalization\4.0.11\ref\net45\_._ +system.globalization\4.0.11\ref\netcore50\System.Globalization.dll +system.globalization\4.0.11\ref\netstandard1.0\System.Globalization.dll +system.globalization\4.0.11\ref\netstandard1.3\System.Globalization.dll +system.globalization\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.globalization\4.0.11\ref\win8\_._ +system.globalization\4.0.11\ref\wp80\_._ +system.globalization\4.0.11\ref\wpa81\_._ +system.globalization\4.0.11\ref\xamarinios10\_._ +system.globalization\4.0.11\ref\xamarinmac20\_._ +system.globalization\4.0.11\ref\xamarintvos10\_._ +system.globalization\4.0.11\ref\xamarinwatchos10\_._ +system.globalization\4.0.11\system.globalization.4.0.11.nupkg +system.globalization\4.0.11\system.globalization.4.0.11.nupkg.sha512 +system.globalization\4.0.11\system.globalization.nuspec +system.globalization\4.0.11\ThirdPartyNotices.txt +system.globalization\4.3.0\dotnet_library_license.txt +system.globalization\4.3.0\lib\MonoAndroid10\_._ +system.globalization\4.3.0\lib\MonoTouch10\_._ +system.globalization\4.3.0\lib\net45\_._ +system.globalization\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.globalization\4.3.0\lib\win8\_._ +system.globalization\4.3.0\lib\wp80\_._ +system.globalization\4.3.0\lib\wpa81\_._ +system.globalization\4.3.0\lib\xamarinios10\_._ +system.globalization\4.3.0\lib\xamarinmac20\_._ +system.globalization\4.3.0\lib\xamarintvos10\_._ +system.globalization\4.3.0\lib\xamarinwatchos10\_._ +system.globalization\4.3.0\ref\MonoAndroid10\_._ +system.globalization\4.3.0\ref\MonoTouch10\_._ +system.globalization\4.3.0\ref\net45\_._ +system.globalization\4.3.0\ref\netcore50\System.Globalization.dll +system.globalization\4.3.0\ref\netstandard1.0\System.Globalization.dll +system.globalization\4.3.0\ref\netstandard1.3\System.Globalization.dll +system.globalization\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.globalization\4.3.0\ref\win8\_._ +system.globalization\4.3.0\ref\wp80\_._ +system.globalization\4.3.0\ref\wpa81\_._ +system.globalization\4.3.0\ref\xamarinios10\_._ +system.globalization\4.3.0\ref\xamarinmac20\_._ +system.globalization\4.3.0\ref\xamarintvos10\_._ +system.globalization\4.3.0\ref\xamarinwatchos10\_._ +system.globalization\4.3.0\system.globalization.4.3.0.nupkg +system.globalization\4.3.0\system.globalization.4.3.0.nupkg.sha512 +system.globalization\4.3.0\system.globalization.nuspec +system.globalization\4.3.0\ThirdPartyNotices.txt +system.identitymodel.tokens.jwt\5.2.0\lib\net45\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.2.0\lib\net451\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.2.0\lib\netstandard1.4\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.2.0\system.identitymodel.tokens.jwt.5.2.0.nupkg +system.identitymodel.tokens.jwt\5.2.0\system.identitymodel.tokens.jwt.5.2.0.nupkg.sha512 +system.identitymodel.tokens.jwt\5.2.0\system.identitymodel.tokens.jwt.nuspec +system.interactive.async\3.1.1\lib\net45\System.Interactive.Async.dll +system.interactive.async\3.1.1\lib\net46\System.Interactive.Async.dll +system.interactive.async\3.1.1\lib\netstandard1.0\System.Interactive.Async.dll +system.interactive.async\3.1.1\lib\netstandard1.3\System.Interactive.Async.dll +system.interactive.async\3.1.1\system.interactive.async.3.1.1.nupkg +system.interactive.async\3.1.1\system.interactive.async.3.1.1.nupkg.sha512 +system.interactive.async\3.1.1\system.interactive.async.nuspec +system.io.compression.zipfile\4.0.1\dotnet_library_license.txt +system.io.compression.zipfile\4.0.1\lib\MonoAndroid10\_._ +system.io.compression.zipfile\4.0.1\lib\MonoTouch10\_._ +system.io.compression.zipfile\4.0.1\lib\net46\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.0.1\lib\netstandard1.3\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.0.1\lib\xamarinios10\_._ +system.io.compression.zipfile\4.0.1\lib\xamarinmac20\_._ +system.io.compression.zipfile\4.0.1\lib\xamarintvos10\_._ +system.io.compression.zipfile\4.0.1\lib\xamarinwatchos10\_._ +system.io.compression.zipfile\4.0.1\ref\MonoAndroid10\_._ +system.io.compression.zipfile\4.0.1\ref\MonoTouch10\_._ +system.io.compression.zipfile\4.0.1\ref\net46\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.0.1\ref\netstandard1.3\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.0.1\ref\xamarinios10\_._ +system.io.compression.zipfile\4.0.1\ref\xamarinmac20\_._ +system.io.compression.zipfile\4.0.1\ref\xamarintvos10\_._ +system.io.compression.zipfile\4.0.1\ref\xamarinwatchos10\_._ +system.io.compression.zipfile\4.0.1\system.io.compression.zipfile.4.0.1.nupkg +system.io.compression.zipfile\4.0.1\system.io.compression.zipfile.4.0.1.nupkg.sha512 +system.io.compression.zipfile\4.0.1\system.io.compression.zipfile.nuspec +system.io.compression.zipfile\4.0.1\ThirdPartyNotices.txt +system.io.compression.zipfile\4.3.0\dotnet_library_license.txt +system.io.compression.zipfile\4.3.0\lib\MonoAndroid10\_._ +system.io.compression.zipfile\4.3.0\lib\MonoTouch10\_._ +system.io.compression.zipfile\4.3.0\lib\net46\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.3.0\lib\netstandard1.3\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.3.0\lib\xamarinios10\_._ +system.io.compression.zipfile\4.3.0\lib\xamarinmac20\_._ +system.io.compression.zipfile\4.3.0\lib\xamarintvos10\_._ +system.io.compression.zipfile\4.3.0\lib\xamarinwatchos10\_._ +system.io.compression.zipfile\4.3.0\ref\MonoAndroid10\_._ +system.io.compression.zipfile\4.3.0\ref\MonoTouch10\_._ +system.io.compression.zipfile\4.3.0\ref\net46\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.3.0\ref\netstandard1.3\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.3.0\ref\xamarinios10\_._ +system.io.compression.zipfile\4.3.0\ref\xamarinmac20\_._ +system.io.compression.zipfile\4.3.0\ref\xamarintvos10\_._ +system.io.compression.zipfile\4.3.0\ref\xamarinwatchos10\_._ +system.io.compression.zipfile\4.3.0\system.io.compression.zipfile.4.3.0.nupkg +system.io.compression.zipfile\4.3.0\system.io.compression.zipfile.4.3.0.nupkg.sha512 +system.io.compression.zipfile\4.3.0\system.io.compression.zipfile.nuspec +system.io.compression.zipfile\4.3.0\ThirdPartyNotices.txt +system.io.compression\4.1.0\dotnet_library_license.txt +system.io.compression\4.1.0\lib\MonoAndroid10\_._ +system.io.compression\4.1.0\lib\MonoTouch10\_._ +system.io.compression\4.1.0\lib\net45\_._ +system.io.compression\4.1.0\lib\net46\System.IO.Compression.dll +system.io.compression\4.1.0\lib\portable-net45+win8+wpa81\_._ +system.io.compression\4.1.0\lib\win8\_._ +system.io.compression\4.1.0\lib\wpa81\_._ +system.io.compression\4.1.0\lib\xamarinios10\_._ +system.io.compression\4.1.0\lib\xamarinmac20\_._ +system.io.compression\4.1.0\lib\xamarintvos10\_._ +system.io.compression\4.1.0\lib\xamarinwatchos10\_._ +system.io.compression\4.1.0\ref\MonoAndroid10\_._ +system.io.compression\4.1.0\ref\MonoTouch10\_._ +system.io.compression\4.1.0\ref\net45\_._ +system.io.compression\4.1.0\ref\net46\System.IO.Compression.dll +system.io.compression\4.1.0\ref\netcore50\System.IO.Compression.dll +system.io.compression\4.1.0\ref\netstandard1.1\System.IO.Compression.dll +system.io.compression\4.1.0\ref\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.1.0\ref\portable-net45+win8+wpa81\_._ +system.io.compression\4.1.0\ref\win8\_._ +system.io.compression\4.1.0\ref\wpa81\_._ +system.io.compression\4.1.0\ref\xamarinios10\_._ +system.io.compression\4.1.0\ref\xamarinmac20\_._ +system.io.compression\4.1.0\ref\xamarintvos10\_._ +system.io.compression\4.1.0\ref\xamarinwatchos10\_._ +system.io.compression\4.1.0\runtimes\unix\lib\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.1.0\runtimes\win\lib\net46\System.IO.Compression.dll +system.io.compression\4.1.0\runtimes\win\lib\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.1.0\system.io.compression.4.1.0.nupkg +system.io.compression\4.1.0\system.io.compression.4.1.0.nupkg.sha512 +system.io.compression\4.1.0\system.io.compression.nuspec +system.io.compression\4.1.0\ThirdPartyNotices.txt +system.io.compression\4.3.0\dotnet_library_license.txt +system.io.compression\4.3.0\lib\MonoAndroid10\_._ +system.io.compression\4.3.0\lib\MonoTouch10\_._ +system.io.compression\4.3.0\lib\net45\_._ +system.io.compression\4.3.0\lib\net46\System.IO.Compression.dll +system.io.compression\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.io.compression\4.3.0\lib\win8\_._ +system.io.compression\4.3.0\lib\wpa81\_._ +system.io.compression\4.3.0\lib\xamarinios10\_._ +system.io.compression\4.3.0\lib\xamarinmac20\_._ +system.io.compression\4.3.0\lib\xamarintvos10\_._ +system.io.compression\4.3.0\lib\xamarinwatchos10\_._ +system.io.compression\4.3.0\ref\MonoAndroid10\_._ +system.io.compression\4.3.0\ref\MonoTouch10\_._ +system.io.compression\4.3.0\ref\net45\_._ +system.io.compression\4.3.0\ref\net46\System.IO.Compression.dll +system.io.compression\4.3.0\ref\netcore50\System.IO.Compression.dll +system.io.compression\4.3.0\ref\netstandard1.1\System.IO.Compression.dll +system.io.compression\4.3.0\ref\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.io.compression\4.3.0\ref\win8\_._ +system.io.compression\4.3.0\ref\wpa81\_._ +system.io.compression\4.3.0\ref\xamarinios10\_._ +system.io.compression\4.3.0\ref\xamarinmac20\_._ +system.io.compression\4.3.0\ref\xamarintvos10\_._ +system.io.compression\4.3.0\ref\xamarinwatchos10\_._ +system.io.compression\4.3.0\runtimes\unix\lib\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.3.0\runtimes\win\lib\net46\System.IO.Compression.dll +system.io.compression\4.3.0\runtimes\win\lib\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.3.0\system.io.compression.4.3.0.nupkg +system.io.compression\4.3.0\system.io.compression.4.3.0.nupkg.sha512 +system.io.compression\4.3.0\system.io.compression.nuspec +system.io.compression\4.3.0\ThirdPartyNotices.txt +system.io.filesystem.primitives\4.0.1\dotnet_library_license.txt +system.io.filesystem.primitives\4.0.1\lib\MonoAndroid10\_._ +system.io.filesystem.primitives\4.0.1\lib\MonoTouch10\_._ +system.io.filesystem.primitives\4.0.1\lib\net46\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.0.1\lib\netstandard1.3\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.0.1\lib\xamarinios10\_._ +system.io.filesystem.primitives\4.0.1\lib\xamarinmac20\_._ +system.io.filesystem.primitives\4.0.1\lib\xamarintvos10\_._ +system.io.filesystem.primitives\4.0.1\lib\xamarinwatchos10\_._ +system.io.filesystem.primitives\4.0.1\ref\MonoAndroid10\_._ +system.io.filesystem.primitives\4.0.1\ref\MonoTouch10\_._ +system.io.filesystem.primitives\4.0.1\ref\net46\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.0.1\ref\netstandard1.3\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.0.1\ref\xamarinios10\_._ +system.io.filesystem.primitives\4.0.1\ref\xamarinmac20\_._ +system.io.filesystem.primitives\4.0.1\ref\xamarintvos10\_._ +system.io.filesystem.primitives\4.0.1\ref\xamarinwatchos10\_._ +system.io.filesystem.primitives\4.0.1\system.io.filesystem.primitives.4.0.1.nupkg +system.io.filesystem.primitives\4.0.1\system.io.filesystem.primitives.4.0.1.nupkg.sha512 +system.io.filesystem.primitives\4.0.1\system.io.filesystem.primitives.nuspec +system.io.filesystem.primitives\4.0.1\ThirdPartyNotices.txt +system.io.filesystem.primitives\4.3.0\dotnet_library_license.txt +system.io.filesystem.primitives\4.3.0\lib\MonoAndroid10\_._ +system.io.filesystem.primitives\4.3.0\lib\MonoTouch10\_._ +system.io.filesystem.primitives\4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.3.0\lib\netstandard1.3\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.3.0\lib\xamarinios10\_._ +system.io.filesystem.primitives\4.3.0\lib\xamarinmac20\_._ +system.io.filesystem.primitives\4.3.0\lib\xamarintvos10\_._ +system.io.filesystem.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.io.filesystem.primitives\4.3.0\ref\MonoAndroid10\_._ +system.io.filesystem.primitives\4.3.0\ref\MonoTouch10\_._ +system.io.filesystem.primitives\4.3.0\ref\net46\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.3.0\ref\netstandard1.3\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.3.0\ref\xamarinios10\_._ +system.io.filesystem.primitives\4.3.0\ref\xamarinmac20\_._ +system.io.filesystem.primitives\4.3.0\ref\xamarintvos10\_._ +system.io.filesystem.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.io.filesystem.primitives\4.3.0\system.io.filesystem.primitives.4.3.0.nupkg +system.io.filesystem.primitives\4.3.0\system.io.filesystem.primitives.4.3.0.nupkg.sha512 +system.io.filesystem.primitives\4.3.0\system.io.filesystem.primitives.nuspec +system.io.filesystem.primitives\4.3.0\ThirdPartyNotices.txt +system.io.filesystem\4.0.1\dotnet_library_license.txt +system.io.filesystem\4.0.1\lib\MonoAndroid10\_._ +system.io.filesystem\4.0.1\lib\MonoTouch10\_._ +system.io.filesystem\4.0.1\lib\net46\System.IO.FileSystem.dll +system.io.filesystem\4.0.1\lib\xamarinios10\_._ +system.io.filesystem\4.0.1\lib\xamarinmac20\_._ +system.io.filesystem\4.0.1\lib\xamarintvos10\_._ +system.io.filesystem\4.0.1\lib\xamarinwatchos10\_._ +system.io.filesystem\4.0.1\ref\MonoAndroid10\_._ +system.io.filesystem\4.0.1\ref\MonoTouch10\_._ +system.io.filesystem\4.0.1\ref\net46\System.IO.FileSystem.dll +system.io.filesystem\4.0.1\ref\netstandard1.3\System.IO.FileSystem.dll +system.io.filesystem\4.0.1\ref\xamarinios10\_._ +system.io.filesystem\4.0.1\ref\xamarinmac20\_._ +system.io.filesystem\4.0.1\ref\xamarintvos10\_._ +system.io.filesystem\4.0.1\ref\xamarinwatchos10\_._ +system.io.filesystem\4.0.1\system.io.filesystem.4.0.1.nupkg +system.io.filesystem\4.0.1\system.io.filesystem.4.0.1.nupkg.sha512 +system.io.filesystem\4.0.1\system.io.filesystem.nuspec +system.io.filesystem\4.0.1\ThirdPartyNotices.txt +system.io.filesystem\4.3.0\dotnet_library_license.txt +system.io.filesystem\4.3.0\lib\MonoAndroid10\_._ +system.io.filesystem\4.3.0\lib\MonoTouch10\_._ +system.io.filesystem\4.3.0\lib\net46\System.IO.FileSystem.dll +system.io.filesystem\4.3.0\lib\xamarinios10\_._ +system.io.filesystem\4.3.0\lib\xamarinmac20\_._ +system.io.filesystem\4.3.0\lib\xamarintvos10\_._ +system.io.filesystem\4.3.0\lib\xamarinwatchos10\_._ +system.io.filesystem\4.3.0\ref\MonoAndroid10\_._ +system.io.filesystem\4.3.0\ref\MonoTouch10\_._ +system.io.filesystem\4.3.0\ref\net46\System.IO.FileSystem.dll +system.io.filesystem\4.3.0\ref\netstandard1.3\System.IO.FileSystem.dll +system.io.filesystem\4.3.0\ref\xamarinios10\_._ +system.io.filesystem\4.3.0\ref\xamarinmac20\_._ +system.io.filesystem\4.3.0\ref\xamarintvos10\_._ +system.io.filesystem\4.3.0\ref\xamarinwatchos10\_._ +system.io.filesystem\4.3.0\system.io.filesystem.4.3.0.nupkg +system.io.filesystem\4.3.0\system.io.filesystem.4.3.0.nupkg.sha512 +system.io.filesystem\4.3.0\system.io.filesystem.nuspec +system.io.filesystem\4.3.0\ThirdPartyNotices.txt +system.io.pipelines\4.5.0\.signature.p7s +system.io.pipelines\4.5.0\lib\netcoreapp2.1\System.IO.Pipelines.dll +system.io.pipelines\4.5.0\lib\netstandard1.3\System.IO.Pipelines.dll +system.io.pipelines\4.5.0\lib\netstandard2.0\System.IO.Pipelines.dll +system.io.pipelines\4.5.0\LICENSE.TXT +system.io.pipelines\4.5.0\ref\netstandard1.3\System.IO.Pipelines.dll +system.io.pipelines\4.5.0\system.io.pipelines.4.5.0.nupkg +system.io.pipelines\4.5.0\system.io.pipelines.4.5.0.nupkg.sha512 +system.io.pipelines\4.5.0\system.io.pipelines.nuspec +system.io.pipelines\4.5.0\THIRD-PARTY-NOTICES.TXT +system.io.pipelines\4.5.0\useSharedDesignerContext.txt +system.io.pipelines\4.5.0\version.txt +system.io\4.1.0\dotnet_library_license.txt +system.io\4.1.0\lib\MonoAndroid10\_._ +system.io\4.1.0\lib\MonoTouch10\_._ +system.io\4.1.0\lib\net45\_._ +system.io\4.1.0\lib\net462\System.IO.dll +system.io\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.io\4.1.0\lib\win8\_._ +system.io\4.1.0\lib\wp80\_._ +system.io\4.1.0\lib\wpa81\_._ +system.io\4.1.0\lib\xamarinios10\_._ +system.io\4.1.0\lib\xamarinmac20\_._ +system.io\4.1.0\lib\xamarintvos10\_._ +system.io\4.1.0\lib\xamarinwatchos10\_._ +system.io\4.1.0\ref\MonoAndroid10\_._ +system.io\4.1.0\ref\MonoTouch10\_._ +system.io\4.1.0\ref\net45\_._ +system.io\4.1.0\ref\net462\System.IO.dll +system.io\4.1.0\ref\netcore50\System.IO.dll +system.io\4.1.0\ref\netstandard1.0\System.IO.dll +system.io\4.1.0\ref\netstandard1.3\System.IO.dll +system.io\4.1.0\ref\netstandard1.5\System.IO.dll +system.io\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.io\4.1.0\ref\win8\_._ +system.io\4.1.0\ref\wp80\_._ +system.io\4.1.0\ref\wpa81\_._ +system.io\4.1.0\ref\xamarinios10\_._ +system.io\4.1.0\ref\xamarinmac20\_._ +system.io\4.1.0\ref\xamarintvos10\_._ +system.io\4.1.0\ref\xamarinwatchos10\_._ +system.io\4.1.0\system.io.4.1.0.nupkg +system.io\4.1.0\system.io.4.1.0.nupkg.sha512 +system.io\4.1.0\system.io.nuspec +system.io\4.1.0\ThirdPartyNotices.txt +system.io\4.3.0\dotnet_library_license.txt +system.io\4.3.0\lib\MonoAndroid10\_._ +system.io\4.3.0\lib\MonoTouch10\_._ +system.io\4.3.0\lib\net45\_._ +system.io\4.3.0\lib\net462\System.IO.dll +system.io\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.io\4.3.0\lib\win8\_._ +system.io\4.3.0\lib\wp80\_._ +system.io\4.3.0\lib\wpa81\_._ +system.io\4.3.0\lib\xamarinios10\_._ +system.io\4.3.0\lib\xamarinmac20\_._ +system.io\4.3.0\lib\xamarintvos10\_._ +system.io\4.3.0\lib\xamarinwatchos10\_._ +system.io\4.3.0\ref\MonoAndroid10\_._ +system.io\4.3.0\ref\MonoTouch10\_._ +system.io\4.3.0\ref\net45\_._ +system.io\4.3.0\ref\net462\System.IO.dll +system.io\4.3.0\ref\netcore50\System.IO.dll +system.io\4.3.0\ref\netstandard1.0\System.IO.dll +system.io\4.3.0\ref\netstandard1.3\System.IO.dll +system.io\4.3.0\ref\netstandard1.5\System.IO.dll +system.io\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.io\4.3.0\ref\win8\_._ +system.io\4.3.0\ref\wp80\_._ +system.io\4.3.0\ref\wpa81\_._ +system.io\4.3.0\ref\xamarinios10\_._ +system.io\4.3.0\ref\xamarinmac20\_._ +system.io\4.3.0\ref\xamarintvos10\_._ +system.io\4.3.0\ref\xamarinwatchos10\_._ +system.io\4.3.0\system.io.4.3.0.nupkg +system.io\4.3.0\system.io.4.3.0.nupkg.sha512 +system.io\4.3.0\system.io.nuspec +system.io\4.3.0\ThirdPartyNotices.txt +system.linq.expressions\4.1.0\dotnet_library_license.txt +system.linq.expressions\4.1.0\lib\MonoAndroid10\_._ +system.linq.expressions\4.1.0\lib\MonoTouch10\_._ +system.linq.expressions\4.1.0\lib\net45\_._ +system.linq.expressions\4.1.0\lib\net463\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\lib\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\lib\netstandard1.6\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq.expressions\4.1.0\lib\win8\_._ +system.linq.expressions\4.1.0\lib\wp80\_._ +system.linq.expressions\4.1.0\lib\wpa81\_._ +system.linq.expressions\4.1.0\lib\xamarinios10\_._ +system.linq.expressions\4.1.0\lib\xamarinmac20\_._ +system.linq.expressions\4.1.0\lib\xamarintvos10\_._ +system.linq.expressions\4.1.0\lib\xamarinwatchos10\_._ +system.linq.expressions\4.1.0\ref\MonoAndroid10\_._ +system.linq.expressions\4.1.0\ref\MonoTouch10\_._ +system.linq.expressions\4.1.0\ref\net45\_._ +system.linq.expressions\4.1.0\ref\net463\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\netstandard1.0\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\netstandard1.3\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\netstandard1.6\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq.expressions\4.1.0\ref\win8\_._ +system.linq.expressions\4.1.0\ref\wp80\_._ +system.linq.expressions\4.1.0\ref\wpa81\_._ +system.linq.expressions\4.1.0\ref\xamarinios10\_._ +system.linq.expressions\4.1.0\ref\xamarinmac20\_._ +system.linq.expressions\4.1.0\ref\xamarintvos10\_._ +system.linq.expressions\4.1.0\ref\xamarinwatchos10\_._ +system.linq.expressions\4.1.0\runtimes\aot\lib\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\system.linq.expressions.4.1.0.nupkg +system.linq.expressions\4.1.0\system.linq.expressions.4.1.0.nupkg.sha512 +system.linq.expressions\4.1.0\system.linq.expressions.nuspec +system.linq.expressions\4.1.0\ThirdPartyNotices.txt +system.linq.expressions\4.3.0\dotnet_library_license.txt +system.linq.expressions\4.3.0\lib\MonoAndroid10\_._ +system.linq.expressions\4.3.0\lib\MonoTouch10\_._ +system.linq.expressions\4.3.0\lib\net45\_._ +system.linq.expressions\4.3.0\lib\net463\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\lib\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\lib\netstandard1.6\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq.expressions\4.3.0\lib\win8\_._ +system.linq.expressions\4.3.0\lib\wp80\_._ +system.linq.expressions\4.3.0\lib\wpa81\_._ +system.linq.expressions\4.3.0\lib\xamarinios10\_._ +system.linq.expressions\4.3.0\lib\xamarinmac20\_._ +system.linq.expressions\4.3.0\lib\xamarintvos10\_._ +system.linq.expressions\4.3.0\lib\xamarinwatchos10\_._ +system.linq.expressions\4.3.0\ref\MonoAndroid10\_._ +system.linq.expressions\4.3.0\ref\MonoTouch10\_._ +system.linq.expressions\4.3.0\ref\net45\_._ +system.linq.expressions\4.3.0\ref\net463\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\netstandard1.0\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\netstandard1.3\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\netstandard1.6\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq.expressions\4.3.0\ref\win8\_._ +system.linq.expressions\4.3.0\ref\wp80\_._ +system.linq.expressions\4.3.0\ref\wpa81\_._ +system.linq.expressions\4.3.0\ref\xamarinios10\_._ +system.linq.expressions\4.3.0\ref\xamarinmac20\_._ +system.linq.expressions\4.3.0\ref\xamarintvos10\_._ +system.linq.expressions\4.3.0\ref\xamarinwatchos10\_._ +system.linq.expressions\4.3.0\runtimes\aot\lib\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\system.linq.expressions.4.3.0.nupkg +system.linq.expressions\4.3.0\system.linq.expressions.4.3.0.nupkg.sha512 +system.linq.expressions\4.3.0\system.linq.expressions.nuspec +system.linq.expressions\4.3.0\ThirdPartyNotices.txt +system.linq.parallel\4.3.0\dotnet_library_license.txt +system.linq.parallel\4.3.0\lib\MonoAndroid10\_._ +system.linq.parallel\4.3.0\lib\MonoTouch10\_._ +system.linq.parallel\4.3.0\lib\net45\_._ +system.linq.parallel\4.3.0\lib\netcore50\System.Linq.Parallel.dll +system.linq.parallel\4.3.0\lib\netstandard1.3\System.Linq.Parallel.dll +system.linq.parallel\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.linq.parallel\4.3.0\lib\win8\_._ +system.linq.parallel\4.3.0\lib\wpa81\_._ +system.linq.parallel\4.3.0\lib\xamarinios10\_._ +system.linq.parallel\4.3.0\lib\xamarinmac20\_._ +system.linq.parallel\4.3.0\lib\xamarintvos10\_._ +system.linq.parallel\4.3.0\lib\xamarinwatchos10\_._ +system.linq.parallel\4.3.0\ref\MonoAndroid10\_._ +system.linq.parallel\4.3.0\ref\MonoTouch10\_._ +system.linq.parallel\4.3.0\ref\net45\_._ +system.linq.parallel\4.3.0\ref\netcore50\System.Linq.Parallel.dll +system.linq.parallel\4.3.0\ref\netstandard1.1\System.Linq.Parallel.dll +system.linq.parallel\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.linq.parallel\4.3.0\ref\win8\_._ +system.linq.parallel\4.3.0\ref\wpa81\_._ +system.linq.parallel\4.3.0\ref\xamarinios10\_._ +system.linq.parallel\4.3.0\ref\xamarinmac20\_._ +system.linq.parallel\4.3.0\ref\xamarintvos10\_._ +system.linq.parallel\4.3.0\ref\xamarinwatchos10\_._ +system.linq.parallel\4.3.0\system.linq.parallel.4.3.0.nupkg +system.linq.parallel\4.3.0\system.linq.parallel.4.3.0.nupkg.sha512 +system.linq.parallel\4.3.0\system.linq.parallel.nuspec +system.linq.parallel\4.3.0\ThirdPartyNotices.txt +system.linq.queryable\4.0.1\dotnet_library_license.txt +system.linq.queryable\4.0.1\lib\monoandroid10\_._ +system.linq.queryable\4.0.1\lib\monotouch10\_._ +system.linq.queryable\4.0.1\lib\net45\_._ +system.linq.queryable\4.0.1\lib\netcore50\System.Linq.Queryable.dll +system.linq.queryable\4.0.1\lib\netstandard1.3\System.Linq.Queryable.dll +system.linq.queryable\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq.queryable\4.0.1\lib\win8\_._ +system.linq.queryable\4.0.1\lib\wp80\_._ +system.linq.queryable\4.0.1\lib\wpa81\_._ +system.linq.queryable\4.0.1\lib\xamarinios10\_._ +system.linq.queryable\4.0.1\lib\xamarinmac20\_._ +system.linq.queryable\4.0.1\lib\xamarintvos10\_._ +system.linq.queryable\4.0.1\lib\xamarinwatchos10\_._ +system.linq.queryable\4.0.1\ref\monoandroid10\_._ +system.linq.queryable\4.0.1\ref\monotouch10\_._ +system.linq.queryable\4.0.1\ref\net45\_._ +system.linq.queryable\4.0.1\ref\netcore50\System.Linq.Queryable.dll +system.linq.queryable\4.0.1\ref\netstandard1.0\System.Linq.Queryable.dll +system.linq.queryable\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq.queryable\4.0.1\ref\win8\_._ +system.linq.queryable\4.0.1\ref\wp80\_._ +system.linq.queryable\4.0.1\ref\wpa81\_._ +system.linq.queryable\4.0.1\ref\xamarinios10\_._ +system.linq.queryable\4.0.1\ref\xamarinmac20\_._ +system.linq.queryable\4.0.1\ref\xamarintvos10\_._ +system.linq.queryable\4.0.1\ref\xamarinwatchos10\_._ +system.linq.queryable\4.0.1\system.linq.queryable.4.0.1.nupkg +system.linq.queryable\4.0.1\system.linq.queryable.4.0.1.nupkg.sha512 +system.linq.queryable\4.0.1\system.linq.queryable.nuspec +system.linq.queryable\4.0.1\ThirdPartyNotices.txt +system.linq\4.1.0\dotnet_library_license.txt +system.linq\4.1.0\lib\MonoAndroid10\_._ +system.linq\4.1.0\lib\MonoTouch10\_._ +system.linq\4.1.0\lib\net45\_._ +system.linq\4.1.0\lib\net463\System.Linq.dll +system.linq\4.1.0\lib\netcore50\System.Linq.dll +system.linq\4.1.0\lib\netstandard1.6\System.Linq.dll +system.linq\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq\4.1.0\lib\win8\_._ +system.linq\4.1.0\lib\wp80\_._ +system.linq\4.1.0\lib\wpa81\_._ +system.linq\4.1.0\lib\xamarinios10\_._ +system.linq\4.1.0\lib\xamarinmac20\_._ +system.linq\4.1.0\lib\xamarintvos10\_._ +system.linq\4.1.0\lib\xamarinwatchos10\_._ +system.linq\4.1.0\ref\MonoAndroid10\_._ +system.linq\4.1.0\ref\MonoTouch10\_._ +system.linq\4.1.0\ref\net45\_._ +system.linq\4.1.0\ref\net463\System.Linq.dll +system.linq\4.1.0\ref\netcore50\System.Linq.dll +system.linq\4.1.0\ref\netstandard1.0\System.Linq.dll +system.linq\4.1.0\ref\netstandard1.6\System.Linq.dll +system.linq\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq\4.1.0\ref\win8\_._ +system.linq\4.1.0\ref\wp80\_._ +system.linq\4.1.0\ref\wpa81\_._ +system.linq\4.1.0\ref\xamarinios10\_._ +system.linq\4.1.0\ref\xamarinmac20\_._ +system.linq\4.1.0\ref\xamarintvos10\_._ +system.linq\4.1.0\ref\xamarinwatchos10\_._ +system.linq\4.1.0\system.linq.4.1.0.nupkg +system.linq\4.1.0\system.linq.4.1.0.nupkg.sha512 +system.linq\4.1.0\system.linq.nuspec +system.linq\4.1.0\ThirdPartyNotices.txt +system.linq\4.3.0\dotnet_library_license.txt +system.linq\4.3.0\lib\MonoAndroid10\_._ +system.linq\4.3.0\lib\MonoTouch10\_._ +system.linq\4.3.0\lib\net45\_._ +system.linq\4.3.0\lib\net463\System.Linq.dll +system.linq\4.3.0\lib\netcore50\System.Linq.dll +system.linq\4.3.0\lib\netstandard1.6\System.Linq.dll +system.linq\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq\4.3.0\lib\win8\_._ +system.linq\4.3.0\lib\wp80\_._ +system.linq\4.3.0\lib\wpa81\_._ +system.linq\4.3.0\lib\xamarinios10\_._ +system.linq\4.3.0\lib\xamarinmac20\_._ +system.linq\4.3.0\lib\xamarintvos10\_._ +system.linq\4.3.0\lib\xamarinwatchos10\_._ +system.linq\4.3.0\ref\MonoAndroid10\_._ +system.linq\4.3.0\ref\MonoTouch10\_._ +system.linq\4.3.0\ref\net45\_._ +system.linq\4.3.0\ref\net463\System.Linq.dll +system.linq\4.3.0\ref\netcore50\System.Linq.dll +system.linq\4.3.0\ref\netstandard1.0\System.Linq.dll +system.linq\4.3.0\ref\netstandard1.6\System.Linq.dll +system.linq\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq\4.3.0\ref\win8\_._ +system.linq\4.3.0\ref\wp80\_._ +system.linq\4.3.0\ref\wpa81\_._ +system.linq\4.3.0\ref\xamarinios10\_._ +system.linq\4.3.0\ref\xamarinmac20\_._ +system.linq\4.3.0\ref\xamarintvos10\_._ +system.linq\4.3.0\ref\xamarinwatchos10\_._ +system.linq\4.3.0\system.linq.4.3.0.nupkg +system.linq\4.3.0\system.linq.4.3.0.nupkg.sha512 +system.linq\4.3.0\system.linq.nuspec +system.linq\4.3.0\ThirdPartyNotices.txt +system.memory\4.5.1\.signature.p7s +system.memory\4.5.1\lib\netcoreapp2.1\_._ +system.memory\4.5.1\lib\netstandard1.1\System.Memory.dll +system.memory\4.5.1\lib\netstandard2.0\System.Memory.dll +system.memory\4.5.1\LICENSE.TXT +system.memory\4.5.1\ref\netcoreapp2.1\_._ +system.memory\4.5.1\ref\netstandard1.1\System.Memory.dll +system.memory\4.5.1\ref\netstandard2.0\System.Memory.dll +system.memory\4.5.1\system.memory.4.5.1.nupkg +system.memory\4.5.1\system.memory.4.5.1.nupkg.sha512 +system.memory\4.5.1\system.memory.nuspec +system.memory\4.5.1\THIRD-PARTY-NOTICES.TXT +system.memory\4.5.1\useSharedDesignerContext.txt +system.memory\4.5.1\version.txt +system.net.http\4.1.0\dotnet_library_license.txt +system.net.http\4.1.0\lib\monoandroid10\_._ +system.net.http\4.1.0\lib\monotouch10\_._ +system.net.http\4.1.0\lib\net45\_._ +system.net.http\4.1.0\lib\net46\System.Net.Http.dll +system.net.http\4.1.0\lib\portable-net45+win8+wpa81\_._ +system.net.http\4.1.0\lib\win8\_._ +system.net.http\4.1.0\lib\wpa81\_._ +system.net.http\4.1.0\lib\xamarinios10\_._ +system.net.http\4.1.0\lib\Xamarinmac20\_._ +system.net.http\4.1.0\lib\xamarintvos10\_._ +system.net.http\4.1.0\lib\xamarinwatchos10\_._ +system.net.http\4.1.0\ref\monoandroid10\_._ +system.net.http\4.1.0\ref\monotouch10\_._ +system.net.http\4.1.0\ref\net45\_._ +system.net.http\4.1.0\ref\net46\System.Net.Http.dll +system.net.http\4.1.0\ref\netcore50\System.Net.Http.dll +system.net.http\4.1.0\ref\netstandard1.1\System.Net.Http.dll +system.net.http\4.1.0\ref\netstandard1.3\System.Net.Http.dll +system.net.http\4.1.0\ref\portable-net45+win8+wpa81\_._ +system.net.http\4.1.0\ref\win8\_._ +system.net.http\4.1.0\ref\wpa81\_._ +system.net.http\4.1.0\ref\xamarinios10\_._ +system.net.http\4.1.0\ref\Xamarinmac20\_._ +system.net.http\4.1.0\ref\xamarintvos10\_._ +system.net.http\4.1.0\ref\xamarinwatchos10\_._ +system.net.http\4.1.0\runtimes\unix\lib\netstandard1.6\System.Net.Http.dll +system.net.http\4.1.0\runtimes\win\lib\net46\System.Net.Http.dll +system.net.http\4.1.0\runtimes\win\lib\netcore50\System.Net.Http.dll +system.net.http\4.1.0\runtimes\win\lib\netstandard1.3\System.Net.Http.dll +system.net.http\4.1.0\system.net.http.4.1.0.nupkg +system.net.http\4.1.0\system.net.http.4.1.0.nupkg.sha512 +system.net.http\4.1.0\system.net.http.nuspec +system.net.http\4.1.0\ThirdPartyNotices.txt +system.net.http\4.3.0\dotnet_library_license.txt +system.net.http\4.3.0\lib\monoandroid10\_._ +system.net.http\4.3.0\lib\monotouch10\_._ +system.net.http\4.3.0\lib\net45\_._ +system.net.http\4.3.0\lib\net46\System.Net.Http.dll +system.net.http\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.net.http\4.3.0\lib\win8\_._ +system.net.http\4.3.0\lib\wpa81\_._ +system.net.http\4.3.0\lib\xamarinios10\_._ +system.net.http\4.3.0\lib\Xamarinmac20\_._ +system.net.http\4.3.0\lib\xamarintvos10\_._ +system.net.http\4.3.0\lib\xamarinwatchos10\_._ +system.net.http\4.3.0\ref\monoandroid10\_._ +system.net.http\4.3.0\ref\monotouch10\_._ +system.net.http\4.3.0\ref\net45\_._ +system.net.http\4.3.0\ref\net46\System.Net.Http.dll +system.net.http\4.3.0\ref\netcore50\System.Net.Http.dll +system.net.http\4.3.0\ref\netstandard1.1\System.Net.Http.dll +system.net.http\4.3.0\ref\netstandard1.3\System.Net.Http.dll +system.net.http\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.net.http\4.3.0\ref\win8\_._ +system.net.http\4.3.0\ref\wpa81\_._ +system.net.http\4.3.0\ref\xamarinios10\_._ +system.net.http\4.3.0\ref\Xamarinmac20\_._ +system.net.http\4.3.0\ref\xamarintvos10\_._ +system.net.http\4.3.0\ref\xamarinwatchos10\_._ +system.net.http\4.3.0\runtimes\unix\lib\netstandard1.6\System.Net.Http.dll +system.net.http\4.3.0\runtimes\win\lib\net46\System.Net.Http.dll +system.net.http\4.3.0\runtimes\win\lib\netcore50\System.Net.Http.dll +system.net.http\4.3.0\runtimes\win\lib\netstandard1.3\System.Net.Http.dll +system.net.http\4.3.0\system.net.http.4.3.0.nupkg +system.net.http\4.3.0\system.net.http.4.3.0.nupkg.sha512 +system.net.http\4.3.0\system.net.http.nuspec +system.net.http\4.3.0\ThirdPartyNotices.txt +system.net.nameresolution\4.3.0\dotnet_library_license.txt +system.net.nameresolution\4.3.0\lib\MonoAndroid10\_._ +system.net.nameresolution\4.3.0\lib\MonoTouch10\_._ +system.net.nameresolution\4.3.0\lib\net46\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\lib\xamarinios10\_._ +system.net.nameresolution\4.3.0\lib\xamarinmac20\_._ +system.net.nameresolution\4.3.0\lib\xamarintvos10\_._ +system.net.nameresolution\4.3.0\lib\xamarinwatchos10\_._ +system.net.nameresolution\4.3.0\ref\MonoAndroid10\_._ +system.net.nameresolution\4.3.0\ref\MonoTouch10\_._ +system.net.nameresolution\4.3.0\ref\net46\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\ref\netstandard1.3\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\ref\xamarinios10\_._ +system.net.nameresolution\4.3.0\ref\xamarinmac20\_._ +system.net.nameresolution\4.3.0\ref\xamarintvos10\_._ +system.net.nameresolution\4.3.0\ref\xamarinwatchos10\_._ +system.net.nameresolution\4.3.0\runtimes\unix\lib\netstandard1.3\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\runtimes\win\lib\net46\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\runtimes\win\lib\netcore50\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\runtimes\win\lib\netstandard1.3\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\system.net.nameresolution.4.3.0.nupkg +system.net.nameresolution\4.3.0\system.net.nameresolution.4.3.0.nupkg.sha512 +system.net.nameresolution\4.3.0\system.net.nameresolution.nuspec +system.net.nameresolution\4.3.0\ThirdPartyNotices.txt +system.net.primitives\4.0.11\dotnet_library_license.txt +system.net.primitives\4.0.11\lib\MonoAndroid10\_._ +system.net.primitives\4.0.11\lib\MonoTouch10\_._ +system.net.primitives\4.0.11\lib\net45\_._ +system.net.primitives\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.net.primitives\4.0.11\lib\win8\_._ +system.net.primitives\4.0.11\lib\wp80\_._ +system.net.primitives\4.0.11\lib\wpa81\_._ +system.net.primitives\4.0.11\lib\xamarinios10\_._ +system.net.primitives\4.0.11\lib\xamarinmac20\_._ +system.net.primitives\4.0.11\lib\xamarintvos10\_._ +system.net.primitives\4.0.11\lib\xamarinwatchos10\_._ +system.net.primitives\4.0.11\ref\MonoAndroid10\_._ +system.net.primitives\4.0.11\ref\MonoTouch10\_._ +system.net.primitives\4.0.11\ref\net45\_._ +system.net.primitives\4.0.11\ref\netcore50\System.Net.Primitives.dll +system.net.primitives\4.0.11\ref\netstandard1.0\System.Net.Primitives.dll +system.net.primitives\4.0.11\ref\netstandard1.1\System.Net.Primitives.dll +system.net.primitives\4.0.11\ref\netstandard1.3\System.Net.Primitives.dll +system.net.primitives\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.net.primitives\4.0.11\ref\win8\_._ +system.net.primitives\4.0.11\ref\wp80\_._ +system.net.primitives\4.0.11\ref\wpa81\_._ +system.net.primitives\4.0.11\ref\xamarinios10\_._ +system.net.primitives\4.0.11\ref\xamarinmac20\_._ +system.net.primitives\4.0.11\ref\xamarintvos10\_._ +system.net.primitives\4.0.11\ref\xamarinwatchos10\_._ +system.net.primitives\4.0.11\system.net.primitives.4.0.11.nupkg +system.net.primitives\4.0.11\system.net.primitives.4.0.11.nupkg.sha512 +system.net.primitives\4.0.11\system.net.primitives.nuspec +system.net.primitives\4.0.11\ThirdPartyNotices.txt +system.net.primitives\4.3.0\dotnet_library_license.txt +system.net.primitives\4.3.0\lib\MonoAndroid10\_._ +system.net.primitives\4.3.0\lib\MonoTouch10\_._ +system.net.primitives\4.3.0\lib\net45\_._ +system.net.primitives\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.net.primitives\4.3.0\lib\win8\_._ +system.net.primitives\4.3.0\lib\wp80\_._ +system.net.primitives\4.3.0\lib\wpa81\_._ +system.net.primitives\4.3.0\lib\xamarinios10\_._ +system.net.primitives\4.3.0\lib\xamarinmac20\_._ +system.net.primitives\4.3.0\lib\xamarintvos10\_._ +system.net.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.net.primitives\4.3.0\ref\MonoAndroid10\_._ +system.net.primitives\4.3.0\ref\MonoTouch10\_._ +system.net.primitives\4.3.0\ref\net45\_._ +system.net.primitives\4.3.0\ref\netcore50\System.Net.Primitives.dll +system.net.primitives\4.3.0\ref\netstandard1.0\System.Net.Primitives.dll +system.net.primitives\4.3.0\ref\netstandard1.1\System.Net.Primitives.dll +system.net.primitives\4.3.0\ref\netstandard1.3\System.Net.Primitives.dll +system.net.primitives\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.net.primitives\4.3.0\ref\win8\_._ +system.net.primitives\4.3.0\ref\wp80\_._ +system.net.primitives\4.3.0\ref\wpa81\_._ +system.net.primitives\4.3.0\ref\xamarinios10\_._ +system.net.primitives\4.3.0\ref\xamarinmac20\_._ +system.net.primitives\4.3.0\ref\xamarintvos10\_._ +system.net.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.net.primitives\4.3.0\system.net.primitives.4.3.0.nupkg +system.net.primitives\4.3.0\system.net.primitives.4.3.0.nupkg.sha512 +system.net.primitives\4.3.0\system.net.primitives.nuspec +system.net.primitives\4.3.0\ThirdPartyNotices.txt +system.net.security\4.3.0\dotnet_library_license.txt +system.net.security\4.3.0\lib\MonoAndroid10\_._ +system.net.security\4.3.0\lib\MonoTouch10\_._ +system.net.security\4.3.0\lib\net46\System.Net.Security.dll +system.net.security\4.3.0\lib\xamarinios10\_._ +system.net.security\4.3.0\lib\xamarinmac20\_._ +system.net.security\4.3.0\lib\xamarintvos10\_._ +system.net.security\4.3.0\lib\xamarinwatchos10\_._ +system.net.security\4.3.0\ref\MonoAndroid10\_._ +system.net.security\4.3.0\ref\MonoTouch10\_._ +system.net.security\4.3.0\ref\net46\System.Net.Security.dll +system.net.security\4.3.0\ref\netstandard1.3\System.Net.Security.dll +system.net.security\4.3.0\ref\xamarinios10\_._ +system.net.security\4.3.0\ref\xamarinmac20\_._ +system.net.security\4.3.0\ref\xamarintvos10\_._ +system.net.security\4.3.0\ref\xamarinwatchos10\_._ +system.net.security\4.3.0\runtimes\unix\lib\netstandard1.6\System.Net.Security.dll +system.net.security\4.3.0\runtimes\win\lib\net46\System.Net.Security.dll +system.net.security\4.3.0\runtimes\win\lib\netstandard1.3\System.Net.Security.dll +system.net.security\4.3.0\runtimes\win7\lib\netcore50\_._ +system.net.security\4.3.0\system.net.security.4.3.0.nupkg +system.net.security\4.3.0\system.net.security.4.3.0.nupkg.sha512 +system.net.security\4.3.0\system.net.security.nuspec +system.net.security\4.3.0\ThirdPartyNotices.txt +system.net.sockets\4.1.0\dotnet_library_license.txt +system.net.sockets\4.1.0\lib\MonoAndroid10\_._ +system.net.sockets\4.1.0\lib\MonoTouch10\_._ +system.net.sockets\4.1.0\lib\net46\System.Net.Sockets.dll +system.net.sockets\4.1.0\lib\xamarinios10\_._ +system.net.sockets\4.1.0\lib\xamarinmac20\_._ +system.net.sockets\4.1.0\lib\xamarintvos10\_._ +system.net.sockets\4.1.0\lib\xamarinwatchos10\_._ +system.net.sockets\4.1.0\ref\MonoAndroid10\_._ +system.net.sockets\4.1.0\ref\MonoTouch10\_._ +system.net.sockets\4.1.0\ref\net46\System.Net.Sockets.dll +system.net.sockets\4.1.0\ref\netstandard1.3\System.Net.Sockets.dll +system.net.sockets\4.1.0\ref\xamarinios10\_._ +system.net.sockets\4.1.0\ref\xamarinmac20\_._ +system.net.sockets\4.1.0\ref\xamarintvos10\_._ +system.net.sockets\4.1.0\ref\xamarinwatchos10\_._ +system.net.sockets\4.1.0\system.net.sockets.4.1.0.nupkg +system.net.sockets\4.1.0\system.net.sockets.4.1.0.nupkg.sha512 +system.net.sockets\4.1.0\system.net.sockets.nuspec +system.net.sockets\4.1.0\ThirdPartyNotices.txt +system.net.sockets\4.3.0\dotnet_library_license.txt +system.net.sockets\4.3.0\lib\MonoAndroid10\_._ +system.net.sockets\4.3.0\lib\MonoTouch10\_._ +system.net.sockets\4.3.0\lib\net46\System.Net.Sockets.dll +system.net.sockets\4.3.0\lib\xamarinios10\_._ +system.net.sockets\4.3.0\lib\xamarinmac20\_._ +system.net.sockets\4.3.0\lib\xamarintvos10\_._ +system.net.sockets\4.3.0\lib\xamarinwatchos10\_._ +system.net.sockets\4.3.0\ref\MonoAndroid10\_._ +system.net.sockets\4.3.0\ref\MonoTouch10\_._ +system.net.sockets\4.3.0\ref\net46\System.Net.Sockets.dll +system.net.sockets\4.3.0\ref\netstandard1.3\System.Net.Sockets.dll +system.net.sockets\4.3.0\ref\xamarinios10\_._ +system.net.sockets\4.3.0\ref\xamarinmac20\_._ +system.net.sockets\4.3.0\ref\xamarintvos10\_._ +system.net.sockets\4.3.0\ref\xamarinwatchos10\_._ +system.net.sockets\4.3.0\system.net.sockets.4.3.0.nupkg +system.net.sockets\4.3.0\system.net.sockets.4.3.0.nupkg.sha512 +system.net.sockets\4.3.0\system.net.sockets.nuspec +system.net.sockets\4.3.0\ThirdPartyNotices.txt +system.net.websockets.websocketprotocol\4.5.1\.signature.p7s +system.net.websockets.websocketprotocol\4.5.1\lib\netcoreapp2.1\System.Net.WebSockets.WebSocketProtocol.dll +system.net.websockets.websocketprotocol\4.5.1\lib\netstandard2.0\System.Net.WebSockets.WebSocketProtocol.dll +system.net.websockets.websocketprotocol\4.5.1\LICENSE.TXT +system.net.websockets.websocketprotocol\4.5.1\ref\netstandard2.0\System.Net.WebSockets.WebSocketProtocol.dll +system.net.websockets.websocketprotocol\4.5.1\system.net.websockets.websocketprotocol.4.5.1.nupkg +system.net.websockets.websocketprotocol\4.5.1\system.net.websockets.websocketprotocol.4.5.1.nupkg.sha512 +system.net.websockets.websocketprotocol\4.5.1\system.net.websockets.websocketprotocol.nuspec +system.net.websockets.websocketprotocol\4.5.1\THIRD-PARTY-NOTICES.TXT +system.net.websockets.websocketprotocol\4.5.1\useSharedDesignerContext.txt +system.net.websockets.websocketprotocol\4.5.1\version.txt +system.numerics.vectors\4.5.0\.signature.p7s +system.numerics.vectors\4.5.0\lib\MonoAndroid10\_._ +system.numerics.vectors\4.5.0\lib\MonoTouch10\_._ +system.numerics.vectors\4.5.0\lib\net46\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\lib\netcoreapp2.0\_._ +system.numerics.vectors\4.5.0\lib\netstandard1.0\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\lib\netstandard2.0\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\lib\portable-net45+win8+wp8+wpa81\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\lib\uap10.0.16299\_._ +system.numerics.vectors\4.5.0\lib\xamarinios10\_._ +system.numerics.vectors\4.5.0\lib\xamarinmac20\_._ +system.numerics.vectors\4.5.0\lib\xamarintvos10\_._ +system.numerics.vectors\4.5.0\lib\xamarinwatchos10\_._ +system.numerics.vectors\4.5.0\LICENSE.TXT +system.numerics.vectors\4.5.0\ref\MonoAndroid10\_._ +system.numerics.vectors\4.5.0\ref\MonoTouch10\_._ +system.numerics.vectors\4.5.0\ref\net45\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\ref\net46\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\ref\netcoreapp2.0\_._ +system.numerics.vectors\4.5.0\ref\netstandard1.0\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\ref\netstandard2.0\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\ref\uap10.0.16299\_._ +system.numerics.vectors\4.5.0\ref\xamarinios10\_._ +system.numerics.vectors\4.5.0\ref\xamarinmac20\_._ +system.numerics.vectors\4.5.0\ref\xamarintvos10\_._ +system.numerics.vectors\4.5.0\ref\xamarinwatchos10\_._ +system.numerics.vectors\4.5.0\system.numerics.vectors.4.5.0.nupkg +system.numerics.vectors\4.5.0\system.numerics.vectors.4.5.0.nupkg.sha512 +system.numerics.vectors\4.5.0\system.numerics.vectors.nuspec +system.numerics.vectors\4.5.0\THIRD-PARTY-NOTICES.TXT +system.numerics.vectors\4.5.0\useSharedDesignerContext.txt +system.numerics.vectors\4.5.0\version.txt +system.objectmodel\4.0.12\dotnet_library_license.txt +system.objectmodel\4.0.12\lib\MonoAndroid10\_._ +system.objectmodel\4.0.12\lib\MonoTouch10\_._ +system.objectmodel\4.0.12\lib\net45\_._ +system.objectmodel\4.0.12\lib\netcore50\System.ObjectModel.dll +system.objectmodel\4.0.12\lib\netstandard1.3\System.ObjectModel.dll +system.objectmodel\4.0.12\lib\portable-net45+win8+wp8+wpa81\_._ +system.objectmodel\4.0.12\lib\win8\_._ +system.objectmodel\4.0.12\lib\wp80\_._ +system.objectmodel\4.0.12\lib\wpa81\_._ +system.objectmodel\4.0.12\lib\xamarinios10\_._ +system.objectmodel\4.0.12\lib\xamarinmac20\_._ +system.objectmodel\4.0.12\lib\xamarintvos10\_._ +system.objectmodel\4.0.12\lib\xamarinwatchos10\_._ +system.objectmodel\4.0.12\ref\MonoAndroid10\_._ +system.objectmodel\4.0.12\ref\MonoTouch10\_._ +system.objectmodel\4.0.12\ref\net45\_._ +system.objectmodel\4.0.12\ref\netcore50\System.ObjectModel.dll +system.objectmodel\4.0.12\ref\netstandard1.0\System.ObjectModel.dll +system.objectmodel\4.0.12\ref\netstandard1.3\System.ObjectModel.dll +system.objectmodel\4.0.12\ref\portable-net45+win8+wp8+wpa81\_._ +system.objectmodel\4.0.12\ref\win8\_._ +system.objectmodel\4.0.12\ref\wp80\_._ +system.objectmodel\4.0.12\ref\wpa81\_._ +system.objectmodel\4.0.12\ref\xamarinios10\_._ +system.objectmodel\4.0.12\ref\xamarinmac20\_._ +system.objectmodel\4.0.12\ref\xamarintvos10\_._ +system.objectmodel\4.0.12\ref\xamarinwatchos10\_._ +system.objectmodel\4.0.12\system.objectmodel.4.0.12.nupkg +system.objectmodel\4.0.12\system.objectmodel.4.0.12.nupkg.sha512 +system.objectmodel\4.0.12\system.objectmodel.nuspec +system.objectmodel\4.0.12\ThirdPartyNotices.txt +system.objectmodel\4.3.0\dotnet_library_license.txt +system.objectmodel\4.3.0\lib\MonoAndroid10\_._ +system.objectmodel\4.3.0\lib\MonoTouch10\_._ +system.objectmodel\4.3.0\lib\net45\_._ +system.objectmodel\4.3.0\lib\netcore50\System.ObjectModel.dll +system.objectmodel\4.3.0\lib\netstandard1.3\System.ObjectModel.dll +system.objectmodel\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.objectmodel\4.3.0\lib\win8\_._ +system.objectmodel\4.3.0\lib\wp80\_._ +system.objectmodel\4.3.0\lib\wpa81\_._ +system.objectmodel\4.3.0\lib\xamarinios10\_._ +system.objectmodel\4.3.0\lib\xamarinmac20\_._ +system.objectmodel\4.3.0\lib\xamarintvos10\_._ +system.objectmodel\4.3.0\lib\xamarinwatchos10\_._ +system.objectmodel\4.3.0\ref\MonoAndroid10\_._ +system.objectmodel\4.3.0\ref\MonoTouch10\_._ +system.objectmodel\4.3.0\ref\net45\_._ +system.objectmodel\4.3.0\ref\netcore50\System.ObjectModel.dll +system.objectmodel\4.3.0\ref\netstandard1.0\System.ObjectModel.dll +system.objectmodel\4.3.0\ref\netstandard1.3\System.ObjectModel.dll +system.objectmodel\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.objectmodel\4.3.0\ref\win8\_._ +system.objectmodel\4.3.0\ref\wp80\_._ +system.objectmodel\4.3.0\ref\wpa81\_._ +system.objectmodel\4.3.0\ref\xamarinios10\_._ +system.objectmodel\4.3.0\ref\xamarinmac20\_._ +system.objectmodel\4.3.0\ref\xamarintvos10\_._ +system.objectmodel\4.3.0\ref\xamarinwatchos10\_._ +system.objectmodel\4.3.0\system.objectmodel.4.3.0.nupkg +system.objectmodel\4.3.0\system.objectmodel.4.3.0.nupkg.sha512 +system.objectmodel\4.3.0\system.objectmodel.nuspec +system.objectmodel\4.3.0\ThirdPartyNotices.txt +system.private.datacontractserialization\4.1.1\dotnet_library_license.txt +system.private.datacontractserialization\4.1.1\lib\netstandard1.3\System.Private.DataContractSerialization.dll +system.private.datacontractserialization\4.1.1\ref\netstandard\_._ +system.private.datacontractserialization\4.1.1\runtimes\aot\lib\netcore50\System.Private.DataContractSerialization.dll +system.private.datacontractserialization\4.1.1\system.private.datacontractserialization.4.1.1.nupkg +system.private.datacontractserialization\4.1.1\system.private.datacontractserialization.4.1.1.nupkg.sha512 +system.private.datacontractserialization\4.1.1\system.private.datacontractserialization.nuspec +system.private.datacontractserialization\4.1.1\ThirdPartyNotices.txt +system.private.datacontractserialization\4.3.0\dotnet_library_license.txt +system.private.datacontractserialization\4.3.0\lib\netstandard1.3\System.Private.DataContractSerialization.dll +system.private.datacontractserialization\4.3.0\ref\netstandard\_._ +system.private.datacontractserialization\4.3.0\runtimes\aot\lib\netcore50\System.Private.DataContractSerialization.dll +system.private.datacontractserialization\4.3.0\system.private.datacontractserialization.4.3.0.nupkg +system.private.datacontractserialization\4.3.0\system.private.datacontractserialization.4.3.0.nupkg.sha512 +system.private.datacontractserialization\4.3.0\system.private.datacontractserialization.nuspec +system.private.datacontractserialization\4.3.0\ThirdPartyNotices.txt +system.reflection.emit.ilgeneration\4.0.1\dotnet_library_license.txt +system.reflection.emit.ilgeneration\4.0.1\lib\net45\_._ +system.reflection.emit.ilgeneration\4.0.1\lib\netcore50\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.0.1\lib\netstandard1.3\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.0.1\lib\portable-net45+wp8\_._ +system.reflection.emit.ilgeneration\4.0.1\lib\wp80\_._ +system.reflection.emit.ilgeneration\4.0.1\ref\net45\_._ +system.reflection.emit.ilgeneration\4.0.1\ref\netstandard1.0\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.0.1\ref\portable-net45+wp8\_._ +system.reflection.emit.ilgeneration\4.0.1\ref\wp80\_._ +system.reflection.emit.ilgeneration\4.0.1\runtimes\aot\lib\netcore50\_._ +system.reflection.emit.ilgeneration\4.0.1\system.reflection.emit.ilgeneration.4.0.1.nupkg +system.reflection.emit.ilgeneration\4.0.1\system.reflection.emit.ilgeneration.4.0.1.nupkg.sha512 +system.reflection.emit.ilgeneration\4.0.1\system.reflection.emit.ilgeneration.nuspec +system.reflection.emit.ilgeneration\4.0.1\ThirdPartyNotices.txt +system.reflection.emit.ilgeneration\4.3.0\dotnet_library_license.txt +system.reflection.emit.ilgeneration\4.3.0\lib\MonoAndroid10\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\MonoTouch10\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\net45\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\netcore50\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.3.0\lib\netstandard1.3\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.3.0\lib\portable-net45+wp8\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\wp80\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\xamarinios10\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\xamarinmac20\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\xamarintvos10\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\MonoAndroid10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\MonoTouch10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\net45\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\netstandard1.0\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.3.0\ref\portable-net45+wp8\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\wp80\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\xamarinios10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\xamarinmac20\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\xamarintvos10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.emit.ilgeneration\4.3.0\runtimes\aot\lib\netcore50\_._ +system.reflection.emit.ilgeneration\4.3.0\system.reflection.emit.ilgeneration.4.3.0.nupkg +system.reflection.emit.ilgeneration\4.3.0\system.reflection.emit.ilgeneration.4.3.0.nupkg.sha512 +system.reflection.emit.ilgeneration\4.3.0\system.reflection.emit.ilgeneration.nuspec +system.reflection.emit.ilgeneration\4.3.0\ThirdPartyNotices.txt +system.reflection.emit.lightweight\4.0.1\dotnet_library_license.txt +system.reflection.emit.lightweight\4.0.1\lib\net45\_._ +system.reflection.emit.lightweight\4.0.1\lib\netcore50\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.0.1\lib\netstandard1.3\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.0.1\lib\portable-net45+wp8\_._ +system.reflection.emit.lightweight\4.0.1\lib\wp80\_._ +system.reflection.emit.lightweight\4.0.1\ref\net45\_._ +system.reflection.emit.lightweight\4.0.1\ref\netstandard1.0\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.0.1\ref\portable-net45+wp8\_._ +system.reflection.emit.lightweight\4.0.1\ref\wp80\_._ +system.reflection.emit.lightweight\4.0.1\runtimes\aot\lib\netcore50\_._ +system.reflection.emit.lightweight\4.0.1\system.reflection.emit.lightweight.4.0.1.nupkg +system.reflection.emit.lightweight\4.0.1\system.reflection.emit.lightweight.4.0.1.nupkg.sha512 +system.reflection.emit.lightweight\4.0.1\system.reflection.emit.lightweight.nuspec +system.reflection.emit.lightweight\4.0.1\ThirdPartyNotices.txt +system.reflection.emit.lightweight\4.3.0\dotnet_library_license.txt +system.reflection.emit.lightweight\4.3.0\lib\MonoAndroid10\_._ +system.reflection.emit.lightweight\4.3.0\lib\MonoTouch10\_._ +system.reflection.emit.lightweight\4.3.0\lib\net45\_._ +system.reflection.emit.lightweight\4.3.0\lib\netcore50\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.3.0\lib\netstandard1.3\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.3.0\lib\portable-net45+wp8\_._ +system.reflection.emit.lightweight\4.3.0\lib\wp80\_._ +system.reflection.emit.lightweight\4.3.0\lib\xamarinios10\_._ +system.reflection.emit.lightweight\4.3.0\lib\xamarinmac20\_._ +system.reflection.emit.lightweight\4.3.0\lib\xamarintvos10\_._ +system.reflection.emit.lightweight\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.emit.lightweight\4.3.0\ref\MonoAndroid10\_._ +system.reflection.emit.lightweight\4.3.0\ref\MonoTouch10\_._ +system.reflection.emit.lightweight\4.3.0\ref\net45\_._ +system.reflection.emit.lightweight\4.3.0\ref\netstandard1.0\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.3.0\ref\portable-net45+wp8\_._ +system.reflection.emit.lightweight\4.3.0\ref\wp80\_._ +system.reflection.emit.lightweight\4.3.0\ref\xamarinios10\_._ +system.reflection.emit.lightweight\4.3.0\ref\xamarinmac20\_._ +system.reflection.emit.lightweight\4.3.0\ref\xamarintvos10\_._ +system.reflection.emit.lightweight\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.emit.lightweight\4.3.0\runtimes\aot\lib\netcore50\_._ +system.reflection.emit.lightweight\4.3.0\system.reflection.emit.lightweight.4.3.0.nupkg +system.reflection.emit.lightweight\4.3.0\system.reflection.emit.lightweight.4.3.0.nupkg.sha512 +system.reflection.emit.lightweight\4.3.0\system.reflection.emit.lightweight.nuspec +system.reflection.emit.lightweight\4.3.0\ThirdPartyNotices.txt +system.reflection.emit\4.0.1\dotnet_library_license.txt +system.reflection.emit\4.0.1\lib\MonoAndroid10\_._ +system.reflection.emit\4.0.1\lib\net45\_._ +system.reflection.emit\4.0.1\lib\netcore50\System.Reflection.Emit.dll +system.reflection.emit\4.0.1\lib\netstandard1.3\System.Reflection.Emit.dll +system.reflection.emit\4.0.1\lib\xamarinmac20\_._ +system.reflection.emit\4.0.1\ref\MonoAndroid10\_._ +system.reflection.emit\4.0.1\ref\net45\_._ +system.reflection.emit\4.0.1\ref\netstandard1.1\System.Reflection.Emit.dll +system.reflection.emit\4.0.1\ref\xamarinmac20\_._ +system.reflection.emit\4.0.1\system.reflection.emit.4.0.1.nupkg +system.reflection.emit\4.0.1\system.reflection.emit.4.0.1.nupkg.sha512 +system.reflection.emit\4.0.1\system.reflection.emit.nuspec +system.reflection.emit\4.0.1\ThirdPartyNotices.txt +system.reflection.emit\4.3.0\dotnet_library_license.txt +system.reflection.emit\4.3.0\lib\MonoAndroid10\_._ +system.reflection.emit\4.3.0\lib\monotouch10\_._ +system.reflection.emit\4.3.0\lib\net45\_._ +system.reflection.emit\4.3.0\lib\netcore50\System.Reflection.Emit.dll +system.reflection.emit\4.3.0\lib\netstandard1.3\System.Reflection.Emit.dll +system.reflection.emit\4.3.0\lib\xamarinios10\_._ +system.reflection.emit\4.3.0\lib\xamarinmac20\_._ +system.reflection.emit\4.3.0\lib\xamarintvos10\_._ +system.reflection.emit\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.emit\4.3.0\ref\MonoAndroid10\_._ +system.reflection.emit\4.3.0\ref\net45\_._ +system.reflection.emit\4.3.0\ref\netstandard1.1\System.Reflection.Emit.dll +system.reflection.emit\4.3.0\ref\xamarinmac20\_._ +system.reflection.emit\4.3.0\system.reflection.emit.4.3.0.nupkg +system.reflection.emit\4.3.0\system.reflection.emit.4.3.0.nupkg.sha512 +system.reflection.emit\4.3.0\system.reflection.emit.nuspec +system.reflection.emit\4.3.0\ThirdPartyNotices.txt +system.reflection.extensions\4.0.1\dotnet_library_license.txt +system.reflection.extensions\4.0.1\lib\MonoAndroid10\_._ +system.reflection.extensions\4.0.1\lib\MonoTouch10\_._ +system.reflection.extensions\4.0.1\lib\net45\_._ +system.reflection.extensions\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection.extensions\4.0.1\lib\win8\_._ +system.reflection.extensions\4.0.1\lib\wp80\_._ +system.reflection.extensions\4.0.1\lib\wpa81\_._ +system.reflection.extensions\4.0.1\lib\xamarinios10\_._ +system.reflection.extensions\4.0.1\lib\xamarinmac20\_._ +system.reflection.extensions\4.0.1\lib\xamarintvos10\_._ +system.reflection.extensions\4.0.1\lib\xamarinwatchos10\_._ +system.reflection.extensions\4.0.1\ref\MonoAndroid10\_._ +system.reflection.extensions\4.0.1\ref\MonoTouch10\_._ +system.reflection.extensions\4.0.1\ref\net45\_._ +system.reflection.extensions\4.0.1\ref\netcore50\System.Reflection.Extensions.dll +system.reflection.extensions\4.0.1\ref\netstandard1.0\System.Reflection.Extensions.dll +system.reflection.extensions\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection.extensions\4.0.1\ref\win8\_._ +system.reflection.extensions\4.0.1\ref\wp80\_._ +system.reflection.extensions\4.0.1\ref\wpa81\_._ +system.reflection.extensions\4.0.1\ref\xamarinios10\_._ +system.reflection.extensions\4.0.1\ref\xamarinmac20\_._ +system.reflection.extensions\4.0.1\ref\xamarintvos10\_._ +system.reflection.extensions\4.0.1\ref\xamarinwatchos10\_._ +system.reflection.extensions\4.0.1\system.reflection.extensions.4.0.1.nupkg +system.reflection.extensions\4.0.1\system.reflection.extensions.4.0.1.nupkg.sha512 +system.reflection.extensions\4.0.1\system.reflection.extensions.nuspec +system.reflection.extensions\4.0.1\ThirdPartyNotices.txt +system.reflection.extensions\4.3.0\dotnet_library_license.txt +system.reflection.extensions\4.3.0\lib\MonoAndroid10\_._ +system.reflection.extensions\4.3.0\lib\MonoTouch10\_._ +system.reflection.extensions\4.3.0\lib\net45\_._ +system.reflection.extensions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection.extensions\4.3.0\lib\win8\_._ +system.reflection.extensions\4.3.0\lib\wp80\_._ +system.reflection.extensions\4.3.0\lib\wpa81\_._ +system.reflection.extensions\4.3.0\lib\xamarinios10\_._ +system.reflection.extensions\4.3.0\lib\xamarinmac20\_._ +system.reflection.extensions\4.3.0\lib\xamarintvos10\_._ +system.reflection.extensions\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.extensions\4.3.0\ref\MonoAndroid10\_._ +system.reflection.extensions\4.3.0\ref\MonoTouch10\_._ +system.reflection.extensions\4.3.0\ref\net45\_._ +system.reflection.extensions\4.3.0\ref\netcore50\System.Reflection.Extensions.dll +system.reflection.extensions\4.3.0\ref\netstandard1.0\System.Reflection.Extensions.dll +system.reflection.extensions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection.extensions\4.3.0\ref\win8\_._ +system.reflection.extensions\4.3.0\ref\wp80\_._ +system.reflection.extensions\4.3.0\ref\wpa81\_._ +system.reflection.extensions\4.3.0\ref\xamarinios10\_._ +system.reflection.extensions\4.3.0\ref\xamarinmac20\_._ +system.reflection.extensions\4.3.0\ref\xamarintvos10\_._ +system.reflection.extensions\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.extensions\4.3.0\system.reflection.extensions.4.3.0.nupkg +system.reflection.extensions\4.3.0\system.reflection.extensions.4.3.0.nupkg.sha512 +system.reflection.extensions\4.3.0\system.reflection.extensions.nuspec +system.reflection.extensions\4.3.0\ThirdPartyNotices.txt +system.reflection.metadata\1.4.1\dotnet_library_license.txt +system.reflection.metadata\1.4.1\lib\netstandard1.1\System.Reflection.Metadata.dll +system.reflection.metadata\1.4.1\lib\portable-net45+win8\System.Reflection.Metadata.dll +system.reflection.metadata\1.4.1\system.reflection.metadata.1.4.1.nupkg +system.reflection.metadata\1.4.1\system.reflection.metadata.1.4.1.nupkg.sha512 +system.reflection.metadata\1.4.1\system.reflection.metadata.nuspec +system.reflection.metadata\1.4.1\ThirdPartyNotices.txt +system.reflection.metadata\1.4.2\dotnet_library_license.txt +system.reflection.metadata\1.4.2\lib\netstandard1.1\System.Reflection.Metadata.dll +system.reflection.metadata\1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll +system.reflection.metadata\1.4.2\system.reflection.metadata.1.4.2.nupkg +system.reflection.metadata\1.4.2\system.reflection.metadata.1.4.2.nupkg.sha512 +system.reflection.metadata\1.4.2\system.reflection.metadata.nuspec +system.reflection.metadata\1.4.2\ThirdPartyNotices.txt +system.reflection.metadata\1.6.0\.signature.p7s +system.reflection.metadata\1.6.0\lib\netstandard1.1\System.Reflection.Metadata.dll +system.reflection.metadata\1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll +system.reflection.metadata\1.6.0\lib\portable-net45+win8\System.Reflection.Metadata.dll +system.reflection.metadata\1.6.0\LICENSE.TXT +system.reflection.metadata\1.6.0\system.reflection.metadata.1.6.0.nupkg +system.reflection.metadata\1.6.0\system.reflection.metadata.1.6.0.nupkg.sha512 +system.reflection.metadata\1.6.0\system.reflection.metadata.nuspec +system.reflection.metadata\1.6.0\THIRD-PARTY-NOTICES.TXT +system.reflection.metadata\1.6.0\useSharedDesignerContext.txt +system.reflection.metadata\1.6.0\version.txt +system.reflection.primitives\4.0.1\dotnet_library_license.txt +system.reflection.primitives\4.0.1\lib\MonoAndroid10\_._ +system.reflection.primitives\4.0.1\lib\MonoTouch10\_._ +system.reflection.primitives\4.0.1\lib\net45\_._ +system.reflection.primitives\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection.primitives\4.0.1\lib\win8\_._ +system.reflection.primitives\4.0.1\lib\wp80\_._ +system.reflection.primitives\4.0.1\lib\wpa81\_._ +system.reflection.primitives\4.0.1\lib\xamarinios10\_._ +system.reflection.primitives\4.0.1\lib\xamarinmac20\_._ +system.reflection.primitives\4.0.1\lib\xamarintvos10\_._ +system.reflection.primitives\4.0.1\lib\xamarinwatchos10\_._ +system.reflection.primitives\4.0.1\ref\MonoAndroid10\_._ +system.reflection.primitives\4.0.1\ref\MonoTouch10\_._ +system.reflection.primitives\4.0.1\ref\net45\_._ +system.reflection.primitives\4.0.1\ref\netcore50\System.Reflection.Primitives.dll +system.reflection.primitives\4.0.1\ref\netstandard1.0\System.Reflection.Primitives.dll +system.reflection.primitives\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection.primitives\4.0.1\ref\win8\_._ +system.reflection.primitives\4.0.1\ref\wp80\_._ +system.reflection.primitives\4.0.1\ref\wpa81\_._ +system.reflection.primitives\4.0.1\ref\xamarinios10\_._ +system.reflection.primitives\4.0.1\ref\xamarinmac20\_._ +system.reflection.primitives\4.0.1\ref\xamarintvos10\_._ +system.reflection.primitives\4.0.1\ref\xamarinwatchos10\_._ +system.reflection.primitives\4.0.1\system.reflection.primitives.4.0.1.nupkg +system.reflection.primitives\4.0.1\system.reflection.primitives.4.0.1.nupkg.sha512 +system.reflection.primitives\4.0.1\system.reflection.primitives.nuspec +system.reflection.primitives\4.0.1\ThirdPartyNotices.txt +system.reflection.primitives\4.3.0\dotnet_library_license.txt +system.reflection.primitives\4.3.0\lib\MonoAndroid10\_._ +system.reflection.primitives\4.3.0\lib\MonoTouch10\_._ +system.reflection.primitives\4.3.0\lib\net45\_._ +system.reflection.primitives\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection.primitives\4.3.0\lib\win8\_._ +system.reflection.primitives\4.3.0\lib\wp80\_._ +system.reflection.primitives\4.3.0\lib\wpa81\_._ +system.reflection.primitives\4.3.0\lib\xamarinios10\_._ +system.reflection.primitives\4.3.0\lib\xamarinmac20\_._ +system.reflection.primitives\4.3.0\lib\xamarintvos10\_._ +system.reflection.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.primitives\4.3.0\ref\MonoAndroid10\_._ +system.reflection.primitives\4.3.0\ref\MonoTouch10\_._ +system.reflection.primitives\4.3.0\ref\net45\_._ +system.reflection.primitives\4.3.0\ref\netcore50\System.Reflection.Primitives.dll +system.reflection.primitives\4.3.0\ref\netstandard1.0\System.Reflection.Primitives.dll +system.reflection.primitives\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection.primitives\4.3.0\ref\win8\_._ +system.reflection.primitives\4.3.0\ref\wp80\_._ +system.reflection.primitives\4.3.0\ref\wpa81\_._ +system.reflection.primitives\4.3.0\ref\xamarinios10\_._ +system.reflection.primitives\4.3.0\ref\xamarinmac20\_._ +system.reflection.primitives\4.3.0\ref\xamarintvos10\_._ +system.reflection.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.primitives\4.3.0\system.reflection.primitives.4.3.0.nupkg +system.reflection.primitives\4.3.0\system.reflection.primitives.4.3.0.nupkg.sha512 +system.reflection.primitives\4.3.0\system.reflection.primitives.nuspec +system.reflection.primitives\4.3.0\ThirdPartyNotices.txt +system.reflection.typeextensions\4.1.0\dotnet_library_license.txt +system.reflection.typeextensions\4.1.0\lib\MonoAndroid10\_._ +system.reflection.typeextensions\4.1.0\lib\MonoTouch10\_._ +system.reflection.typeextensions\4.1.0\lib\net46\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\lib\net462\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\lib\netcore50\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\lib\netstandard1.5\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\lib\xamarinios10\_._ +system.reflection.typeextensions\4.1.0\lib\xamarinmac20\_._ +system.reflection.typeextensions\4.1.0\lib\xamarintvos10\_._ +system.reflection.typeextensions\4.1.0\lib\xamarinwatchos10\_._ +system.reflection.typeextensions\4.1.0\ref\MonoAndroid10\_._ +system.reflection.typeextensions\4.1.0\ref\MonoTouch10\_._ +system.reflection.typeextensions\4.1.0\ref\net46\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\ref\net462\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\ref\netstandard1.3\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\ref\netstandard1.5\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\ref\xamarinios10\_._ +system.reflection.typeextensions\4.1.0\ref\xamarinmac20\_._ +system.reflection.typeextensions\4.1.0\ref\xamarintvos10\_._ +system.reflection.typeextensions\4.1.0\ref\xamarinwatchos10\_._ +system.reflection.typeextensions\4.1.0\runtimes\aot\lib\netcore50\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\system.reflection.typeextensions.4.1.0.nupkg +system.reflection.typeextensions\4.1.0\system.reflection.typeextensions.4.1.0.nupkg.sha512 +system.reflection.typeextensions\4.1.0\system.reflection.typeextensions.nuspec +system.reflection.typeextensions\4.1.0\ThirdPartyNotices.txt +system.reflection.typeextensions\4.3.0\dotnet_library_license.txt +system.reflection.typeextensions\4.3.0\lib\MonoAndroid10\_._ +system.reflection.typeextensions\4.3.0\lib\MonoTouch10\_._ +system.reflection.typeextensions\4.3.0\lib\net46\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\lib\net462\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\lib\netcore50\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\lib\netstandard1.5\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\lib\xamarinios10\_._ +system.reflection.typeextensions\4.3.0\lib\xamarinmac20\_._ +system.reflection.typeextensions\4.3.0\lib\xamarintvos10\_._ +system.reflection.typeextensions\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.typeextensions\4.3.0\ref\MonoAndroid10\_._ +system.reflection.typeextensions\4.3.0\ref\MonoTouch10\_._ +system.reflection.typeextensions\4.3.0\ref\net46\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\ref\net462\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\ref\netstandard1.3\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\ref\netstandard1.5\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\ref\xamarinios10\_._ +system.reflection.typeextensions\4.3.0\ref\xamarinmac20\_._ +system.reflection.typeextensions\4.3.0\ref\xamarintvos10\_._ +system.reflection.typeextensions\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.typeextensions\4.3.0\runtimes\aot\lib\netcore50\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\system.reflection.typeextensions.4.3.0.nupkg +system.reflection.typeextensions\4.3.0\system.reflection.typeextensions.4.3.0.nupkg.sha512 +system.reflection.typeextensions\4.3.0\system.reflection.typeextensions.nuspec +system.reflection.typeextensions\4.3.0\ThirdPartyNotices.txt +system.reflection\4.1.0\dotnet_library_license.txt +system.reflection\4.1.0\lib\MonoAndroid10\_._ +system.reflection\4.1.0\lib\MonoTouch10\_._ +system.reflection\4.1.0\lib\net45\_._ +system.reflection\4.1.0\lib\net462\System.Reflection.dll +system.reflection\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection\4.1.0\lib\win8\_._ +system.reflection\4.1.0\lib\wp80\_._ +system.reflection\4.1.0\lib\wpa81\_._ +system.reflection\4.1.0\lib\xamarinios10\_._ +system.reflection\4.1.0\lib\xamarinmac20\_._ +system.reflection\4.1.0\lib\xamarintvos10\_._ +system.reflection\4.1.0\lib\xamarinwatchos10\_._ +system.reflection\4.1.0\ref\MonoAndroid10\_._ +system.reflection\4.1.0\ref\MonoTouch10\_._ +system.reflection\4.1.0\ref\net45\_._ +system.reflection\4.1.0\ref\net462\System.Reflection.dll +system.reflection\4.1.0\ref\netcore50\System.Reflection.dll +system.reflection\4.1.0\ref\netstandard1.0\System.Reflection.dll +system.reflection\4.1.0\ref\netstandard1.3\System.Reflection.dll +system.reflection\4.1.0\ref\netstandard1.5\System.Reflection.dll +system.reflection\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection\4.1.0\ref\win8\_._ +system.reflection\4.1.0\ref\wp80\_._ +system.reflection\4.1.0\ref\wpa81\_._ +system.reflection\4.1.0\ref\xamarinios10\_._ +system.reflection\4.1.0\ref\xamarinmac20\_._ +system.reflection\4.1.0\ref\xamarintvos10\_._ +system.reflection\4.1.0\ref\xamarinwatchos10\_._ +system.reflection\4.1.0\system.reflection.4.1.0.nupkg +system.reflection\4.1.0\system.reflection.4.1.0.nupkg.sha512 +system.reflection\4.1.0\system.reflection.nuspec +system.reflection\4.1.0\ThirdPartyNotices.txt +system.reflection\4.3.0\dotnet_library_license.txt +system.reflection\4.3.0\lib\MonoAndroid10\_._ +system.reflection\4.3.0\lib\MonoTouch10\_._ +system.reflection\4.3.0\lib\net45\_._ +system.reflection\4.3.0\lib\net462\System.Reflection.dll +system.reflection\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection\4.3.0\lib\win8\_._ +system.reflection\4.3.0\lib\wp80\_._ +system.reflection\4.3.0\lib\wpa81\_._ +system.reflection\4.3.0\lib\xamarinios10\_._ +system.reflection\4.3.0\lib\xamarinmac20\_._ +system.reflection\4.3.0\lib\xamarintvos10\_._ +system.reflection\4.3.0\lib\xamarinwatchos10\_._ +system.reflection\4.3.0\ref\MonoAndroid10\_._ +system.reflection\4.3.0\ref\MonoTouch10\_._ +system.reflection\4.3.0\ref\net45\_._ +system.reflection\4.3.0\ref\net462\System.Reflection.dll +system.reflection\4.3.0\ref\netcore50\System.Reflection.dll +system.reflection\4.3.0\ref\netstandard1.0\System.Reflection.dll +system.reflection\4.3.0\ref\netstandard1.3\System.Reflection.dll +system.reflection\4.3.0\ref\netstandard1.5\System.Reflection.dll +system.reflection\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection\4.3.0\ref\win8\_._ +system.reflection\4.3.0\ref\wp80\_._ +system.reflection\4.3.0\ref\wpa81\_._ +system.reflection\4.3.0\ref\xamarinios10\_._ +system.reflection\4.3.0\ref\xamarinmac20\_._ +system.reflection\4.3.0\ref\xamarintvos10\_._ +system.reflection\4.3.0\ref\xamarinwatchos10\_._ +system.reflection\4.3.0\system.reflection.4.3.0.nupkg +system.reflection\4.3.0\system.reflection.4.3.0.nupkg.sha512 +system.reflection\4.3.0\system.reflection.nuspec +system.reflection\4.3.0\ThirdPartyNotices.txt +system.resources.resourcemanager\4.0.1\dotnet_library_license.txt +system.resources.resourcemanager\4.0.1\lib\MonoAndroid10\_._ +system.resources.resourcemanager\4.0.1\lib\MonoTouch10\_._ +system.resources.resourcemanager\4.0.1\lib\net45\_._ +system.resources.resourcemanager\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.resources.resourcemanager\4.0.1\lib\win8\_._ +system.resources.resourcemanager\4.0.1\lib\wp80\_._ +system.resources.resourcemanager\4.0.1\lib\wpa81\_._ +system.resources.resourcemanager\4.0.1\lib\xamarinios10\_._ +system.resources.resourcemanager\4.0.1\lib\xamarinmac20\_._ +system.resources.resourcemanager\4.0.1\lib\xamarintvos10\_._ +system.resources.resourcemanager\4.0.1\lib\xamarinwatchos10\_._ +system.resources.resourcemanager\4.0.1\ref\MonoAndroid10\_._ +system.resources.resourcemanager\4.0.1\ref\MonoTouch10\_._ +system.resources.resourcemanager\4.0.1\ref\net45\_._ +system.resources.resourcemanager\4.0.1\ref\netcore50\System.Resources.ResourceManager.dll +system.resources.resourcemanager\4.0.1\ref\netstandard1.0\System.Resources.ResourceManager.dll +system.resources.resourcemanager\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.resources.resourcemanager\4.0.1\ref\win8\_._ +system.resources.resourcemanager\4.0.1\ref\wp80\_._ +system.resources.resourcemanager\4.0.1\ref\wpa81\_._ +system.resources.resourcemanager\4.0.1\ref\xamarinios10\_._ +system.resources.resourcemanager\4.0.1\ref\xamarinmac20\_._ +system.resources.resourcemanager\4.0.1\ref\xamarintvos10\_._ +system.resources.resourcemanager\4.0.1\ref\xamarinwatchos10\_._ +system.resources.resourcemanager\4.0.1\system.resources.resourcemanager.4.0.1.nupkg +system.resources.resourcemanager\4.0.1\system.resources.resourcemanager.4.0.1.nupkg.sha512 +system.resources.resourcemanager\4.0.1\system.resources.resourcemanager.nuspec +system.resources.resourcemanager\4.0.1\ThirdPartyNotices.txt +system.resources.resourcemanager\4.3.0\dotnet_library_license.txt +system.resources.resourcemanager\4.3.0\lib\MonoAndroid10\_._ +system.resources.resourcemanager\4.3.0\lib\MonoTouch10\_._ +system.resources.resourcemanager\4.3.0\lib\net45\_._ +system.resources.resourcemanager\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.resources.resourcemanager\4.3.0\lib\win8\_._ +system.resources.resourcemanager\4.3.0\lib\wp80\_._ +system.resources.resourcemanager\4.3.0\lib\wpa81\_._ +system.resources.resourcemanager\4.3.0\lib\xamarinios10\_._ +system.resources.resourcemanager\4.3.0\lib\xamarinmac20\_._ +system.resources.resourcemanager\4.3.0\lib\xamarintvos10\_._ +system.resources.resourcemanager\4.3.0\lib\xamarinwatchos10\_._ +system.resources.resourcemanager\4.3.0\ref\MonoAndroid10\_._ +system.resources.resourcemanager\4.3.0\ref\MonoTouch10\_._ +system.resources.resourcemanager\4.3.0\ref\net45\_._ +system.resources.resourcemanager\4.3.0\ref\netcore50\System.Resources.ResourceManager.dll +system.resources.resourcemanager\4.3.0\ref\netstandard1.0\System.Resources.ResourceManager.dll +system.resources.resourcemanager\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.resources.resourcemanager\4.3.0\ref\win8\_._ +system.resources.resourcemanager\4.3.0\ref\wp80\_._ +system.resources.resourcemanager\4.3.0\ref\wpa81\_._ +system.resources.resourcemanager\4.3.0\ref\xamarinios10\_._ +system.resources.resourcemanager\4.3.0\ref\xamarinmac20\_._ +system.resources.resourcemanager\4.3.0\ref\xamarintvos10\_._ +system.resources.resourcemanager\4.3.0\ref\xamarinwatchos10\_._ +system.resources.resourcemanager\4.3.0\system.resources.resourcemanager.4.3.0.nupkg +system.resources.resourcemanager\4.3.0\system.resources.resourcemanager.4.3.0.nupkg.sha512 +system.resources.resourcemanager\4.3.0\system.resources.resourcemanager.nuspec +system.resources.resourcemanager\4.3.0\ThirdPartyNotices.txt +system.runtime.compilerservices.unsafe\4.5.0\.signature.p7s +system.runtime.compilerservices.unsafe\4.5.0\lib\netcoreapp2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\lib\uap10.0.16300\_._ +system.runtime.compilerservices.unsafe\4.5.0\LICENSE.TXT +system.runtime.compilerservices.unsafe\4.5.0\ref\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\ref\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\ref\uap10.0.16300\_._ +system.runtime.compilerservices.unsafe\4.5.0\system.runtime.compilerservices.unsafe.4.5.0.nupkg +system.runtime.compilerservices.unsafe\4.5.0\system.runtime.compilerservices.unsafe.4.5.0.nupkg.sha512 +system.runtime.compilerservices.unsafe\4.5.0\system.runtime.compilerservices.unsafe.nuspec +system.runtime.compilerservices.unsafe\4.5.0\THIRD-PARTY-NOTICES.TXT +system.runtime.compilerservices.unsafe\4.5.0\useSharedDesignerContext.txt +system.runtime.compilerservices.unsafe\4.5.0\version.txt +system.runtime.compilerservices.unsafe\4.5.1\.signature.p7s +system.runtime.compilerservices.unsafe\4.5.1\lib\netcoreapp2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\LICENSE.TXT +system.runtime.compilerservices.unsafe\4.5.1\ref\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\ref\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\system.runtime.compilerservices.unsafe.4.5.1.nupkg +system.runtime.compilerservices.unsafe\4.5.1\system.runtime.compilerservices.unsafe.4.5.1.nupkg.sha512 +system.runtime.compilerservices.unsafe\4.5.1\system.runtime.compilerservices.unsafe.nuspec +system.runtime.compilerservices.unsafe\4.5.1\THIRD-PARTY-NOTICES.TXT +system.runtime.compilerservices.unsafe\4.5.1\useSharedDesignerContext.txt +system.runtime.compilerservices.unsafe\4.5.1\version.txt +system.runtime.extensions\4.1.0\dotnet_library_license.txt +system.runtime.extensions\4.1.0\lib\MonoAndroid10\_._ +system.runtime.extensions\4.1.0\lib\MonoTouch10\_._ +system.runtime.extensions\4.1.0\lib\net45\_._ +system.runtime.extensions\4.1.0\lib\net462\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.extensions\4.1.0\lib\win8\_._ +system.runtime.extensions\4.1.0\lib\wp80\_._ +system.runtime.extensions\4.1.0\lib\wpa81\_._ +system.runtime.extensions\4.1.0\lib\xamarinios10\_._ +system.runtime.extensions\4.1.0\lib\xamarinmac20\_._ +system.runtime.extensions\4.1.0\lib\xamarintvos10\_._ +system.runtime.extensions\4.1.0\lib\xamarinwatchos10\_._ +system.runtime.extensions\4.1.0\ref\MonoAndroid10\_._ +system.runtime.extensions\4.1.0\ref\MonoTouch10\_._ +system.runtime.extensions\4.1.0\ref\net45\_._ +system.runtime.extensions\4.1.0\ref\net462\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\netcore50\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\netstandard1.0\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\netstandard1.3\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\netstandard1.5\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.extensions\4.1.0\ref\win8\_._ +system.runtime.extensions\4.1.0\ref\wp80\_._ +system.runtime.extensions\4.1.0\ref\wpa81\_._ +system.runtime.extensions\4.1.0\ref\xamarinios10\_._ +system.runtime.extensions\4.1.0\ref\xamarinmac20\_._ +system.runtime.extensions\4.1.0\ref\xamarintvos10\_._ +system.runtime.extensions\4.1.0\ref\xamarinwatchos10\_._ +system.runtime.extensions\4.1.0\system.runtime.extensions.4.1.0.nupkg +system.runtime.extensions\4.1.0\system.runtime.extensions.4.1.0.nupkg.sha512 +system.runtime.extensions\4.1.0\system.runtime.extensions.nuspec +system.runtime.extensions\4.1.0\ThirdPartyNotices.txt +system.runtime.extensions\4.3.0\dotnet_library_license.txt +system.runtime.extensions\4.3.0\lib\MonoAndroid10\_._ +system.runtime.extensions\4.3.0\lib\MonoTouch10\_._ +system.runtime.extensions\4.3.0\lib\net45\_._ +system.runtime.extensions\4.3.0\lib\net462\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.extensions\4.3.0\lib\win8\_._ +system.runtime.extensions\4.3.0\lib\wp80\_._ +system.runtime.extensions\4.3.0\lib\wpa81\_._ +system.runtime.extensions\4.3.0\lib\xamarinios10\_._ +system.runtime.extensions\4.3.0\lib\xamarinmac20\_._ +system.runtime.extensions\4.3.0\lib\xamarintvos10\_._ +system.runtime.extensions\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.extensions\4.3.0\ref\MonoAndroid10\_._ +system.runtime.extensions\4.3.0\ref\MonoTouch10\_._ +system.runtime.extensions\4.3.0\ref\net45\_._ +system.runtime.extensions\4.3.0\ref\net462\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\netcore50\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\netstandard1.0\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\netstandard1.3\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\netstandard1.5\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.extensions\4.3.0\ref\win8\_._ +system.runtime.extensions\4.3.0\ref\wp80\_._ +system.runtime.extensions\4.3.0\ref\wpa81\_._ +system.runtime.extensions\4.3.0\ref\xamarinios10\_._ +system.runtime.extensions\4.3.0\ref\xamarinmac20\_._ +system.runtime.extensions\4.3.0\ref\xamarintvos10\_._ +system.runtime.extensions\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.extensions\4.3.0\system.runtime.extensions.4.3.0.nupkg +system.runtime.extensions\4.3.0\system.runtime.extensions.4.3.0.nupkg.sha512 +system.runtime.extensions\4.3.0\system.runtime.extensions.nuspec +system.runtime.extensions\4.3.0\ThirdPartyNotices.txt +system.runtime.handles\4.0.1\dotnet_library_license.txt +system.runtime.handles\4.0.1\lib\MonoAndroid10\_._ +system.runtime.handles\4.0.1\lib\MonoTouch10\_._ +system.runtime.handles\4.0.1\lib\net46\_._ +system.runtime.handles\4.0.1\lib\xamarinios10\_._ +system.runtime.handles\4.0.1\lib\xamarinmac20\_._ +system.runtime.handles\4.0.1\lib\xamarintvos10\_._ +system.runtime.handles\4.0.1\lib\xamarinwatchos10\_._ +system.runtime.handles\4.0.1\ref\MonoAndroid10\_._ +system.runtime.handles\4.0.1\ref\MonoTouch10\_._ +system.runtime.handles\4.0.1\ref\net46\_._ +system.runtime.handles\4.0.1\ref\netstandard1.3\System.Runtime.Handles.dll +system.runtime.handles\4.0.1\ref\xamarinios10\_._ +system.runtime.handles\4.0.1\ref\xamarinmac20\_._ +system.runtime.handles\4.0.1\ref\xamarintvos10\_._ +system.runtime.handles\4.0.1\ref\xamarinwatchos10\_._ +system.runtime.handles\4.0.1\system.runtime.handles.4.0.1.nupkg +system.runtime.handles\4.0.1\system.runtime.handles.4.0.1.nupkg.sha512 +system.runtime.handles\4.0.1\system.runtime.handles.nuspec +system.runtime.handles\4.0.1\ThirdPartyNotices.txt +system.runtime.handles\4.3.0\dotnet_library_license.txt +system.runtime.handles\4.3.0\lib\MonoAndroid10\_._ +system.runtime.handles\4.3.0\lib\MonoTouch10\_._ +system.runtime.handles\4.3.0\lib\net46\_._ +system.runtime.handles\4.3.0\lib\xamarinios10\_._ +system.runtime.handles\4.3.0\lib\xamarinmac20\_._ +system.runtime.handles\4.3.0\lib\xamarintvos10\_._ +system.runtime.handles\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.handles\4.3.0\ref\MonoAndroid10\_._ +system.runtime.handles\4.3.0\ref\MonoTouch10\_._ +system.runtime.handles\4.3.0\ref\net46\_._ +system.runtime.handles\4.3.0\ref\netstandard1.3\System.Runtime.Handles.dll +system.runtime.handles\4.3.0\ref\xamarinios10\_._ +system.runtime.handles\4.3.0\ref\xamarinmac20\_._ +system.runtime.handles\4.3.0\ref\xamarintvos10\_._ +system.runtime.handles\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.handles\4.3.0\system.runtime.handles.4.3.0.nupkg +system.runtime.handles\4.3.0\system.runtime.handles.4.3.0.nupkg.sha512 +system.runtime.handles\4.3.0\system.runtime.handles.nuspec +system.runtime.handles\4.3.0\ThirdPartyNotices.txt +system.runtime.interopservices.runtimeinformation\4.0.0\dotnet_library_license.txt +system.runtime.interopservices.runtimeinformation\4.0.0\lib\MonoAndroid10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\MonoTouch10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\lib\win8\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\lib\wpa81\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\lib\xamarinios10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\xamarinmac20\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\xamarintvos10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\xamarinwatchos10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\MonoAndroid10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\MonoTouch10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\ref\xamarinios10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\xamarinmac20\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\xamarintvos10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\xamarinwatchos10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\aot\lib\netcore50\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\unix\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\win\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\win\lib\netcore50\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\win\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\system.runtime.interopservices.runtimeinformation.4.0.0.nupkg +system.runtime.interopservices.runtimeinformation\4.0.0\system.runtime.interopservices.runtimeinformation.4.0.0.nupkg.sha512 +system.runtime.interopservices.runtimeinformation\4.0.0\system.runtime.interopservices.runtimeinformation.nuspec +system.runtime.interopservices.runtimeinformation\4.0.0\ThirdPartyNotices.txt +system.runtime.interopservices.runtimeinformation\4.3.0\dotnet_library_license.txt +system.runtime.interopservices.runtimeinformation\4.3.0\lib\MonoAndroid10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\MonoTouch10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\lib\win8\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\lib\wpa81\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\lib\xamarinios10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\xamarinmac20\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\xamarintvos10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\MonoAndroid10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\MonoTouch10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\ref\xamarinios10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\xamarinmac20\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\xamarintvos10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\aot\lib\netcore50\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\unix\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\win\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\win\lib\netcore50\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\win\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\system.runtime.interopservices.runtimeinformation.4.3.0.nupkg +system.runtime.interopservices.runtimeinformation\4.3.0\system.runtime.interopservices.runtimeinformation.4.3.0.nupkg.sha512 +system.runtime.interopservices.runtimeinformation\4.3.0\system.runtime.interopservices.runtimeinformation.nuspec +system.runtime.interopservices.runtimeinformation\4.3.0\ThirdPartyNotices.txt +system.runtime.interopservices\4.1.0\dotnet_library_license.txt +system.runtime.interopservices\4.1.0\lib\MonoAndroid10\_._ +system.runtime.interopservices\4.1.0\lib\MonoTouch10\_._ +system.runtime.interopservices\4.1.0\lib\net45\_._ +system.runtime.interopservices\4.1.0\lib\net462\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\lib\portable-net45+win8+wpa81\_._ +system.runtime.interopservices\4.1.0\lib\win8\_._ +system.runtime.interopservices\4.1.0\lib\wpa81\_._ +system.runtime.interopservices\4.1.0\lib\xamarinios10\_._ +system.runtime.interopservices\4.1.0\lib\xamarinmac20\_._ +system.runtime.interopservices\4.1.0\lib\xamarintvos10\_._ +system.runtime.interopservices\4.1.0\lib\xamarinwatchos10\_._ +system.runtime.interopservices\4.1.0\ref\MonoAndroid10\_._ +system.runtime.interopservices\4.1.0\ref\MonoTouch10\_._ +system.runtime.interopservices\4.1.0\ref\net45\_._ +system.runtime.interopservices\4.1.0\ref\net462\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netcore50\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netstandard1.1\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netstandard1.2\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netstandard1.3\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netstandard1.5\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\portable-net45+win8+wpa81\_._ +system.runtime.interopservices\4.1.0\ref\win8\_._ +system.runtime.interopservices\4.1.0\ref\wpa81\_._ +system.runtime.interopservices\4.1.0\ref\xamarinios10\_._ +system.runtime.interopservices\4.1.0\ref\xamarinmac20\_._ +system.runtime.interopservices\4.1.0\ref\xamarintvos10\_._ +system.runtime.interopservices\4.1.0\ref\xamarinwatchos10\_._ +system.runtime.interopservices\4.1.0\system.runtime.interopservices.4.1.0.nupkg +system.runtime.interopservices\4.1.0\system.runtime.interopservices.4.1.0.nupkg.sha512 +system.runtime.interopservices\4.1.0\system.runtime.interopservices.nuspec +system.runtime.interopservices\4.1.0\ThirdPartyNotices.txt +system.runtime.interopservices\4.3.0\dotnet_library_license.txt +system.runtime.interopservices\4.3.0\lib\MonoAndroid10\_._ +system.runtime.interopservices\4.3.0\lib\MonoTouch10\_._ +system.runtime.interopservices\4.3.0\lib\net45\_._ +system.runtime.interopservices\4.3.0\lib\net462\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\lib\net463\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.runtime.interopservices\4.3.0\lib\win8\_._ +system.runtime.interopservices\4.3.0\lib\wpa81\_._ +system.runtime.interopservices\4.3.0\lib\xamarinios10\_._ +system.runtime.interopservices\4.3.0\lib\xamarinmac20\_._ +system.runtime.interopservices\4.3.0\lib\xamarintvos10\_._ +system.runtime.interopservices\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.interopservices\4.3.0\ref\MonoAndroid10\_._ +system.runtime.interopservices\4.3.0\ref\MonoTouch10\_._ +system.runtime.interopservices\4.3.0\ref\net45\_._ +system.runtime.interopservices\4.3.0\ref\net462\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\net463\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netcore50\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netcoreapp1.1\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netstandard1.1\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netstandard1.2\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netstandard1.3\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netstandard1.5\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.runtime.interopservices\4.3.0\ref\win8\_._ +system.runtime.interopservices\4.3.0\ref\wpa81\_._ +system.runtime.interopservices\4.3.0\ref\xamarinios10\_._ +system.runtime.interopservices\4.3.0\ref\xamarinmac20\_._ +system.runtime.interopservices\4.3.0\ref\xamarintvos10\_._ +system.runtime.interopservices\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.interopservices\4.3.0\system.runtime.interopservices.4.3.0.nupkg +system.runtime.interopservices\4.3.0\system.runtime.interopservices.4.3.0.nupkg.sha512 +system.runtime.interopservices\4.3.0\system.runtime.interopservices.nuspec +system.runtime.interopservices\4.3.0\ThirdPartyNotices.txt +system.runtime.numerics\4.0.1\dotnet_library_license.txt +system.runtime.numerics\4.0.1\lib\MonoAndroid10\_._ +system.runtime.numerics\4.0.1\lib\MonoTouch10\_._ +system.runtime.numerics\4.0.1\lib\net45\_._ +system.runtime.numerics\4.0.1\lib\netcore50\System.Runtime.Numerics.dll +system.runtime.numerics\4.0.1\lib\netstandard1.3\System.Runtime.Numerics.dll +system.runtime.numerics\4.0.1\lib\portable-net45+win8+wpa81\_._ +system.runtime.numerics\4.0.1\lib\win8\_._ +system.runtime.numerics\4.0.1\lib\wpa81\_._ +system.runtime.numerics\4.0.1\lib\xamarinios10\_._ +system.runtime.numerics\4.0.1\lib\xamarinmac20\_._ +system.runtime.numerics\4.0.1\lib\xamarintvos10\_._ +system.runtime.numerics\4.0.1\lib\xamarinwatchos10\_._ +system.runtime.numerics\4.0.1\ref\MonoAndroid10\_._ +system.runtime.numerics\4.0.1\ref\MonoTouch10\_._ +system.runtime.numerics\4.0.1\ref\net45\_._ +system.runtime.numerics\4.0.1\ref\netcore50\System.Runtime.Numerics.dll +system.runtime.numerics\4.0.1\ref\netstandard1.1\System.Runtime.Numerics.dll +system.runtime.numerics\4.0.1\ref\portable-net45+win8+wpa81\_._ +system.runtime.numerics\4.0.1\ref\win8\_._ +system.runtime.numerics\4.0.1\ref\wpa81\_._ +system.runtime.numerics\4.0.1\ref\xamarinios10\_._ +system.runtime.numerics\4.0.1\ref\xamarinmac20\_._ +system.runtime.numerics\4.0.1\ref\xamarintvos10\_._ +system.runtime.numerics\4.0.1\ref\xamarinwatchos10\_._ +system.runtime.numerics\4.0.1\system.runtime.numerics.4.0.1.nupkg +system.runtime.numerics\4.0.1\system.runtime.numerics.4.0.1.nupkg.sha512 +system.runtime.numerics\4.0.1\system.runtime.numerics.nuspec +system.runtime.numerics\4.0.1\ThirdPartyNotices.txt +system.runtime.numerics\4.3.0\dotnet_library_license.txt +system.runtime.numerics\4.3.0\lib\MonoAndroid10\_._ +system.runtime.numerics\4.3.0\lib\MonoTouch10\_._ +system.runtime.numerics\4.3.0\lib\net45\_._ +system.runtime.numerics\4.3.0\lib\netcore50\System.Runtime.Numerics.dll +system.runtime.numerics\4.3.0\lib\netstandard1.3\System.Runtime.Numerics.dll +system.runtime.numerics\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.runtime.numerics\4.3.0\lib\win8\_._ +system.runtime.numerics\4.3.0\lib\wpa81\_._ +system.runtime.numerics\4.3.0\lib\xamarinios10\_._ +system.runtime.numerics\4.3.0\lib\xamarinmac20\_._ +system.runtime.numerics\4.3.0\lib\xamarintvos10\_._ +system.runtime.numerics\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.numerics\4.3.0\ref\MonoAndroid10\_._ +system.runtime.numerics\4.3.0\ref\MonoTouch10\_._ +system.runtime.numerics\4.3.0\ref\net45\_._ +system.runtime.numerics\4.3.0\ref\netcore50\System.Runtime.Numerics.dll +system.runtime.numerics\4.3.0\ref\netstandard1.1\System.Runtime.Numerics.dll +system.runtime.numerics\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.runtime.numerics\4.3.0\ref\win8\_._ +system.runtime.numerics\4.3.0\ref\wpa81\_._ +system.runtime.numerics\4.3.0\ref\xamarinios10\_._ +system.runtime.numerics\4.3.0\ref\xamarinmac20\_._ +system.runtime.numerics\4.3.0\ref\xamarintvos10\_._ +system.runtime.numerics\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.numerics\4.3.0\system.runtime.numerics.4.3.0.nupkg +system.runtime.numerics\4.3.0\system.runtime.numerics.4.3.0.nupkg.sha512 +system.runtime.numerics\4.3.0\system.runtime.numerics.nuspec +system.runtime.numerics\4.3.0\ThirdPartyNotices.txt +system.runtime.serialization.formatters\4.3.0\dotnet_library_license.txt +system.runtime.serialization.formatters\4.3.0\lib\MonoAndroid10\_._ +system.runtime.serialization.formatters\4.3.0\lib\MonoTouch10\_._ +system.runtime.serialization.formatters\4.3.0\lib\net46\System.Runtime.Serialization.Formatters.dll +system.runtime.serialization.formatters\4.3.0\lib\netstandard1.4\System.Runtime.Serialization.Formatters.dll +system.runtime.serialization.formatters\4.3.0\lib\xamarinios10\_._ +system.runtime.serialization.formatters\4.3.0\lib\xamarinmac20\_._ +system.runtime.serialization.formatters\4.3.0\lib\xamarintvos10\_._ +system.runtime.serialization.formatters\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.serialization.formatters\4.3.0\ref\MonoAndroid10\_._ +system.runtime.serialization.formatters\4.3.0\ref\MonoTouch10\_._ +system.runtime.serialization.formatters\4.3.0\ref\net46\System.Runtime.Serialization.Formatters.dll +system.runtime.serialization.formatters\4.3.0\ref\netstandard1.3\System.Runtime.Serialization.Formatters.dll +system.runtime.serialization.formatters\4.3.0\ref\xamarinios10\_._ +system.runtime.serialization.formatters\4.3.0\ref\xamarinmac20\_._ +system.runtime.serialization.formatters\4.3.0\ref\xamarintvos10\_._ +system.runtime.serialization.formatters\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.serialization.formatters\4.3.0\system.runtime.serialization.formatters.4.3.0.nupkg +system.runtime.serialization.formatters\4.3.0\system.runtime.serialization.formatters.4.3.0.nupkg.sha512 +system.runtime.serialization.formatters\4.3.0\system.runtime.serialization.formatters.nuspec +system.runtime.serialization.formatters\4.3.0\ThirdPartyNotices.txt +system.runtime.serialization.json\4.0.2\dotnet_library_license.txt +system.runtime.serialization.json\4.0.2\lib\MonoAndroid10\_._ +system.runtime.serialization.json\4.0.2\lib\MonoTouch10\_._ +system.runtime.serialization.json\4.0.2\lib\net45\_._ +system.runtime.serialization.json\4.0.2\lib\netcore50\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.0.2\lib\netstandard1.3\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.0.2\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.json\4.0.2\lib\win8\_._ +system.runtime.serialization.json\4.0.2\lib\wp80\_._ +system.runtime.serialization.json\4.0.2\lib\wpa81\_._ +system.runtime.serialization.json\4.0.2\lib\xamarinios10\_._ +system.runtime.serialization.json\4.0.2\lib\xamarinmac20\_._ +system.runtime.serialization.json\4.0.2\lib\xamarintvos10\_._ +system.runtime.serialization.json\4.0.2\lib\xamarinwatchos10\_._ +system.runtime.serialization.json\4.0.2\ref\MonoAndroid10\_._ +system.runtime.serialization.json\4.0.2\ref\MonoTouch10\_._ +system.runtime.serialization.json\4.0.2\ref\net45\_._ +system.runtime.serialization.json\4.0.2\ref\netcore50\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.0.2\ref\netstandard1.0\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.0.2\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.json\4.0.2\ref\win8\_._ +system.runtime.serialization.json\4.0.2\ref\wp80\_._ +system.runtime.serialization.json\4.0.2\ref\wpa81\_._ +system.runtime.serialization.json\4.0.2\ref\xamarinios10\_._ +system.runtime.serialization.json\4.0.2\ref\xamarinmac20\_._ +system.runtime.serialization.json\4.0.2\ref\xamarintvos10\_._ +system.runtime.serialization.json\4.0.2\ref\xamarinwatchos10\_._ +system.runtime.serialization.json\4.0.2\system.runtime.serialization.json.4.0.2.nupkg +system.runtime.serialization.json\4.0.2\system.runtime.serialization.json.4.0.2.nupkg.sha512 +system.runtime.serialization.json\4.0.2\system.runtime.serialization.json.nuspec +system.runtime.serialization.json\4.0.2\ThirdPartyNotices.txt +system.runtime.serialization.primitives\4.1.1\dotnet_library_license.txt +system.runtime.serialization.primitives\4.1.1\lib\MonoAndroid10\_._ +system.runtime.serialization.primitives\4.1.1\lib\MonoTouch10\_._ +system.runtime.serialization.primitives\4.1.1\lib\net45\_._ +system.runtime.serialization.primitives\4.1.1\lib\net46\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\lib\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\lib\netstandard1.3\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.primitives\4.1.1\lib\win8\_._ +system.runtime.serialization.primitives\4.1.1\lib\wp80\_._ +system.runtime.serialization.primitives\4.1.1\lib\wpa81\_._ +system.runtime.serialization.primitives\4.1.1\lib\xamarinios10\_._ +system.runtime.serialization.primitives\4.1.1\lib\xamarinmac20\_._ +system.runtime.serialization.primitives\4.1.1\lib\xamarintvos10\_._ +system.runtime.serialization.primitives\4.1.1\lib\xamarinwatchos10\_._ +system.runtime.serialization.primitives\4.1.1\ref\MonoAndroid10\_._ +system.runtime.serialization.primitives\4.1.1\ref\MonoTouch10\_._ +system.runtime.serialization.primitives\4.1.1\ref\net45\_._ +system.runtime.serialization.primitives\4.1.1\ref\net46\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\ref\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\ref\netstandard1.0\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\ref\netstandard1.3\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.primitives\4.1.1\ref\win8\_._ +system.runtime.serialization.primitives\4.1.1\ref\wp80\_._ +system.runtime.serialization.primitives\4.1.1\ref\wpa81\_._ +system.runtime.serialization.primitives\4.1.1\ref\xamarinios10\_._ +system.runtime.serialization.primitives\4.1.1\ref\xamarinmac20\_._ +system.runtime.serialization.primitives\4.1.1\ref\xamarintvos10\_._ +system.runtime.serialization.primitives\4.1.1\ref\xamarinwatchos10\_._ +system.runtime.serialization.primitives\4.1.1\runtimes\aot\lib\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\system.runtime.serialization.primitives.4.1.1.nupkg +system.runtime.serialization.primitives\4.1.1\system.runtime.serialization.primitives.4.1.1.nupkg.sha512 +system.runtime.serialization.primitives\4.1.1\system.runtime.serialization.primitives.nuspec +system.runtime.serialization.primitives\4.1.1\ThirdPartyNotices.txt +system.runtime.serialization.primitives\4.3.0\dotnet_library_license.txt +system.runtime.serialization.primitives\4.3.0\lib\MonoAndroid10\_._ +system.runtime.serialization.primitives\4.3.0\lib\MonoTouch10\_._ +system.runtime.serialization.primitives\4.3.0\lib\net45\_._ +system.runtime.serialization.primitives\4.3.0\lib\net46\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\lib\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\lib\netstandard1.3\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.primitives\4.3.0\lib\win8\_._ +system.runtime.serialization.primitives\4.3.0\lib\wp80\_._ +system.runtime.serialization.primitives\4.3.0\lib\wpa81\_._ +system.runtime.serialization.primitives\4.3.0\lib\xamarinios10\_._ +system.runtime.serialization.primitives\4.3.0\lib\xamarinmac20\_._ +system.runtime.serialization.primitives\4.3.0\lib\xamarintvos10\_._ +system.runtime.serialization.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.serialization.primitives\4.3.0\ref\MonoAndroid10\_._ +system.runtime.serialization.primitives\4.3.0\ref\MonoTouch10\_._ +system.runtime.serialization.primitives\4.3.0\ref\net45\_._ +system.runtime.serialization.primitives\4.3.0\ref\net46\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\ref\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\ref\netstandard1.0\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\ref\netstandard1.3\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.primitives\4.3.0\ref\win8\_._ +system.runtime.serialization.primitives\4.3.0\ref\wp80\_._ +system.runtime.serialization.primitives\4.3.0\ref\wpa81\_._ +system.runtime.serialization.primitives\4.3.0\ref\xamarinios10\_._ +system.runtime.serialization.primitives\4.3.0\ref\xamarinmac20\_._ +system.runtime.serialization.primitives\4.3.0\ref\xamarintvos10\_._ +system.runtime.serialization.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.serialization.primitives\4.3.0\runtimes\aot\lib\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\system.runtime.serialization.primitives.4.3.0.nupkg +system.runtime.serialization.primitives\4.3.0\system.runtime.serialization.primitives.4.3.0.nupkg.sha512 +system.runtime.serialization.primitives\4.3.0\system.runtime.serialization.primitives.nuspec +system.runtime.serialization.primitives\4.3.0\ThirdPartyNotices.txt +system.runtime.serialization.xml\4.3.0\dotnet_library_license.txt +system.runtime.serialization.xml\4.3.0\lib\MonoAndroid10\_._ +system.runtime.serialization.xml\4.3.0\lib\MonoTouch10\_._ +system.runtime.serialization.xml\4.3.0\lib\net45\_._ +system.runtime.serialization.xml\4.3.0\lib\net46\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\lib\netcore50\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\lib\netstandard1.3\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.xml\4.3.0\lib\win8\_._ +system.runtime.serialization.xml\4.3.0\lib\wp80\_._ +system.runtime.serialization.xml\4.3.0\lib\wpa81\_._ +system.runtime.serialization.xml\4.3.0\lib\xamarinios10\_._ +system.runtime.serialization.xml\4.3.0\lib\xamarinmac20\_._ +system.runtime.serialization.xml\4.3.0\lib\xamarintvos10\_._ +system.runtime.serialization.xml\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.serialization.xml\4.3.0\ref\MonoAndroid10\_._ +system.runtime.serialization.xml\4.3.0\ref\MonoTouch10\_._ +system.runtime.serialization.xml\4.3.0\ref\net45\_._ +system.runtime.serialization.xml\4.3.0\ref\net46\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\ref\netcore50\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\ref\netstandard1.0\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\ref\netstandard1.3\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.xml\4.3.0\ref\win8\_._ +system.runtime.serialization.xml\4.3.0\ref\wp80\_._ +system.runtime.serialization.xml\4.3.0\ref\wpa81\_._ +system.runtime.serialization.xml\4.3.0\ref\xamarinios10\_._ +system.runtime.serialization.xml\4.3.0\ref\xamarinmac20\_._ +system.runtime.serialization.xml\4.3.0\ref\xamarintvos10\_._ +system.runtime.serialization.xml\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.serialization.xml\4.3.0\system.runtime.serialization.xml.4.3.0.nupkg +system.runtime.serialization.xml\4.3.0\system.runtime.serialization.xml.4.3.0.nupkg.sha512 +system.runtime.serialization.xml\4.3.0\system.runtime.serialization.xml.nuspec +system.runtime.serialization.xml\4.3.0\ThirdPartyNotices.txt +system.runtime\4.1.0\dotnet_library_license.txt +system.runtime\4.1.0\lib\MonoAndroid10\_._ +system.runtime\4.1.0\lib\MonoTouch10\_._ +system.runtime\4.1.0\lib\net45\_._ +system.runtime\4.1.0\lib\net462\System.Runtime.dll +system.runtime\4.1.0\lib\portable-net45+win8+wp80+wpa81\_._ +system.runtime\4.1.0\lib\win8\_._ +system.runtime\4.1.0\lib\wp80\_._ +system.runtime\4.1.0\lib\wpa81\_._ +system.runtime\4.1.0\lib\xamarinios10\_._ +system.runtime\4.1.0\lib\xamarinmac20\_._ +system.runtime\4.1.0\lib\xamarintvos10\_._ +system.runtime\4.1.0\lib\xamarinwatchos10\_._ +system.runtime\4.1.0\ref\MonoAndroid10\_._ +system.runtime\4.1.0\ref\MonoTouch10\_._ +system.runtime\4.1.0\ref\net45\_._ +system.runtime\4.1.0\ref\net462\System.Runtime.dll +system.runtime\4.1.0\ref\netcore50\System.Runtime.dll +system.runtime\4.1.0\ref\netstandard1.0\System.Runtime.dll +system.runtime\4.1.0\ref\netstandard1.2\System.Runtime.dll +system.runtime\4.1.0\ref\netstandard1.3\System.Runtime.dll +system.runtime\4.1.0\ref\netstandard1.5\System.Runtime.dll +system.runtime\4.1.0\ref\portable-net45+win8+wp80+wpa81\_._ +system.runtime\4.1.0\ref\win8\_._ +system.runtime\4.1.0\ref\wp80\_._ +system.runtime\4.1.0\ref\wpa81\_._ +system.runtime\4.1.0\ref\xamarinios10\_._ +system.runtime\4.1.0\ref\xamarinmac20\_._ +system.runtime\4.1.0\ref\xamarintvos10\_._ +system.runtime\4.1.0\ref\xamarinwatchos10\_._ +system.runtime\4.1.0\system.runtime.4.1.0.nupkg +system.runtime\4.1.0\system.runtime.4.1.0.nupkg.sha512 +system.runtime\4.1.0\system.runtime.nuspec +system.runtime\4.1.0\ThirdPartyNotices.txt +system.runtime\4.3.0\dotnet_library_license.txt +system.runtime\4.3.0\lib\MonoAndroid10\_._ +system.runtime\4.3.0\lib\MonoTouch10\_._ +system.runtime\4.3.0\lib\net45\_._ +system.runtime\4.3.0\lib\net462\System.Runtime.dll +system.runtime\4.3.0\lib\portable-net45+win8+wp80+wpa81\_._ +system.runtime\4.3.0\lib\win8\_._ +system.runtime\4.3.0\lib\wp80\_._ +system.runtime\4.3.0\lib\wpa81\_._ +system.runtime\4.3.0\lib\xamarinios10\_._ +system.runtime\4.3.0\lib\xamarinmac20\_._ +system.runtime\4.3.0\lib\xamarintvos10\_._ +system.runtime\4.3.0\lib\xamarinwatchos10\_._ +system.runtime\4.3.0\ref\MonoAndroid10\_._ +system.runtime\4.3.0\ref\MonoTouch10\_._ +system.runtime\4.3.0\ref\net45\_._ +system.runtime\4.3.0\ref\net462\System.Runtime.dll +system.runtime\4.3.0\ref\netcore50\System.Runtime.dll +system.runtime\4.3.0\ref\netstandard1.0\System.Runtime.dll +system.runtime\4.3.0\ref\netstandard1.2\System.Runtime.dll +system.runtime\4.3.0\ref\netstandard1.3\System.Runtime.dll +system.runtime\4.3.0\ref\netstandard1.5\System.Runtime.dll +system.runtime\4.3.0\ref\portable-net45+win8+wp80+wpa81\_._ +system.runtime\4.3.0\ref\win8\_._ +system.runtime\4.3.0\ref\wp80\_._ +system.runtime\4.3.0\ref\wpa81\_._ +system.runtime\4.3.0\ref\xamarinios10\_._ +system.runtime\4.3.0\ref\xamarinmac20\_._ +system.runtime\4.3.0\ref\xamarintvos10\_._ +system.runtime\4.3.0\ref\xamarinwatchos10\_._ +system.runtime\4.3.0\system.runtime.4.3.0.nupkg +system.runtime\4.3.0\system.runtime.4.3.0.nupkg.sha512 +system.runtime\4.3.0\system.runtime.nuspec +system.runtime\4.3.0\ThirdPartyNotices.txt +system.security.accesscontrol\4.5.0\.signature.p7s +system.security.accesscontrol\4.5.0\lib\net46\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\lib\net461\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\lib\netstandard1.3\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\lib\netstandard2.0\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\lib\uap10.0.16299\_._ +system.security.accesscontrol\4.5.0\LICENSE.TXT +system.security.accesscontrol\4.5.0\ref\net46\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\ref\net461\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\ref\netstandard1.3\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\ref\netstandard2.0\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\ref\uap10.0.16299\_._ +system.security.accesscontrol\4.5.0\runtimes\win\lib\net46\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\runtimes\win\lib\net461\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\runtimes\win\lib\netstandard1.3\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\runtimes\win\lib\uap10.0.16299\_._ +system.security.accesscontrol\4.5.0\system.security.accesscontrol.4.5.0.nupkg +system.security.accesscontrol\4.5.0\system.security.accesscontrol.4.5.0.nupkg.sha512 +system.security.accesscontrol\4.5.0\system.security.accesscontrol.nuspec +system.security.accesscontrol\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.accesscontrol\4.5.0\useSharedDesignerContext.txt +system.security.accesscontrol\4.5.0\version.txt +system.security.claims\4.3.0\dotnet_library_license.txt +system.security.claims\4.3.0\lib\MonoAndroid10\_._ +system.security.claims\4.3.0\lib\MonoTouch10\_._ +system.security.claims\4.3.0\lib\net46\System.Security.Claims.dll +system.security.claims\4.3.0\lib\netstandard1.3\System.Security.Claims.dll +system.security.claims\4.3.0\lib\xamarinios10\_._ +system.security.claims\4.3.0\lib\xamarinmac20\_._ +system.security.claims\4.3.0\lib\xamarintvos10\_._ +system.security.claims\4.3.0\lib\xamarinwatchos10\_._ +system.security.claims\4.3.0\ref\MonoAndroid10\_._ +system.security.claims\4.3.0\ref\MonoTouch10\_._ +system.security.claims\4.3.0\ref\net46\System.Security.Claims.dll +system.security.claims\4.3.0\ref\netstandard1.3\System.Security.Claims.dll +system.security.claims\4.3.0\ref\xamarinios10\_._ +system.security.claims\4.3.0\ref\xamarinmac20\_._ +system.security.claims\4.3.0\ref\xamarintvos10\_._ +system.security.claims\4.3.0\ref\xamarinwatchos10\_._ +system.security.claims\4.3.0\system.security.claims.4.3.0.nupkg +system.security.claims\4.3.0\system.security.claims.4.3.0.nupkg.sha512 +system.security.claims\4.3.0\system.security.claims.nuspec +system.security.claims\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.algorithms\4.2.0\dotnet_library_license.txt +system.security.cryptography.algorithms\4.2.0\lib\MonoAndroid10\_._ +system.security.cryptography.algorithms\4.2.0\lib\MonoTouch10\_._ +system.security.cryptography.algorithms\4.2.0\lib\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\lib\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\lib\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\lib\xamarinios10\_._ +system.security.cryptography.algorithms\4.2.0\lib\xamarinmac20\_._ +system.security.cryptography.algorithms\4.2.0\lib\xamarintvos10\_._ +system.security.cryptography.algorithms\4.2.0\lib\xamarinwatchos10\_._ +system.security.cryptography.algorithms\4.2.0\ref\MonoAndroid10\_._ +system.security.cryptography.algorithms\4.2.0\ref\MonoTouch10\_._ +system.security.cryptography.algorithms\4.2.0\ref\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\netstandard1.3\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\netstandard1.4\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\xamarinios10\_._ +system.security.cryptography.algorithms\4.2.0\ref\xamarinmac20\_._ +system.security.cryptography.algorithms\4.2.0\ref\xamarintvos10\_._ +system.security.cryptography.algorithms\4.2.0\ref\xamarinwatchos10\_._ +system.security.cryptography.algorithms\4.2.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\netcore50\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\system.security.cryptography.algorithms.4.2.0.nupkg +system.security.cryptography.algorithms\4.2.0\system.security.cryptography.algorithms.4.2.0.nupkg.sha512 +system.security.cryptography.algorithms\4.2.0\system.security.cryptography.algorithms.nuspec +system.security.cryptography.algorithms\4.2.0\ThirdPartyNotices.txt +system.security.cryptography.algorithms\4.3.0\dotnet_library_license.txt +system.security.cryptography.algorithms\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.algorithms\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.algorithms\4.3.0\lib\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.algorithms\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.algorithms\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.algorithms\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.algorithms\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.algorithms\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.algorithms\4.3.0\ref\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\netstandard1.4\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.algorithms\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.algorithms\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.algorithms\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.algorithms\4.3.0\runtimes\osx\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\netcore50\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\system.security.cryptography.algorithms.4.3.0.nupkg +system.security.cryptography.algorithms\4.3.0\system.security.cryptography.algorithms.4.3.0.nupkg.sha512 +system.security.cryptography.algorithms\4.3.0\system.security.cryptography.algorithms.nuspec +system.security.cryptography.algorithms\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.cng\4.2.0\dotnet_library_license.txt +system.security.cryptography.cng\4.2.0\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\lib\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\netstandard1.3\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\system.security.cryptography.cng.4.2.0.nupkg +system.security.cryptography.cng\4.2.0\system.security.cryptography.cng.4.2.0.nupkg.sha512 +system.security.cryptography.cng\4.2.0\system.security.cryptography.cng.nuspec +system.security.cryptography.cng\4.2.0\ThirdPartyNotices.txt +system.security.cryptography.cng\4.3.0\dotnet_library_license.txt +system.security.cryptography.cng\4.3.0\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\lib\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\system.security.cryptography.cng.4.3.0.nupkg +system.security.cryptography.cng\4.3.0\system.security.cryptography.cng.4.3.0.nupkg.sha512 +system.security.cryptography.cng\4.3.0\system.security.cryptography.cng.nuspec +system.security.cryptography.cng\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.cng\4.5.0\.signature.p7s +system.security.cryptography.cng\4.5.0\lib\MonoAndroid10\_._ +system.security.cryptography.cng\4.5.0\lib\MonoTouch10\_._ +system.security.cryptography.cng\4.5.0\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\net462\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\net47\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netcoreapp2.1\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netstandard1.3\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netstandard2.0\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\uap10.0.16299\_._ +system.security.cryptography.cng\4.5.0\lib\xamarinios10\_._ +system.security.cryptography.cng\4.5.0\lib\xamarinmac20\_._ +system.security.cryptography.cng\4.5.0\lib\xamarintvos10\_._ +system.security.cryptography.cng\4.5.0\lib\xamarinwatchos10\_._ +system.security.cryptography.cng\4.5.0\LICENSE.TXT +system.security.cryptography.cng\4.5.0\ref\MonoAndroid10\_._ +system.security.cryptography.cng\4.5.0\ref\MonoTouch10\_._ +system.security.cryptography.cng\4.5.0\ref\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\net462\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\net47\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netcoreapp2.0\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netcoreapp2.1\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netstandard1.3\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netstandard2.0\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\uap10.0.16299\_._ +system.security.cryptography.cng\4.5.0\ref\xamarinios10\_._ +system.security.cryptography.cng\4.5.0\ref\xamarinmac20\_._ +system.security.cryptography.cng\4.5.0\ref\xamarintvos10\_._ +system.security.cryptography.cng\4.5.0\ref\xamarinwatchos10\_._ +system.security.cryptography.cng\4.5.0\runtimes\win\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\net462\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\net47\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\netcoreapp2.1\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\uap10.0.16299\_._ +system.security.cryptography.cng\4.5.0\system.security.cryptography.cng.4.5.0.nupkg +system.security.cryptography.cng\4.5.0\system.security.cryptography.cng.4.5.0.nupkg.sha512 +system.security.cryptography.cng\4.5.0\system.security.cryptography.cng.nuspec +system.security.cryptography.cng\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.cryptography.cng\4.5.0\useSharedDesignerContext.txt +system.security.cryptography.cng\4.5.0\version.txt +system.security.cryptography.csp\4.0.0\dotnet_library_license.txt +system.security.cryptography.csp\4.0.0\lib\MonoAndroid10\_._ +system.security.cryptography.csp\4.0.0\lib\MonoTouch10\_._ +system.security.cryptography.csp\4.0.0\lib\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\lib\xamarinios10\_._ +system.security.cryptography.csp\4.0.0\lib\xamarinmac20\_._ +system.security.cryptography.csp\4.0.0\lib\xamarintvos10\_._ +system.security.cryptography.csp\4.0.0\lib\xamarinwatchos10\_._ +system.security.cryptography.csp\4.0.0\ref\MonoAndroid10\_._ +system.security.cryptography.csp\4.0.0\ref\MonoTouch10\_._ +system.security.cryptography.csp\4.0.0\ref\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\ref\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\ref\xamarinios10\_._ +system.security.cryptography.csp\4.0.0\ref\xamarinmac20\_._ +system.security.cryptography.csp\4.0.0\ref\xamarintvos10\_._ +system.security.cryptography.csp\4.0.0\ref\xamarinwatchos10\_._ +system.security.cryptography.csp\4.0.0\runtimes\unix\lib\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\runtimes\win\lib\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\runtimes\win\lib\netcore50\_._ +system.security.cryptography.csp\4.0.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\system.security.cryptography.csp.4.0.0.nupkg +system.security.cryptography.csp\4.0.0\system.security.cryptography.csp.4.0.0.nupkg.sha512 +system.security.cryptography.csp\4.0.0\system.security.cryptography.csp.nuspec +system.security.cryptography.csp\4.0.0\ThirdPartyNotices.txt +system.security.cryptography.csp\4.3.0\dotnet_library_license.txt +system.security.cryptography.csp\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.csp\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.csp\4.3.0\lib\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.csp\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.csp\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.csp\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.csp\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.csp\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.csp\4.3.0\ref\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.csp\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.csp\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.csp\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.csp\4.3.0\runtimes\unix\lib\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\runtimes\win\lib\netcore50\_._ +system.security.cryptography.csp\4.3.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\system.security.cryptography.csp.4.3.0.nupkg +system.security.cryptography.csp\4.3.0\system.security.cryptography.csp.4.3.0.nupkg.sha512 +system.security.cryptography.csp\4.3.0\system.security.cryptography.csp.nuspec +system.security.cryptography.csp\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.encoding\4.0.0\dotnet_library_license.txt +system.security.cryptography.encoding\4.0.0\lib\MonoAndroid10\_._ +system.security.cryptography.encoding\4.0.0\lib\MonoTouch10\_._ +system.security.cryptography.encoding\4.0.0\lib\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\lib\xamarinios10\_._ +system.security.cryptography.encoding\4.0.0\lib\xamarinmac20\_._ +system.security.cryptography.encoding\4.0.0\lib\xamarintvos10\_._ +system.security.cryptography.encoding\4.0.0\lib\xamarinwatchos10\_._ +system.security.cryptography.encoding\4.0.0\ref\MonoAndroid10\_._ +system.security.cryptography.encoding\4.0.0\ref\MonoTouch10\_._ +system.security.cryptography.encoding\4.0.0\ref\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\ref\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\ref\xamarinios10\_._ +system.security.cryptography.encoding\4.0.0\ref\xamarinmac20\_._ +system.security.cryptography.encoding\4.0.0\ref\xamarintvos10\_._ +system.security.cryptography.encoding\4.0.0\ref\xamarinwatchos10\_._ +system.security.cryptography.encoding\4.0.0\runtimes\unix\lib\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\runtimes\win\lib\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\system.security.cryptography.encoding.4.0.0.nupkg +system.security.cryptography.encoding\4.0.0\system.security.cryptography.encoding.4.0.0.nupkg.sha512 +system.security.cryptography.encoding\4.0.0\system.security.cryptography.encoding.nuspec +system.security.cryptography.encoding\4.0.0\ThirdPartyNotices.txt +system.security.cryptography.encoding\4.3.0\dotnet_library_license.txt +system.security.cryptography.encoding\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.encoding\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.encoding\4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.encoding\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.encoding\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.encoding\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.encoding\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.encoding\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.encoding\4.3.0\ref\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.encoding\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.encoding\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.encoding\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.encoding\4.3.0\runtimes\unix\lib\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\system.security.cryptography.encoding.4.3.0.nupkg +system.security.cryptography.encoding\4.3.0\system.security.cryptography.encoding.4.3.0.nupkg.sha512 +system.security.cryptography.encoding\4.3.0\system.security.cryptography.encoding.nuspec +system.security.cryptography.encoding\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.openssl\4.0.0\dotnet_library_license.txt +system.security.cryptography.openssl\4.0.0\lib\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.0.0\ref\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.0.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.0.0\system.security.cryptography.openssl.4.0.0.nupkg +system.security.cryptography.openssl\4.0.0\system.security.cryptography.openssl.4.0.0.nupkg.sha512 +system.security.cryptography.openssl\4.0.0\system.security.cryptography.openssl.nuspec +system.security.cryptography.openssl\4.0.0\ThirdPartyNotices.txt +system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +system.security.cryptography.openssl\4.3.0\lib\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.3.0\ref\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.3.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.3.0\system.security.cryptography.openssl.4.3.0.nupkg +system.security.cryptography.openssl\4.3.0\system.security.cryptography.openssl.4.3.0.nupkg.sha512 +system.security.cryptography.openssl\4.3.0\system.security.cryptography.openssl.nuspec +system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.pkcs\4.5.0\.signature.p7s +system.security.cryptography.pkcs\4.5.0\lib\net46\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\lib\net461\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\lib\netcoreapp2.1\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\lib\netstandard1.3\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\lib\netstandard2.0\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\LICENSE.TXT +system.security.cryptography.pkcs\4.5.0\ref\net46\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\ref\net461\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\ref\netcoreapp2.1\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\ref\netstandard1.3\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\ref\netstandard2.0\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\net46\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\net461\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\netcoreapp2.1\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\netstandard2.0\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\system.security.cryptography.pkcs.4.5.0.nupkg +system.security.cryptography.pkcs\4.5.0\system.security.cryptography.pkcs.4.5.0.nupkg.sha512 +system.security.cryptography.pkcs\4.5.0\system.security.cryptography.pkcs.nuspec +system.security.cryptography.pkcs\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.cryptography.pkcs\4.5.0\useSharedDesignerContext.txt +system.security.cryptography.pkcs\4.5.0\version.txt +system.security.cryptography.primitives\4.0.0\dotnet_library_license.txt +system.security.cryptography.primitives\4.0.0\lib\MonoAndroid10\_._ +system.security.cryptography.primitives\4.0.0\lib\MonoTouch10\_._ +system.security.cryptography.primitives\4.0.0\lib\net46\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.0.0\lib\netstandard1.3\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.0.0\lib\xamarinios10\_._ +system.security.cryptography.primitives\4.0.0\lib\xamarinmac20\_._ +system.security.cryptography.primitives\4.0.0\lib\xamarintvos10\_._ +system.security.cryptography.primitives\4.0.0\lib\xamarinwatchos10\_._ +system.security.cryptography.primitives\4.0.0\ref\MonoAndroid10\_._ +system.security.cryptography.primitives\4.0.0\ref\MonoTouch10\_._ +system.security.cryptography.primitives\4.0.0\ref\net46\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.0.0\ref\netstandard1.3\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.0.0\ref\xamarinios10\_._ +system.security.cryptography.primitives\4.0.0\ref\xamarinmac20\_._ +system.security.cryptography.primitives\4.0.0\ref\xamarintvos10\_._ +system.security.cryptography.primitives\4.0.0\ref\xamarinwatchos10\_._ +system.security.cryptography.primitives\4.0.0\system.security.cryptography.primitives.4.0.0.nupkg +system.security.cryptography.primitives\4.0.0\system.security.cryptography.primitives.4.0.0.nupkg.sha512 +system.security.cryptography.primitives\4.0.0\system.security.cryptography.primitives.nuspec +system.security.cryptography.primitives\4.0.0\ThirdPartyNotices.txt +system.security.cryptography.primitives\4.3.0\dotnet_library_license.txt +system.security.cryptography.primitives\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.primitives\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.primitives\4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.3.0\lib\netstandard1.3\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.primitives\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.primitives\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.primitives\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.primitives\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.primitives\4.3.0\ref\net46\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.primitives\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.primitives\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.primitives\4.3.0\system.security.cryptography.primitives.4.3.0.nupkg +system.security.cryptography.primitives\4.3.0\system.security.cryptography.primitives.4.3.0.nupkg.sha512 +system.security.cryptography.primitives\4.3.0\system.security.cryptography.primitives.nuspec +system.security.cryptography.primitives\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.x509certificates\4.1.0\dotnet_library_license.txt +system.security.cryptography.x509certificates\4.1.0\lib\MonoAndroid10\_._ +system.security.cryptography.x509certificates\4.1.0\lib\MonoTouch10\_._ +system.security.cryptography.x509certificates\4.1.0\lib\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\lib\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\lib\xamarinios10\_._ +system.security.cryptography.x509certificates\4.1.0\lib\xamarinmac20\_._ +system.security.cryptography.x509certificates\4.1.0\lib\xamarintvos10\_._ +system.security.cryptography.x509certificates\4.1.0\lib\xamarinwatchos10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\MonoAndroid10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\MonoTouch10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\ref\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\ref\netstandard1.3\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\ref\netstandard1.4\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\ref\xamarinios10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\xamarinmac20\_._ +system.security.cryptography.x509certificates\4.1.0\ref\xamarintvos10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\xamarinwatchos10\_._ +system.security.cryptography.x509certificates\4.1.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\runtimes\win\lib\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\runtimes\win\lib\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\runtimes\win\lib\netcore50\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\system.security.cryptography.x509certificates.4.1.0.nupkg +system.security.cryptography.x509certificates\4.1.0\system.security.cryptography.x509certificates.4.1.0.nupkg.sha512 +system.security.cryptography.x509certificates\4.1.0\system.security.cryptography.x509certificates.nuspec +system.security.cryptography.x509certificates\4.1.0\ThirdPartyNotices.txt +system.security.cryptography.x509certificates\4.3.0\dotnet_library_license.txt +system.security.cryptography.x509certificates\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.x509certificates\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.x509certificates\4.3.0\lib\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.x509certificates\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.x509certificates\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.x509certificates\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\ref\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\ref\netstandard1.3\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\ref\netstandard1.4\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.x509certificates\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.x509certificates\4.3.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\runtimes\win\lib\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\runtimes\win\lib\netcore50\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\system.security.cryptography.x509certificates.4.3.0.nupkg +system.security.cryptography.x509certificates\4.3.0\system.security.cryptography.x509certificates.4.3.0.nupkg.sha512 +system.security.cryptography.x509certificates\4.3.0\system.security.cryptography.x509certificates.nuspec +system.security.cryptography.x509certificates\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.xml\4.5.0\.signature.p7s +system.security.cryptography.xml\4.5.0\lib\net461\System.Security.Cryptography.Xml.dll +system.security.cryptography.xml\4.5.0\lib\netstandard2.0\System.Security.Cryptography.Xml.dll +system.security.cryptography.xml\4.5.0\LICENSE.TXT +system.security.cryptography.xml\4.5.0\ref\net461\System.Security.Cryptography.Xml.dll +system.security.cryptography.xml\4.5.0\ref\netstandard2.0\System.Security.Cryptography.Xml.dll +system.security.cryptography.xml\4.5.0\system.security.cryptography.xml.4.5.0.nupkg +system.security.cryptography.xml\4.5.0\system.security.cryptography.xml.4.5.0.nupkg.sha512 +system.security.cryptography.xml\4.5.0\system.security.cryptography.xml.nuspec +system.security.cryptography.xml\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.cryptography.xml\4.5.0\useSharedDesignerContext.txt +system.security.cryptography.xml\4.5.0\version.txt +system.security.permissions\4.5.0\.signature.p7s +system.security.permissions\4.5.0\lib\net461\System.Security.Permissions.dll +system.security.permissions\4.5.0\lib\netstandard2.0\System.Security.Permissions.dll +system.security.permissions\4.5.0\LICENSE.TXT +system.security.permissions\4.5.0\ref\net461\System.Security.Permissions.dll +system.security.permissions\4.5.0\ref\netstandard2.0\System.Security.Permissions.dll +system.security.permissions\4.5.0\system.security.permissions.4.5.0.nupkg +system.security.permissions\4.5.0\system.security.permissions.4.5.0.nupkg.sha512 +system.security.permissions\4.5.0\system.security.permissions.nuspec +system.security.permissions\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.permissions\4.5.0\useSharedDesignerContext.txt +system.security.permissions\4.5.0\version.txt +system.security.principal.windows\4.3.0\dotnet_library_license.txt +system.security.principal.windows\4.3.0\lib\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\ref\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\ref\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\runtimes\unix\lib\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\runtimes\win\lib\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\runtimes\win\lib\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\system.security.principal.windows.4.3.0.nupkg +system.security.principal.windows\4.3.0\system.security.principal.windows.4.3.0.nupkg.sha512 +system.security.principal.windows\4.3.0\system.security.principal.windows.nuspec +system.security.principal.windows\4.3.0\ThirdPartyNotices.txt +system.security.principal.windows\4.5.0\.signature.p7s +system.security.principal.windows\4.5.0\lib\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\lib\net461\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\lib\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\lib\netstandard2.0\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\lib\uap10.0.16299\_._ +system.security.principal.windows\4.5.0\LICENSE.TXT +system.security.principal.windows\4.5.0\ref\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\ref\net461\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\ref\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\ref\netstandard2.0\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\ref\uap10.0.16299\_._ +system.security.principal.windows\4.5.0\runtimes\unix\lib\netcoreapp2.0\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\net461\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\uap10.0.16299\_._ +system.security.principal.windows\4.5.0\system.security.principal.windows.4.5.0.nupkg +system.security.principal.windows\4.5.0\system.security.principal.windows.4.5.0.nupkg.sha512 +system.security.principal.windows\4.5.0\system.security.principal.windows.nuspec +system.security.principal.windows\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.principal.windows\4.5.0\useSharedDesignerContext.txt +system.security.principal.windows\4.5.0\version.txt +system.security.principal\4.3.0\dotnet_library_license.txt +system.security.principal\4.3.0\lib\MonoAndroid10\_._ +system.security.principal\4.3.0\lib\MonoTouch10\_._ +system.security.principal\4.3.0\lib\net45\_._ +system.security.principal\4.3.0\lib\netcore50\System.Security.Principal.dll +system.security.principal\4.3.0\lib\netstandard1.0\System.Security.Principal.dll +system.security.principal\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.security.principal\4.3.0\lib\win8\_._ +system.security.principal\4.3.0\lib\wp80\_._ +system.security.principal\4.3.0\lib\wpa81\_._ +system.security.principal\4.3.0\lib\xamarinios10\_._ +system.security.principal\4.3.0\lib\xamarinmac20\_._ +system.security.principal\4.3.0\lib\xamarintvos10\_._ +system.security.principal\4.3.0\lib\xamarinwatchos10\_._ +system.security.principal\4.3.0\ref\MonoAndroid10\_._ +system.security.principal\4.3.0\ref\MonoTouch10\_._ +system.security.principal\4.3.0\ref\net45\_._ +system.security.principal\4.3.0\ref\netcore50\System.Security.Principal.dll +system.security.principal\4.3.0\ref\netstandard1.0\System.Security.Principal.dll +system.security.principal\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.security.principal\4.3.0\ref\win8\_._ +system.security.principal\4.3.0\ref\wp80\_._ +system.security.principal\4.3.0\ref\wpa81\_._ +system.security.principal\4.3.0\ref\xamarinios10\_._ +system.security.principal\4.3.0\ref\xamarinmac20\_._ +system.security.principal\4.3.0\ref\xamarintvos10\_._ +system.security.principal\4.3.0\ref\xamarinwatchos10\_._ +system.security.principal\4.3.0\system.security.principal.4.3.0.nupkg +system.security.principal\4.3.0\system.security.principal.4.3.0.nupkg.sha512 +system.security.principal\4.3.0\system.security.principal.nuspec +system.security.principal\4.3.0\ThirdPartyNotices.txt +system.spatial\5.8.2\lib\net40\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\System.Spatial.dll +system.spatial\5.8.2\lib\net40\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\System.Spatial.dll +system.spatial\5.8.2\lib\netstandard1.1\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\System.Spatial.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\System.Spatial.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\System.Spatial.dll +system.spatial\5.8.2\lib\sl4\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\system.spatial.5.8.2.nupkg +system.spatial\5.8.2\system.spatial.5.8.2.nupkg.sha512 +system.spatial\5.8.2\system.spatial.nuspec +system.text.encoding.codepages\4.3.0\dotnet_library_license.txt +system.text.encoding.codepages\4.3.0\lib\MonoAndroid10\_._ +system.text.encoding.codepages\4.3.0\lib\MonoTouch10\_._ +system.text.encoding.codepages\4.3.0\lib\net46\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.3.0\lib\xamarinios10\_._ +system.text.encoding.codepages\4.3.0\lib\xamarinmac20\_._ +system.text.encoding.codepages\4.3.0\lib\xamarintvos10\_._ +system.text.encoding.codepages\4.3.0\lib\xamarinwatchos10\_._ +system.text.encoding.codepages\4.3.0\ref\MonoAndroid10\_._ +system.text.encoding.codepages\4.3.0\ref\MonoTouch10\_._ +system.text.encoding.codepages\4.3.0\ref\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.3.0\ref\xamarinios10\_._ +system.text.encoding.codepages\4.3.0\ref\xamarinmac20\_._ +system.text.encoding.codepages\4.3.0\ref\xamarintvos10\_._ +system.text.encoding.codepages\4.3.0\ref\xamarinwatchos10\_._ +system.text.encoding.codepages\4.3.0\runtimes\unix\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.3.0\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.3.0\system.text.encoding.codepages.4.3.0.nupkg +system.text.encoding.codepages\4.3.0\system.text.encoding.codepages.4.3.0.nupkg.sha512 +system.text.encoding.codepages\4.3.0\system.text.encoding.codepages.nuspec +system.text.encoding.codepages\4.3.0\ThirdPartyNotices.txt +system.text.encoding.codepages\4.5.0\.signature.p7s +system.text.encoding.codepages\4.5.0\lib\MonoAndroid10\_._ +system.text.encoding.codepages\4.5.0\lib\MonoTouch10\_._ +system.text.encoding.codepages\4.5.0\lib\net46\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\lib\net461\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\lib\netstandard2.0\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\lib\xamarinios10\_._ +system.text.encoding.codepages\4.5.0\lib\xamarinmac20\_._ +system.text.encoding.codepages\4.5.0\lib\xamarintvos10\_._ +system.text.encoding.codepages\4.5.0\lib\xamarinwatchos10\_._ +system.text.encoding.codepages\4.5.0\LICENSE.TXT +system.text.encoding.codepages\4.5.0\ref\MonoAndroid10\_._ +system.text.encoding.codepages\4.5.0\ref\MonoTouch10\_._ +system.text.encoding.codepages\4.5.0\ref\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\ref\netstandard2.0\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\ref\xamarinios10\_._ +system.text.encoding.codepages\4.5.0\ref\xamarinmac20\_._ +system.text.encoding.codepages\4.5.0\ref\xamarintvos10\_._ +system.text.encoding.codepages\4.5.0\ref\xamarinwatchos10\_._ +system.text.encoding.codepages\4.5.0\runtimes\win\lib\net461\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\runtimes\win\lib\netstandard2.0\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\system.text.encoding.codepages.4.5.0.nupkg +system.text.encoding.codepages\4.5.0\system.text.encoding.codepages.4.5.0.nupkg.sha512 +system.text.encoding.codepages\4.5.0\system.text.encoding.codepages.nuspec +system.text.encoding.codepages\4.5.0\THIRD-PARTY-NOTICES.TXT +system.text.encoding.codepages\4.5.0\useSharedDesignerContext.txt +system.text.encoding.codepages\4.5.0\version.txt +system.text.encoding.extensions\4.0.11\dotnet_library_license.txt +system.text.encoding.extensions\4.0.11\lib\MonoAndroid10\_._ +system.text.encoding.extensions\4.0.11\lib\MonoTouch10\_._ +system.text.encoding.extensions\4.0.11\lib\net45\_._ +system.text.encoding.extensions\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding.extensions\4.0.11\lib\win8\_._ +system.text.encoding.extensions\4.0.11\lib\wp80\_._ +system.text.encoding.extensions\4.0.11\lib\wpa81\_._ +system.text.encoding.extensions\4.0.11\lib\xamarinios10\_._ +system.text.encoding.extensions\4.0.11\lib\xamarinmac20\_._ +system.text.encoding.extensions\4.0.11\lib\xamarintvos10\_._ +system.text.encoding.extensions\4.0.11\lib\xamarinwatchos10\_._ +system.text.encoding.extensions\4.0.11\ref\MonoAndroid10\_._ +system.text.encoding.extensions\4.0.11\ref\MonoTouch10\_._ +system.text.encoding.extensions\4.0.11\ref\net45\_._ +system.text.encoding.extensions\4.0.11\ref\netcore50\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.0.11\ref\netstandard1.0\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.0.11\ref\netstandard1.3\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding.extensions\4.0.11\ref\win8\_._ +system.text.encoding.extensions\4.0.11\ref\wp80\_._ +system.text.encoding.extensions\4.0.11\ref\wpa81\_._ +system.text.encoding.extensions\4.0.11\ref\xamarinios10\_._ +system.text.encoding.extensions\4.0.11\ref\xamarinmac20\_._ +system.text.encoding.extensions\4.0.11\ref\xamarintvos10\_._ +system.text.encoding.extensions\4.0.11\ref\xamarinwatchos10\_._ +system.text.encoding.extensions\4.0.11\system.text.encoding.extensions.4.0.11.nupkg +system.text.encoding.extensions\4.0.11\system.text.encoding.extensions.4.0.11.nupkg.sha512 +system.text.encoding.extensions\4.0.11\system.text.encoding.extensions.nuspec +system.text.encoding.extensions\4.0.11\ThirdPartyNotices.txt +system.text.encoding.extensions\4.3.0\dotnet_library_license.txt +system.text.encoding.extensions\4.3.0\lib\MonoAndroid10\_._ +system.text.encoding.extensions\4.3.0\lib\MonoTouch10\_._ +system.text.encoding.extensions\4.3.0\lib\net45\_._ +system.text.encoding.extensions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding.extensions\4.3.0\lib\win8\_._ +system.text.encoding.extensions\4.3.0\lib\wp80\_._ +system.text.encoding.extensions\4.3.0\lib\wpa81\_._ +system.text.encoding.extensions\4.3.0\lib\xamarinios10\_._ +system.text.encoding.extensions\4.3.0\lib\xamarinmac20\_._ +system.text.encoding.extensions\4.3.0\lib\xamarintvos10\_._ +system.text.encoding.extensions\4.3.0\lib\xamarinwatchos10\_._ +system.text.encoding.extensions\4.3.0\ref\MonoAndroid10\_._ +system.text.encoding.extensions\4.3.0\ref\MonoTouch10\_._ +system.text.encoding.extensions\4.3.0\ref\net45\_._ +system.text.encoding.extensions\4.3.0\ref\netcore50\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.3.0\ref\netstandard1.0\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.3.0\ref\netstandard1.3\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding.extensions\4.3.0\ref\win8\_._ +system.text.encoding.extensions\4.3.0\ref\wp80\_._ +system.text.encoding.extensions\4.3.0\ref\wpa81\_._ +system.text.encoding.extensions\4.3.0\ref\xamarinios10\_._ +system.text.encoding.extensions\4.3.0\ref\xamarinmac20\_._ +system.text.encoding.extensions\4.3.0\ref\xamarintvos10\_._ +system.text.encoding.extensions\4.3.0\ref\xamarinwatchos10\_._ +system.text.encoding.extensions\4.3.0\system.text.encoding.extensions.4.3.0.nupkg +system.text.encoding.extensions\4.3.0\system.text.encoding.extensions.4.3.0.nupkg.sha512 +system.text.encoding.extensions\4.3.0\system.text.encoding.extensions.nuspec +system.text.encoding.extensions\4.3.0\ThirdPartyNotices.txt +system.text.encoding\4.0.11\dotnet_library_license.txt +system.text.encoding\4.0.11\lib\MonoAndroid10\_._ +system.text.encoding\4.0.11\lib\MonoTouch10\_._ +system.text.encoding\4.0.11\lib\net45\_._ +system.text.encoding\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding\4.0.11\lib\win8\_._ +system.text.encoding\4.0.11\lib\wp80\_._ +system.text.encoding\4.0.11\lib\wpa81\_._ +system.text.encoding\4.0.11\lib\xamarinios10\_._ +system.text.encoding\4.0.11\lib\xamarinmac20\_._ +system.text.encoding\4.0.11\lib\xamarintvos10\_._ +system.text.encoding\4.0.11\lib\xamarinwatchos10\_._ +system.text.encoding\4.0.11\ref\MonoAndroid10\_._ +system.text.encoding\4.0.11\ref\MonoTouch10\_._ +system.text.encoding\4.0.11\ref\net45\_._ +system.text.encoding\4.0.11\ref\netcore50\System.Text.Encoding.dll +system.text.encoding\4.0.11\ref\netstandard1.0\System.Text.Encoding.dll +system.text.encoding\4.0.11\ref\netstandard1.3\System.Text.Encoding.dll +system.text.encoding\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding\4.0.11\ref\win8\_._ +system.text.encoding\4.0.11\ref\wp80\_._ +system.text.encoding\4.0.11\ref\wpa81\_._ +system.text.encoding\4.0.11\ref\xamarinios10\_._ +system.text.encoding\4.0.11\ref\xamarinmac20\_._ +system.text.encoding\4.0.11\ref\xamarintvos10\_._ +system.text.encoding\4.0.11\ref\xamarinwatchos10\_._ +system.text.encoding\4.0.11\system.text.encoding.4.0.11.nupkg +system.text.encoding\4.0.11\system.text.encoding.4.0.11.nupkg.sha512 +system.text.encoding\4.0.11\system.text.encoding.nuspec +system.text.encoding\4.0.11\ThirdPartyNotices.txt +system.text.encoding\4.3.0\dotnet_library_license.txt +system.text.encoding\4.3.0\lib\MonoAndroid10\_._ +system.text.encoding\4.3.0\lib\MonoTouch10\_._ +system.text.encoding\4.3.0\lib\net45\_._ +system.text.encoding\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding\4.3.0\lib\win8\_._ +system.text.encoding\4.3.0\lib\wp80\_._ +system.text.encoding\4.3.0\lib\wpa81\_._ +system.text.encoding\4.3.0\lib\xamarinios10\_._ +system.text.encoding\4.3.0\lib\xamarinmac20\_._ +system.text.encoding\4.3.0\lib\xamarintvos10\_._ +system.text.encoding\4.3.0\lib\xamarinwatchos10\_._ +system.text.encoding\4.3.0\ref\MonoAndroid10\_._ +system.text.encoding\4.3.0\ref\MonoTouch10\_._ +system.text.encoding\4.3.0\ref\net45\_._ +system.text.encoding\4.3.0\ref\netcore50\System.Text.Encoding.dll +system.text.encoding\4.3.0\ref\netstandard1.0\System.Text.Encoding.dll +system.text.encoding\4.3.0\ref\netstandard1.3\System.Text.Encoding.dll +system.text.encoding\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding\4.3.0\ref\win8\_._ +system.text.encoding\4.3.0\ref\wp80\_._ +system.text.encoding\4.3.0\ref\wpa81\_._ +system.text.encoding\4.3.0\ref\xamarinios10\_._ +system.text.encoding\4.3.0\ref\xamarinmac20\_._ +system.text.encoding\4.3.0\ref\xamarintvos10\_._ +system.text.encoding\4.3.0\ref\xamarinwatchos10\_._ +system.text.encoding\4.3.0\system.text.encoding.4.3.0.nupkg +system.text.encoding\4.3.0\system.text.encoding.4.3.0.nupkg.sha512 +system.text.encoding\4.3.0\system.text.encoding.nuspec +system.text.encoding\4.3.0\ThirdPartyNotices.txt +system.text.encodings.web\4.3.1\dotnet_library_license.txt +system.text.encodings.web\4.3.1\lib\netstandard1.0\System.Text.Encodings.Web.dll +system.text.encodings.web\4.3.1\system.text.encodings.web.4.3.1.nupkg +system.text.encodings.web\4.3.1\system.text.encodings.web.4.3.1.nupkg.sha512 +system.text.encodings.web\4.3.1\system.text.encodings.web.nuspec +system.text.encodings.web\4.3.1\ThirdPartyNotices.txt +system.text.encodings.web\4.5.0\.signature.p7s +system.text.encodings.web\4.5.0\lib\netstandard1.0\System.Text.Encodings.Web.dll +system.text.encodings.web\4.5.0\lib\netstandard2.0\System.Text.Encodings.Web.dll +system.text.encodings.web\4.5.0\LICENSE.TXT +system.text.encodings.web\4.5.0\system.text.encodings.web.4.5.0.nupkg +system.text.encodings.web\4.5.0\system.text.encodings.web.4.5.0.nupkg.sha512 +system.text.encodings.web\4.5.0\system.text.encodings.web.nuspec +system.text.encodings.web\4.5.0\THIRD-PARTY-NOTICES.TXT +system.text.encodings.web\4.5.0\useSharedDesignerContext.txt +system.text.encodings.web\4.5.0\version.txt +system.text.regularexpressions\4.1.0\dotnet_library_license.txt +system.text.regularexpressions\4.1.0\lib\MonoAndroid10\_._ +system.text.regularexpressions\4.1.0\lib\MonoTouch10\_._ +system.text.regularexpressions\4.1.0\lib\net45\_._ +system.text.regularexpressions\4.1.0\lib\net463\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\lib\netcore50\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\lib\netstandard1.6\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.regularexpressions\4.1.0\lib\win8\_._ +system.text.regularexpressions\4.1.0\lib\wp80\_._ +system.text.regularexpressions\4.1.0\lib\wpa81\_._ +system.text.regularexpressions\4.1.0\lib\xamarinios10\_._ +system.text.regularexpressions\4.1.0\lib\xamarinmac20\_._ +system.text.regularexpressions\4.1.0\lib\xamarintvos10\_._ +system.text.regularexpressions\4.1.0\lib\xamarinwatchos10\_._ +system.text.regularexpressions\4.1.0\ref\MonoAndroid10\_._ +system.text.regularexpressions\4.1.0\ref\MonoTouch10\_._ +system.text.regularexpressions\4.1.0\ref\net45\_._ +system.text.regularexpressions\4.1.0\ref\net463\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\netcore50\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\netstandard1.0\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\netstandard1.3\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\netstandard1.6\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.regularexpressions\4.1.0\ref\win8\_._ +system.text.regularexpressions\4.1.0\ref\wp80\_._ +system.text.regularexpressions\4.1.0\ref\wpa81\_._ +system.text.regularexpressions\4.1.0\ref\xamarinios10\_._ +system.text.regularexpressions\4.1.0\ref\xamarinmac20\_._ +system.text.regularexpressions\4.1.0\ref\xamarintvos10\_._ +system.text.regularexpressions\4.1.0\ref\xamarinwatchos10\_._ +system.text.regularexpressions\4.1.0\system.text.regularexpressions.4.1.0.nupkg +system.text.regularexpressions\4.1.0\system.text.regularexpressions.4.1.0.nupkg.sha512 +system.text.regularexpressions\4.1.0\system.text.regularexpressions.nuspec +system.text.regularexpressions\4.1.0\ThirdPartyNotices.txt +system.text.regularexpressions\4.3.0\dotnet_library_license.txt +system.text.regularexpressions\4.3.0\lib\MonoAndroid10\_._ +system.text.regularexpressions\4.3.0\lib\MonoTouch10\_._ +system.text.regularexpressions\4.3.0\lib\net45\_._ +system.text.regularexpressions\4.3.0\lib\net463\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\lib\netcore50\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\lib\netstandard1.6\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.regularexpressions\4.3.0\lib\win8\_._ +system.text.regularexpressions\4.3.0\lib\wp80\_._ +system.text.regularexpressions\4.3.0\lib\wpa81\_._ +system.text.regularexpressions\4.3.0\lib\xamarinios10\_._ +system.text.regularexpressions\4.3.0\lib\xamarinmac20\_._ +system.text.regularexpressions\4.3.0\lib\xamarintvos10\_._ +system.text.regularexpressions\4.3.0\lib\xamarinwatchos10\_._ +system.text.regularexpressions\4.3.0\ref\MonoAndroid10\_._ +system.text.regularexpressions\4.3.0\ref\MonoTouch10\_._ +system.text.regularexpressions\4.3.0\ref\net45\_._ +system.text.regularexpressions\4.3.0\ref\net463\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netcore50\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netcoreapp1.1\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netstandard1.0\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netstandard1.3\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netstandard1.6\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.regularexpressions\4.3.0\ref\win8\_._ +system.text.regularexpressions\4.3.0\ref\wp80\_._ +system.text.regularexpressions\4.3.0\ref\wpa81\_._ +system.text.regularexpressions\4.3.0\ref\xamarinios10\_._ +system.text.regularexpressions\4.3.0\ref\xamarinmac20\_._ +system.text.regularexpressions\4.3.0\ref\xamarintvos10\_._ +system.text.regularexpressions\4.3.0\ref\xamarinwatchos10\_._ +system.text.regularexpressions\4.3.0\system.text.regularexpressions.4.3.0.nupkg +system.text.regularexpressions\4.3.0\system.text.regularexpressions.4.3.0.nupkg.sha512 +system.text.regularexpressions\4.3.0\system.text.regularexpressions.nuspec +system.text.regularexpressions\4.3.0\ThirdPartyNotices.txt +system.threading.channels\4.5.0\.signature.p7s +system.threading.channels\4.5.0\lib\netcoreapp2.1\System.Threading.Channels.dll +system.threading.channels\4.5.0\lib\netstandard1.3\System.Threading.Channels.dll +system.threading.channels\4.5.0\lib\netstandard2.0\System.Threading.Channels.dll +system.threading.channels\4.5.0\LICENSE.TXT +system.threading.channels\4.5.0\system.threading.channels.4.5.0.nupkg +system.threading.channels\4.5.0\system.threading.channels.4.5.0.nupkg.sha512 +system.threading.channels\4.5.0\system.threading.channels.nuspec +system.threading.channels\4.5.0\THIRD-PARTY-NOTICES.TXT +system.threading.channels\4.5.0\useSharedDesignerContext.txt +system.threading.channels\4.5.0\version.txt +system.threading.tasks.extensions\4.0.0\dotnet_library_license.txt +system.threading.tasks.extensions\4.0.0\lib\netstandard1.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.0.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.0.0\system.threading.tasks.extensions.4.0.0.nupkg +system.threading.tasks.extensions\4.0.0\system.threading.tasks.extensions.4.0.0.nupkg.sha512 +system.threading.tasks.extensions\4.0.0\system.threading.tasks.extensions.nuspec +system.threading.tasks.extensions\4.0.0\ThirdPartyNotices.txt +system.threading.tasks.extensions\4.3.0\dotnet_library_license.txt +system.threading.tasks.extensions\4.3.0\lib\netstandard1.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.3.0\system.threading.tasks.extensions.4.3.0.nupkg +system.threading.tasks.extensions\4.3.0\system.threading.tasks.extensions.4.3.0.nupkg.sha512 +system.threading.tasks.extensions\4.3.0\system.threading.tasks.extensions.nuspec +system.threading.tasks.extensions\4.3.0\ThirdPartyNotices.txt +system.threading.tasks.extensions\4.5.1\.signature.p7s +system.threading.tasks.extensions\4.5.1\lib\MonoAndroid10\_._ +system.threading.tasks.extensions\4.5.1\lib\MonoTouch10\_._ +system.threading.tasks.extensions\4.5.1\lib\netcoreapp2.1\_._ +system.threading.tasks.extensions\4.5.1\lib\netstandard1.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\lib\xamarinios10\_._ +system.threading.tasks.extensions\4.5.1\lib\xamarinmac20\_._ +system.threading.tasks.extensions\4.5.1\lib\xamarintvos10\_._ +system.threading.tasks.extensions\4.5.1\lib\xamarinwatchos10\_._ +system.threading.tasks.extensions\4.5.1\LICENSE.TXT +system.threading.tasks.extensions\4.5.1\ref\MonoAndroid10\_._ +system.threading.tasks.extensions\4.5.1\ref\MonoTouch10\_._ +system.threading.tasks.extensions\4.5.1\ref\netcoreapp2.1\_._ +system.threading.tasks.extensions\4.5.1\ref\netstandard1.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\ref\netstandard2.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\ref\xamarinios10\_._ +system.threading.tasks.extensions\4.5.1\ref\xamarinmac20\_._ +system.threading.tasks.extensions\4.5.1\ref\xamarintvos10\_._ +system.threading.tasks.extensions\4.5.1\ref\xamarinwatchos10\_._ +system.threading.tasks.extensions\4.5.1\system.threading.tasks.extensions.4.5.1.nupkg +system.threading.tasks.extensions\4.5.1\system.threading.tasks.extensions.4.5.1.nupkg.sha512 +system.threading.tasks.extensions\4.5.1\system.threading.tasks.extensions.nuspec +system.threading.tasks.extensions\4.5.1\THIRD-PARTY-NOTICES.TXT +system.threading.tasks.extensions\4.5.1\useSharedDesignerContext.txt +system.threading.tasks.extensions\4.5.1\version.txt +system.threading.tasks.parallel\4.3.0\dotnet_library_license.txt +system.threading.tasks.parallel\4.3.0\lib\MonoAndroid10\_._ +system.threading.tasks.parallel\4.3.0\lib\MonoTouch10\_._ +system.threading.tasks.parallel\4.3.0\lib\net45\_._ +system.threading.tasks.parallel\4.3.0\lib\netcore50\System.Threading.Tasks.Parallel.dll +system.threading.tasks.parallel\4.3.0\lib\netstandard1.3\System.Threading.Tasks.Parallel.dll +system.threading.tasks.parallel\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.threading.tasks.parallel\4.3.0\lib\win8\_._ +system.threading.tasks.parallel\4.3.0\lib\wpa81\_._ +system.threading.tasks.parallel\4.3.0\lib\xamarinios10\_._ +system.threading.tasks.parallel\4.3.0\lib\xamarinmac20\_._ +system.threading.tasks.parallel\4.3.0\lib\xamarintvos10\_._ +system.threading.tasks.parallel\4.3.0\lib\xamarinwatchos10\_._ +system.threading.tasks.parallel\4.3.0\ref\MonoAndroid10\_._ +system.threading.tasks.parallel\4.3.0\ref\MonoTouch10\_._ +system.threading.tasks.parallel\4.3.0\ref\net45\_._ +system.threading.tasks.parallel\4.3.0\ref\netcore50\System.Threading.Tasks.Parallel.dll +system.threading.tasks.parallel\4.3.0\ref\netstandard1.1\System.Threading.Tasks.Parallel.dll +system.threading.tasks.parallel\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.threading.tasks.parallel\4.3.0\ref\win8\_._ +system.threading.tasks.parallel\4.3.0\ref\wpa81\_._ +system.threading.tasks.parallel\4.3.0\ref\xamarinios10\_._ +system.threading.tasks.parallel\4.3.0\ref\xamarinmac20\_._ +system.threading.tasks.parallel\4.3.0\ref\xamarintvos10\_._ +system.threading.tasks.parallel\4.3.0\ref\xamarinwatchos10\_._ +system.threading.tasks.parallel\4.3.0\system.threading.tasks.parallel.4.3.0.nupkg +system.threading.tasks.parallel\4.3.0\system.threading.tasks.parallel.4.3.0.nupkg.sha512 +system.threading.tasks.parallel\4.3.0\system.threading.tasks.parallel.nuspec +system.threading.tasks.parallel\4.3.0\ThirdPartyNotices.txt +system.threading.tasks\4.0.11\dotnet_library_license.txt +system.threading.tasks\4.0.11\lib\MonoAndroid10\_._ +system.threading.tasks\4.0.11\lib\MonoTouch10\_._ +system.threading.tasks\4.0.11\lib\net45\_._ +system.threading.tasks\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.threading.tasks\4.0.11\lib\win8\_._ +system.threading.tasks\4.0.11\lib\wp80\_._ +system.threading.tasks\4.0.11\lib\wpa81\_._ +system.threading.tasks\4.0.11\lib\xamarinios10\_._ +system.threading.tasks\4.0.11\lib\xamarinmac20\_._ +system.threading.tasks\4.0.11\lib\xamarintvos10\_._ +system.threading.tasks\4.0.11\lib\xamarinwatchos10\_._ +system.threading.tasks\4.0.11\ref\MonoAndroid10\_._ +system.threading.tasks\4.0.11\ref\MonoTouch10\_._ +system.threading.tasks\4.0.11\ref\net45\_._ +system.threading.tasks\4.0.11\ref\netcore50\System.Threading.Tasks.dll +system.threading.tasks\4.0.11\ref\netstandard1.0\System.Threading.Tasks.dll +system.threading.tasks\4.0.11\ref\netstandard1.3\System.Threading.Tasks.dll +system.threading.tasks\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.threading.tasks\4.0.11\ref\win8\_._ +system.threading.tasks\4.0.11\ref\wp80\_._ +system.threading.tasks\4.0.11\ref\wpa81\_._ +system.threading.tasks\4.0.11\ref\xamarinios10\_._ +system.threading.tasks\4.0.11\ref\xamarinmac20\_._ +system.threading.tasks\4.0.11\ref\xamarintvos10\_._ +system.threading.tasks\4.0.11\ref\xamarinwatchos10\_._ +system.threading.tasks\4.0.11\system.threading.tasks.4.0.11.nupkg +system.threading.tasks\4.0.11\system.threading.tasks.4.0.11.nupkg.sha512 +system.threading.tasks\4.0.11\system.threading.tasks.nuspec +system.threading.tasks\4.0.11\ThirdPartyNotices.txt +system.threading.tasks\4.3.0\dotnet_library_license.txt +system.threading.tasks\4.3.0\lib\MonoAndroid10\_._ +system.threading.tasks\4.3.0\lib\MonoTouch10\_._ +system.threading.tasks\4.3.0\lib\net45\_._ +system.threading.tasks\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.threading.tasks\4.3.0\lib\win8\_._ +system.threading.tasks\4.3.0\lib\wp80\_._ +system.threading.tasks\4.3.0\lib\wpa81\_._ +system.threading.tasks\4.3.0\lib\xamarinios10\_._ +system.threading.tasks\4.3.0\lib\xamarinmac20\_._ +system.threading.tasks\4.3.0\lib\xamarintvos10\_._ +system.threading.tasks\4.3.0\lib\xamarinwatchos10\_._ +system.threading.tasks\4.3.0\ref\MonoAndroid10\_._ +system.threading.tasks\4.3.0\ref\MonoTouch10\_._ +system.threading.tasks\4.3.0\ref\net45\_._ +system.threading.tasks\4.3.0\ref\netcore50\System.Threading.Tasks.dll +system.threading.tasks\4.3.0\ref\netstandard1.0\System.Threading.Tasks.dll +system.threading.tasks\4.3.0\ref\netstandard1.3\System.Threading.Tasks.dll +system.threading.tasks\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.threading.tasks\4.3.0\ref\win8\_._ +system.threading.tasks\4.3.0\ref\wp80\_._ +system.threading.tasks\4.3.0\ref\wpa81\_._ +system.threading.tasks\4.3.0\ref\xamarinios10\_._ +system.threading.tasks\4.3.0\ref\xamarinmac20\_._ +system.threading.tasks\4.3.0\ref\xamarintvos10\_._ +system.threading.tasks\4.3.0\ref\xamarinwatchos10\_._ +system.threading.tasks\4.3.0\system.threading.tasks.4.3.0.nupkg +system.threading.tasks\4.3.0\system.threading.tasks.4.3.0.nupkg.sha512 +system.threading.tasks\4.3.0\system.threading.tasks.nuspec +system.threading.tasks\4.3.0\ThirdPartyNotices.txt +system.threading.thread\4.3.0\dotnet_library_license.txt +system.threading.thread\4.3.0\lib\MonoAndroid10\_._ +system.threading.thread\4.3.0\lib\MonoTouch10\_._ +system.threading.thread\4.3.0\lib\net46\System.Threading.Thread.dll +system.threading.thread\4.3.0\lib\netcore50\_._ +system.threading.thread\4.3.0\lib\netstandard1.3\System.Threading.Thread.dll +system.threading.thread\4.3.0\lib\xamarinios10\_._ +system.threading.thread\4.3.0\lib\xamarinmac20\_._ +system.threading.thread\4.3.0\lib\xamarintvos10\_._ +system.threading.thread\4.3.0\lib\xamarinwatchos10\_._ +system.threading.thread\4.3.0\ref\MonoAndroid10\_._ +system.threading.thread\4.3.0\ref\MonoTouch10\_._ +system.threading.thread\4.3.0\ref\net46\System.Threading.Thread.dll +system.threading.thread\4.3.0\ref\netstandard1.3\System.Threading.Thread.dll +system.threading.thread\4.3.0\ref\xamarinios10\_._ +system.threading.thread\4.3.0\ref\xamarinmac20\_._ +system.threading.thread\4.3.0\ref\xamarintvos10\_._ +system.threading.thread\4.3.0\ref\xamarinwatchos10\_._ +system.threading.thread\4.3.0\system.threading.thread.4.3.0.nupkg +system.threading.thread\4.3.0\system.threading.thread.4.3.0.nupkg.sha512 +system.threading.thread\4.3.0\system.threading.thread.nuspec +system.threading.thread\4.3.0\ThirdPartyNotices.txt +system.threading.threadpool\4.3.0\dotnet_library_license.txt +system.threading.threadpool\4.3.0\lib\MonoAndroid10\_._ +system.threading.threadpool\4.3.0\lib\MonoTouch10\_._ +system.threading.threadpool\4.3.0\lib\net46\System.Threading.ThreadPool.dll +system.threading.threadpool\4.3.0\lib\netcore50\_._ +system.threading.threadpool\4.3.0\lib\netstandard1.3\System.Threading.ThreadPool.dll +system.threading.threadpool\4.3.0\lib\xamarinios10\_._ +system.threading.threadpool\4.3.0\lib\xamarinmac20\_._ +system.threading.threadpool\4.3.0\lib\xamarintvos10\_._ +system.threading.threadpool\4.3.0\lib\xamarinwatchos10\_._ +system.threading.threadpool\4.3.0\ref\MonoAndroid10\_._ +system.threading.threadpool\4.3.0\ref\MonoTouch10\_._ +system.threading.threadpool\4.3.0\ref\net46\System.Threading.ThreadPool.dll +system.threading.threadpool\4.3.0\ref\netstandard1.3\System.Threading.ThreadPool.dll +system.threading.threadpool\4.3.0\ref\xamarinios10\_._ +system.threading.threadpool\4.3.0\ref\xamarinmac20\_._ +system.threading.threadpool\4.3.0\ref\xamarintvos10\_._ +system.threading.threadpool\4.3.0\ref\xamarinwatchos10\_._ +system.threading.threadpool\4.3.0\system.threading.threadpool.4.3.0.nupkg +system.threading.threadpool\4.3.0\system.threading.threadpool.4.3.0.nupkg.sha512 +system.threading.threadpool\4.3.0\system.threading.threadpool.nuspec +system.threading.threadpool\4.3.0\ThirdPartyNotices.txt +system.threading.timer\4.0.1\dotnet_library_license.txt +system.threading.timer\4.0.1\lib\MonoAndroid10\_._ +system.threading.timer\4.0.1\lib\MonoTouch10\_._ +system.threading.timer\4.0.1\lib\net451\_._ +system.threading.timer\4.0.1\lib\portable-net451+win81+wpa81\_._ +system.threading.timer\4.0.1\lib\win81\_._ +system.threading.timer\4.0.1\lib\wpa81\_._ +system.threading.timer\4.0.1\lib\xamarinios10\_._ +system.threading.timer\4.0.1\lib\xamarinmac20\_._ +system.threading.timer\4.0.1\lib\xamarintvos10\_._ +system.threading.timer\4.0.1\lib\xamarinwatchos10\_._ +system.threading.timer\4.0.1\ref\MonoAndroid10\_._ +system.threading.timer\4.0.1\ref\MonoTouch10\_._ +system.threading.timer\4.0.1\ref\net451\_._ +system.threading.timer\4.0.1\ref\netcore50\System.Threading.Timer.dll +system.threading.timer\4.0.1\ref\netstandard1.2\System.Threading.Timer.dll +system.threading.timer\4.0.1\ref\portable-net451+win81+wpa81\_._ +system.threading.timer\4.0.1\ref\win81\_._ +system.threading.timer\4.0.1\ref\wpa81\_._ +system.threading.timer\4.0.1\ref\xamarinios10\_._ +system.threading.timer\4.0.1\ref\xamarinmac20\_._ +system.threading.timer\4.0.1\ref\xamarintvos10\_._ +system.threading.timer\4.0.1\ref\xamarinwatchos10\_._ +system.threading.timer\4.0.1\system.threading.timer.4.0.1.nupkg +system.threading.timer\4.0.1\system.threading.timer.4.0.1.nupkg.sha512 +system.threading.timer\4.0.1\system.threading.timer.nuspec +system.threading.timer\4.0.1\ThirdPartyNotices.txt +system.threading.timer\4.3.0\dotnet_library_license.txt +system.threading.timer\4.3.0\lib\MonoAndroid10\_._ +system.threading.timer\4.3.0\lib\MonoTouch10\_._ +system.threading.timer\4.3.0\lib\net451\_._ +system.threading.timer\4.3.0\lib\portable-net451+win81+wpa81\_._ +system.threading.timer\4.3.0\lib\win81\_._ +system.threading.timer\4.3.0\lib\wpa81\_._ +system.threading.timer\4.3.0\lib\xamarinios10\_._ +system.threading.timer\4.3.0\lib\xamarinmac20\_._ +system.threading.timer\4.3.0\lib\xamarintvos10\_._ +system.threading.timer\4.3.0\lib\xamarinwatchos10\_._ +system.threading.timer\4.3.0\ref\MonoAndroid10\_._ +system.threading.timer\4.3.0\ref\MonoTouch10\_._ +system.threading.timer\4.3.0\ref\net451\_._ +system.threading.timer\4.3.0\ref\netcore50\System.Threading.Timer.dll +system.threading.timer\4.3.0\ref\netstandard1.2\System.Threading.Timer.dll +system.threading.timer\4.3.0\ref\portable-net451+win81+wpa81\_._ +system.threading.timer\4.3.0\ref\win81\_._ +system.threading.timer\4.3.0\ref\wpa81\_._ +system.threading.timer\4.3.0\ref\xamarinios10\_._ +system.threading.timer\4.3.0\ref\xamarinmac20\_._ +system.threading.timer\4.3.0\ref\xamarintvos10\_._ +system.threading.timer\4.3.0\ref\xamarinwatchos10\_._ +system.threading.timer\4.3.0\system.threading.timer.4.3.0.nupkg +system.threading.timer\4.3.0\system.threading.timer.4.3.0.nupkg.sha512 +system.threading.timer\4.3.0\system.threading.timer.nuspec +system.threading.timer\4.3.0\ThirdPartyNotices.txt +system.threading\4.0.11\dotnet_library_license.txt +system.threading\4.0.11\lib\MonoAndroid10\_._ +system.threading\4.0.11\lib\MonoTouch10\_._ +system.threading\4.0.11\lib\net45\_._ +system.threading\4.0.11\lib\netcore50\System.Threading.dll +system.threading\4.0.11\lib\netstandard1.3\System.Threading.dll +system.threading\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.threading\4.0.11\lib\win8\_._ +system.threading\4.0.11\lib\wp80\_._ +system.threading\4.0.11\lib\wpa81\_._ +system.threading\4.0.11\lib\xamarinios10\_._ +system.threading\4.0.11\lib\xamarinmac20\_._ +system.threading\4.0.11\lib\xamarintvos10\_._ +system.threading\4.0.11\lib\xamarinwatchos10\_._ +system.threading\4.0.11\ref\MonoAndroid10\_._ +system.threading\4.0.11\ref\MonoTouch10\_._ +system.threading\4.0.11\ref\net45\_._ +system.threading\4.0.11\ref\netcore50\System.Threading.dll +system.threading\4.0.11\ref\netstandard1.0\System.Threading.dll +system.threading\4.0.11\ref\netstandard1.3\System.Threading.dll +system.threading\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.threading\4.0.11\ref\win8\_._ +system.threading\4.0.11\ref\wp80\_._ +system.threading\4.0.11\ref\wpa81\_._ +system.threading\4.0.11\ref\xamarinios10\_._ +system.threading\4.0.11\ref\xamarinmac20\_._ +system.threading\4.0.11\ref\xamarintvos10\_._ +system.threading\4.0.11\ref\xamarinwatchos10\_._ +system.threading\4.0.11\runtimes\aot\lib\netcore50\System.Threading.dll +system.threading\4.0.11\system.threading.4.0.11.nupkg +system.threading\4.0.11\system.threading.4.0.11.nupkg.sha512 +system.threading\4.0.11\system.threading.nuspec +system.threading\4.0.11\ThirdPartyNotices.txt +system.threading\4.3.0\dotnet_library_license.txt +system.threading\4.3.0\lib\MonoAndroid10\_._ +system.threading\4.3.0\lib\MonoTouch10\_._ +system.threading\4.3.0\lib\net45\_._ +system.threading\4.3.0\lib\netcore50\System.Threading.dll +system.threading\4.3.0\lib\netstandard1.3\System.Threading.dll +system.threading\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.threading\4.3.0\lib\win8\_._ +system.threading\4.3.0\lib\wp80\_._ +system.threading\4.3.0\lib\wpa81\_._ +system.threading\4.3.0\lib\xamarinios10\_._ +system.threading\4.3.0\lib\xamarinmac20\_._ +system.threading\4.3.0\lib\xamarintvos10\_._ +system.threading\4.3.0\lib\xamarinwatchos10\_._ +system.threading\4.3.0\ref\MonoAndroid10\_._ +system.threading\4.3.0\ref\MonoTouch10\_._ +system.threading\4.3.0\ref\net45\_._ +system.threading\4.3.0\ref\netcore50\System.Threading.dll +system.threading\4.3.0\ref\netstandard1.0\System.Threading.dll +system.threading\4.3.0\ref\netstandard1.3\System.Threading.dll +system.threading\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.threading\4.3.0\ref\win8\_._ +system.threading\4.3.0\ref\wp80\_._ +system.threading\4.3.0\ref\wpa81\_._ +system.threading\4.3.0\ref\xamarinios10\_._ +system.threading\4.3.0\ref\xamarinmac20\_._ +system.threading\4.3.0\ref\xamarintvos10\_._ +system.threading\4.3.0\ref\xamarinwatchos10\_._ +system.threading\4.3.0\runtimes\aot\lib\netcore50\System.Threading.dll +system.threading\4.3.0\system.threading.4.3.0.nupkg +system.threading\4.3.0\system.threading.4.3.0.nupkg.sha512 +system.threading\4.3.0\system.threading.nuspec +system.threading\4.3.0\ThirdPartyNotices.txt +system.valuetuple\4.3.0\dotnet_library_license.txt +system.valuetuple\4.3.0\lib\netstandard1.0\.xml +system.valuetuple\4.3.0\lib\netstandard1.0\System.ValueTuple.dll +system.valuetuple\4.3.0\lib\portable-net40+sl4+win8+wp8\.xml +system.valuetuple\4.3.0\lib\portable-net40+sl4+win8+wp8\System.ValueTuple.dll +system.valuetuple\4.3.0\system.valuetuple.4.3.0.nupkg +system.valuetuple\4.3.0\system.valuetuple.4.3.0.nupkg.sha512 +system.valuetuple\4.3.0\system.valuetuple.nuspec +system.valuetuple\4.3.0\ThirdPartyNotices.txt +system.valuetuple\4.5.0\.signature.p7s +system.valuetuple\4.5.0\lib\MonoAndroid10\_._ +system.valuetuple\4.5.0\lib\MonoTouch10\_._ +system.valuetuple\4.5.0\lib\net461\System.ValueTuple.dll +system.valuetuple\4.5.0\lib\net47\System.ValueTuple.dll +system.valuetuple\4.5.0\lib\netcoreapp2.0\_._ +system.valuetuple\4.5.0\lib\netstandard1.0\System.ValueTuple.dll +system.valuetuple\4.5.0\lib\netstandard2.0\_._ +system.valuetuple\4.5.0\lib\portable-net40+sl4+win8+wp8\System.ValueTuple.dll +system.valuetuple\4.5.0\lib\uap10.0.16299\_._ +system.valuetuple\4.5.0\lib\xamarinios10\_._ +system.valuetuple\4.5.0\lib\xamarinmac20\_._ +system.valuetuple\4.5.0\lib\xamarintvos10\_._ +system.valuetuple\4.5.0\lib\xamarinwatchos10\_._ +system.valuetuple\4.5.0\LICENSE.TXT +system.valuetuple\4.5.0\ref\MonoAndroid10\_._ +system.valuetuple\4.5.0\ref\MonoTouch10\_._ +system.valuetuple\4.5.0\ref\net461\System.ValueTuple.dll +system.valuetuple\4.5.0\ref\net47\System.ValueTuple.dll +system.valuetuple\4.5.0\ref\netcoreapp2.0\_._ +system.valuetuple\4.5.0\ref\netstandard2.0\_._ +system.valuetuple\4.5.0\ref\portable-net40+sl4+win8+wp8\System.ValueTuple.dll +system.valuetuple\4.5.0\ref\uap10.0.16299\_._ +system.valuetuple\4.5.0\ref\xamarinios10\_._ +system.valuetuple\4.5.0\ref\xamarinmac20\_._ +system.valuetuple\4.5.0\ref\xamarintvos10\_._ +system.valuetuple\4.5.0\ref\xamarinwatchos10\_._ +system.valuetuple\4.5.0\system.valuetuple.4.5.0.nupkg +system.valuetuple\4.5.0\system.valuetuple.4.5.0.nupkg.sha512 +system.valuetuple\4.5.0\system.valuetuple.nuspec +system.valuetuple\4.5.0\THIRD-PARTY-NOTICES.TXT +system.valuetuple\4.5.0\useSharedDesignerContext.txt +system.valuetuple\4.5.0\version.txt +system.xml.readerwriter\4.0.11\dotnet_library_license.txt +system.xml.readerwriter\4.0.11\lib\MonoAndroid10\_._ +system.xml.readerwriter\4.0.11\lib\MonoTouch10\_._ +system.xml.readerwriter\4.0.11\lib\net45\_._ +system.xml.readerwriter\4.0.11\lib\netcore50\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\lib\netstandard1.3\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.readerwriter\4.0.11\lib\win8\_._ +system.xml.readerwriter\4.0.11\lib\wp80\_._ +system.xml.readerwriter\4.0.11\lib\wpa81\_._ +system.xml.readerwriter\4.0.11\lib\xamarinios10\_._ +system.xml.readerwriter\4.0.11\lib\xamarinmac20\_._ +system.xml.readerwriter\4.0.11\lib\xamarintvos10\_._ +system.xml.readerwriter\4.0.11\lib\xamarinwatchos10\_._ +system.xml.readerwriter\4.0.11\ref\MonoAndroid10\_._ +system.xml.readerwriter\4.0.11\ref\MonoTouch10\_._ +system.xml.readerwriter\4.0.11\ref\net45\_._ +system.xml.readerwriter\4.0.11\ref\netcore50\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\ref\netstandard1.0\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\ref\netstandard1.3\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.readerwriter\4.0.11\ref\win8\_._ +system.xml.readerwriter\4.0.11\ref\wp80\_._ +system.xml.readerwriter\4.0.11\ref\wpa81\_._ +system.xml.readerwriter\4.0.11\ref\xamarinios10\_._ +system.xml.readerwriter\4.0.11\ref\xamarinmac20\_._ +system.xml.readerwriter\4.0.11\ref\xamarintvos10\_._ +system.xml.readerwriter\4.0.11\ref\xamarinwatchos10\_._ +system.xml.readerwriter\4.0.11\system.xml.readerwriter.4.0.11.nupkg +system.xml.readerwriter\4.0.11\system.xml.readerwriter.4.0.11.nupkg.sha512 +system.xml.readerwriter\4.0.11\system.xml.readerwriter.nuspec +system.xml.readerwriter\4.0.11\ThirdPartyNotices.txt +system.xml.readerwriter\4.3.0\dotnet_library_license.txt +system.xml.readerwriter\4.3.0\lib\MonoAndroid10\_._ +system.xml.readerwriter\4.3.0\lib\MonoTouch10\_._ +system.xml.readerwriter\4.3.0\lib\net45\_._ +system.xml.readerwriter\4.3.0\lib\net46\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\lib\netcore50\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\lib\netstandard1.3\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.readerwriter\4.3.0\lib\win8\_._ +system.xml.readerwriter\4.3.0\lib\wp80\_._ +system.xml.readerwriter\4.3.0\lib\wpa81\_._ +system.xml.readerwriter\4.3.0\lib\xamarinios10\_._ +system.xml.readerwriter\4.3.0\lib\xamarinmac20\_._ +system.xml.readerwriter\4.3.0\lib\xamarintvos10\_._ +system.xml.readerwriter\4.3.0\lib\xamarinwatchos10\_._ +system.xml.readerwriter\4.3.0\ref\MonoAndroid10\_._ +system.xml.readerwriter\4.3.0\ref\MonoTouch10\_._ +system.xml.readerwriter\4.3.0\ref\net45\_._ +system.xml.readerwriter\4.3.0\ref\net46\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\ref\netcore50\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\ref\netstandard1.0\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\ref\netstandard1.3\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.readerwriter\4.3.0\ref\win8\_._ +system.xml.readerwriter\4.3.0\ref\wp80\_._ +system.xml.readerwriter\4.3.0\ref\wpa81\_._ +system.xml.readerwriter\4.3.0\ref\xamarinios10\_._ +system.xml.readerwriter\4.3.0\ref\xamarinmac20\_._ +system.xml.readerwriter\4.3.0\ref\xamarintvos10\_._ +system.xml.readerwriter\4.3.0\ref\xamarinwatchos10\_._ +system.xml.readerwriter\4.3.0\system.xml.readerwriter.4.3.0.nupkg +system.xml.readerwriter\4.3.0\system.xml.readerwriter.4.3.0.nupkg.sha512 +system.xml.readerwriter\4.3.0\system.xml.readerwriter.nuspec +system.xml.readerwriter\4.3.0\ThirdPartyNotices.txt +system.xml.xdocument\4.0.11\dotnet_library_license.txt +system.xml.xdocument\4.0.11\lib\MonoAndroid10\_._ +system.xml.xdocument\4.0.11\lib\MonoTouch10\_._ +system.xml.xdocument\4.0.11\lib\net45\_._ +system.xml.xdocument\4.0.11\lib\netcore50\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\lib\netstandard1.3\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.xdocument\4.0.11\lib\win8\_._ +system.xml.xdocument\4.0.11\lib\wp80\_._ +system.xml.xdocument\4.0.11\lib\wpa81\_._ +system.xml.xdocument\4.0.11\lib\xamarinios10\_._ +system.xml.xdocument\4.0.11\lib\xamarinmac20\_._ +system.xml.xdocument\4.0.11\lib\xamarintvos10\_._ +system.xml.xdocument\4.0.11\lib\xamarinwatchos10\_._ +system.xml.xdocument\4.0.11\ref\MonoAndroid10\_._ +system.xml.xdocument\4.0.11\ref\MonoTouch10\_._ +system.xml.xdocument\4.0.11\ref\net45\_._ +system.xml.xdocument\4.0.11\ref\netcore50\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\ref\netstandard1.0\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\ref\netstandard1.3\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.xdocument\4.0.11\ref\win8\_._ +system.xml.xdocument\4.0.11\ref\wp80\_._ +system.xml.xdocument\4.0.11\ref\wpa81\_._ +system.xml.xdocument\4.0.11\ref\xamarinios10\_._ +system.xml.xdocument\4.0.11\ref\xamarinmac20\_._ +system.xml.xdocument\4.0.11\ref\xamarintvos10\_._ +system.xml.xdocument\4.0.11\ref\xamarinwatchos10\_._ +system.xml.xdocument\4.0.11\system.xml.xdocument.4.0.11.nupkg +system.xml.xdocument\4.0.11\system.xml.xdocument.4.0.11.nupkg.sha512 +system.xml.xdocument\4.0.11\system.xml.xdocument.nuspec +system.xml.xdocument\4.0.11\ThirdPartyNotices.txt +system.xml.xdocument\4.3.0\dotnet_library_license.txt +system.xml.xdocument\4.3.0\lib\MonoAndroid10\_._ +system.xml.xdocument\4.3.0\lib\MonoTouch10\_._ +system.xml.xdocument\4.3.0\lib\net45\_._ +system.xml.xdocument\4.3.0\lib\netcore50\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\lib\netstandard1.3\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.xdocument\4.3.0\lib\win8\_._ +system.xml.xdocument\4.3.0\lib\wp80\_._ +system.xml.xdocument\4.3.0\lib\wpa81\_._ +system.xml.xdocument\4.3.0\lib\xamarinios10\_._ +system.xml.xdocument\4.3.0\lib\xamarinmac20\_._ +system.xml.xdocument\4.3.0\lib\xamarintvos10\_._ +system.xml.xdocument\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xdocument\4.3.0\ref\MonoAndroid10\_._ +system.xml.xdocument\4.3.0\ref\MonoTouch10\_._ +system.xml.xdocument\4.3.0\ref\net45\_._ +system.xml.xdocument\4.3.0\ref\netcore50\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\ref\netstandard1.0\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\ref\netstandard1.3\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.xdocument\4.3.0\ref\win8\_._ +system.xml.xdocument\4.3.0\ref\wp80\_._ +system.xml.xdocument\4.3.0\ref\wpa81\_._ +system.xml.xdocument\4.3.0\ref\xamarinios10\_._ +system.xml.xdocument\4.3.0\ref\xamarinmac20\_._ +system.xml.xdocument\4.3.0\ref\xamarintvos10\_._ +system.xml.xdocument\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xdocument\4.3.0\system.xml.xdocument.4.3.0.nupkg +system.xml.xdocument\4.3.0\system.xml.xdocument.4.3.0.nupkg.sha512 +system.xml.xdocument\4.3.0\system.xml.xdocument.nuspec +system.xml.xdocument\4.3.0\ThirdPartyNotices.txt +system.xml.xmldocument\4.0.1\dotnet_library_license.txt +system.xml.xmldocument\4.0.1\lib\MonoAndroid10\_._ +system.xml.xmldocument\4.0.1\lib\MonoTouch10\_._ +system.xml.xmldocument\4.0.1\lib\net46\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.0.1\lib\netstandard1.3\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.0.1\lib\xamarinios10\_._ +system.xml.xmldocument\4.0.1\lib\xamarinmac20\_._ +system.xml.xmldocument\4.0.1\lib\xamarintvos10\_._ +system.xml.xmldocument\4.0.1\lib\xamarinwatchos10\_._ +system.xml.xmldocument\4.0.1\ref\MonoAndroid10\_._ +system.xml.xmldocument\4.0.1\ref\MonoTouch10\_._ +system.xml.xmldocument\4.0.1\ref\net46\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.0.1\ref\netstandard1.3\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.0.1\ref\xamarinios10\_._ +system.xml.xmldocument\4.0.1\ref\xamarinmac20\_._ +system.xml.xmldocument\4.0.1\ref\xamarintvos10\_._ +system.xml.xmldocument\4.0.1\ref\xamarinwatchos10\_._ +system.xml.xmldocument\4.0.1\system.xml.xmldocument.4.0.1.nupkg +system.xml.xmldocument\4.0.1\system.xml.xmldocument.4.0.1.nupkg.sha512 +system.xml.xmldocument\4.0.1\system.xml.xmldocument.nuspec +system.xml.xmldocument\4.0.1\ThirdPartyNotices.txt +system.xml.xmldocument\4.3.0\dotnet_library_license.txt +system.xml.xmldocument\4.3.0\lib\MonoAndroid10\_._ +system.xml.xmldocument\4.3.0\lib\MonoTouch10\_._ +system.xml.xmldocument\4.3.0\lib\net46\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.3.0\lib\netstandard1.3\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.3.0\lib\xamarinios10\_._ +system.xml.xmldocument\4.3.0\lib\xamarinmac20\_._ +system.xml.xmldocument\4.3.0\lib\xamarintvos10\_._ +system.xml.xmldocument\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xmldocument\4.3.0\ref\MonoAndroid10\_._ +system.xml.xmldocument\4.3.0\ref\MonoTouch10\_._ +system.xml.xmldocument\4.3.0\ref\net46\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.3.0\ref\netstandard1.3\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.3.0\ref\xamarinios10\_._ +system.xml.xmldocument\4.3.0\ref\xamarinmac20\_._ +system.xml.xmldocument\4.3.0\ref\xamarintvos10\_._ +system.xml.xmldocument\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xmldocument\4.3.0\system.xml.xmldocument.4.3.0.nupkg +system.xml.xmldocument\4.3.0\system.xml.xmldocument.4.3.0.nupkg.sha512 +system.xml.xmldocument\4.3.0\system.xml.xmldocument.nuspec +system.xml.xmldocument\4.3.0\ThirdPartyNotices.txt +system.xml.xmlserializer\4.0.11\dotnet_library_license.txt +system.xml.xmlserializer\4.0.11\lib\MonoAndroid10\_._ +system.xml.xmlserializer\4.0.11\lib\MonoTouch10\_._ +system.xml.xmlserializer\4.0.11\lib\net45\_._ +system.xml.xmlserializer\4.0.11\lib\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\lib\netstandard1.3\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.xmlserializer\4.0.11\lib\win8\_._ +system.xml.xmlserializer\4.0.11\lib\wp80\_._ +system.xml.xmlserializer\4.0.11\lib\wpa81\_._ +system.xml.xmlserializer\4.0.11\lib\xamarinios10\_._ +system.xml.xmlserializer\4.0.11\lib\xamarinmac20\_._ +system.xml.xmlserializer\4.0.11\lib\xamarintvos10\_._ +system.xml.xmlserializer\4.0.11\lib\xamarinwatchos10\_._ +system.xml.xmlserializer\4.0.11\ref\MonoAndroid10\_._ +system.xml.xmlserializer\4.0.11\ref\MonoTouch10\_._ +system.xml.xmlserializer\4.0.11\ref\net45\_._ +system.xml.xmlserializer\4.0.11\ref\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\ref\netstandard1.0\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\ref\netstandard1.3\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.xmlserializer\4.0.11\ref\win8\_._ +system.xml.xmlserializer\4.0.11\ref\wp80\_._ +system.xml.xmlserializer\4.0.11\ref\wpa81\_._ +system.xml.xmlserializer\4.0.11\ref\xamarinios10\_._ +system.xml.xmlserializer\4.0.11\ref\xamarinmac20\_._ +system.xml.xmlserializer\4.0.11\ref\xamarintvos10\_._ +system.xml.xmlserializer\4.0.11\ref\xamarinwatchos10\_._ +system.xml.xmlserializer\4.0.11\runtimes\aot\lib\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\system.xml.xmlserializer.4.0.11.nupkg +system.xml.xmlserializer\4.0.11\system.xml.xmlserializer.4.0.11.nupkg.sha512 +system.xml.xmlserializer\4.0.11\system.xml.xmlserializer.nuspec +system.xml.xmlserializer\4.0.11\ThirdPartyNotices.txt +system.xml.xmlserializer\4.3.0\dotnet_library_license.txt +system.xml.xmlserializer\4.3.0\lib\MonoAndroid10\_._ +system.xml.xmlserializer\4.3.0\lib\MonoTouch10\_._ +system.xml.xmlserializer\4.3.0\lib\net45\_._ +system.xml.xmlserializer\4.3.0\lib\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\lib\netstandard1.3\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.xmlserializer\4.3.0\lib\win8\_._ +system.xml.xmlserializer\4.3.0\lib\wp80\_._ +system.xml.xmlserializer\4.3.0\lib\wpa81\_._ +system.xml.xmlserializer\4.3.0\lib\xamarinios10\_._ +system.xml.xmlserializer\4.3.0\lib\xamarinmac20\_._ +system.xml.xmlserializer\4.3.0\lib\xamarintvos10\_._ +system.xml.xmlserializer\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xmlserializer\4.3.0\ref\MonoAndroid10\_._ +system.xml.xmlserializer\4.3.0\ref\MonoTouch10\_._ +system.xml.xmlserializer\4.3.0\ref\net45\_._ +system.xml.xmlserializer\4.3.0\ref\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\ref\netstandard1.0\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\ref\netstandard1.3\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.xmlserializer\4.3.0\ref\win8\_._ +system.xml.xmlserializer\4.3.0\ref\wp80\_._ +system.xml.xmlserializer\4.3.0\ref\wpa81\_._ +system.xml.xmlserializer\4.3.0\ref\xamarinios10\_._ +system.xml.xmlserializer\4.3.0\ref\xamarinmac20\_._ +system.xml.xmlserializer\4.3.0\ref\xamarintvos10\_._ +system.xml.xmlserializer\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xmlserializer\4.3.0\runtimes\aot\lib\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\system.xml.xmlserializer.4.3.0.nupkg +system.xml.xmlserializer\4.3.0\system.xml.xmlserializer.4.3.0.nupkg.sha512 +system.xml.xmlserializer\4.3.0\system.xml.xmlserializer.nuspec +system.xml.xmlserializer\4.3.0\ThirdPartyNotices.txt +system.xml.xpath.xdocument\4.3.0\dotnet_library_license.txt +system.xml.xpath.xdocument\4.3.0\lib\MonoAndroid10\_._ +system.xml.xpath.xdocument\4.3.0\lib\MonoTouch10\_._ +system.xml.xpath.xdocument\4.3.0\lib\net46\System.Xml.XPath.XDocument.dll +system.xml.xpath.xdocument\4.3.0\lib\netstandard1.3\System.Xml.XPath.XDocument.dll +system.xml.xpath.xdocument\4.3.0\lib\xamarinios10\_._ +system.xml.xpath.xdocument\4.3.0\lib\xamarinmac20\_._ +system.xml.xpath.xdocument\4.3.0\lib\xamarintvos10\_._ +system.xml.xpath.xdocument\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xpath.xdocument\4.3.0\ref\MonoAndroid10\_._ +system.xml.xpath.xdocument\4.3.0\ref\MonoTouch10\_._ +system.xml.xpath.xdocument\4.3.0\ref\net46\System.Xml.XPath.XDocument.dll +system.xml.xpath.xdocument\4.3.0\ref\netstandard1.3\System.Xml.XPath.XDocument.dll +system.xml.xpath.xdocument\4.3.0\ref\xamarinios10\_._ +system.xml.xpath.xdocument\4.3.0\ref\xamarinmac20\_._ +system.xml.xpath.xdocument\4.3.0\ref\xamarintvos10\_._ +system.xml.xpath.xdocument\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xpath.xdocument\4.3.0\system.xml.xpath.xdocument.4.3.0.nupkg +system.xml.xpath.xdocument\4.3.0\system.xml.xpath.xdocument.4.3.0.nupkg.sha512 +system.xml.xpath.xdocument\4.3.0\system.xml.xpath.xdocument.nuspec +system.xml.xpath.xdocument\4.3.0\ThirdPartyNotices.txt +system.xml.xpath\4.3.0\dotnet_library_license.txt +system.xml.xpath\4.3.0\lib\MonoAndroid10\_._ +system.xml.xpath\4.3.0\lib\MonoTouch10\_._ +system.xml.xpath\4.3.0\lib\net46\System.Xml.XPath.dll +system.xml.xpath\4.3.0\lib\netstandard1.3\System.Xml.XPath.dll +system.xml.xpath\4.3.0\lib\xamarinios10\_._ +system.xml.xpath\4.3.0\lib\xamarinmac20\_._ +system.xml.xpath\4.3.0\lib\xamarintvos10\_._ +system.xml.xpath\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xpath\4.3.0\ref\MonoAndroid10\_._ +system.xml.xpath\4.3.0\ref\MonoTouch10\_._ +system.xml.xpath\4.3.0\ref\net46\System.Xml.XPath.dll +system.xml.xpath\4.3.0\ref\netstandard1.3\System.Xml.XPath.dll +system.xml.xpath\4.3.0\ref\xamarinios10\_._ +system.xml.xpath\4.3.0\ref\xamarinmac20\_._ +system.xml.xpath\4.3.0\ref\xamarintvos10\_._ +system.xml.xpath\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xpath\4.3.0\system.xml.xpath.4.3.0.nupkg +system.xml.xpath\4.3.0\system.xml.xpath.4.3.0.nupkg.sha512 +system.xml.xpath\4.3.0\system.xml.xpath.nuspec +system.xml.xpath\4.3.0\ThirdPartyNotices.txt +windowsazure.storage\8.1.4\lib\net45\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\net45\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\netstandard1.0\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\netstandard1.0\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\netstandard1.3\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\netstandard1.3\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\win8\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\win8\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\wp8\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\wp8\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\wpa\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\wpa\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\windowsazure.storage.8.1.4.nupkg +windowsazure.storage\8.1.4\windowsazure.storage.8.1.4.nupkg.sha512 +windowsazure.storage\8.1.4\windowsazure.storage.nuspec diff --git a/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.2.txt b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.2.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.3.txt b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.3.txt new file mode 100644 index 0000000000..ae5c6430c8 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.3.txt @@ -0,0 +1,381 @@ +microsoft.netcore.app\2.1.0\.signature.p7s +microsoft.netcore.app\2.1.0\build\netcoreapp2.1\Microsoft.NETCore.App.PlatformManifest.txt +microsoft.netcore.app\2.1.0\build\netcoreapp2.1\Microsoft.NETCore.App.props +microsoft.netcore.app\2.1.0\build\netcoreapp2.1\Microsoft.NETCore.App.targets +microsoft.netcore.app\2.1.0\LICENSE.TXT +microsoft.netcore.app\2.1.0\microsoft.netcore.app.2.1.0.nupkg +microsoft.netcore.app\2.1.0\microsoft.netcore.app.2.1.0.nupkg.sha512 +microsoft.netcore.app\2.1.0\microsoft.netcore.app.nuspec +microsoft.netcore.app\2.1.0\Microsoft.NETCore.App.versions.txt +microsoft.netcore.app\2.1.0\ref\netcoreapp\_._ +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\Microsoft.CSharp.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\Microsoft.VisualBasic.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\Microsoft.Win32.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\mscorlib.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\netstandard.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.AppContext.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Buffers.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Concurrent.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Immutable.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.NonGeneric.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Specialized.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.Annotations.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.DataAnnotations.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.EventBasedAsync.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.TypeConverter.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Configuration.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Console.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Core.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Data.Common.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Data.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Contracts.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Debug.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.DiagnosticSource.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.FileVersionInfo.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Process.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.StackTrace.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.TextWriterTraceListener.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Tools.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.TraceSource.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Tracing.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Drawing.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Drawing.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Dynamic.Runtime.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Globalization.Calendars.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Globalization.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Globalization.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Compression.Brotli.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Compression.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Compression.FileSystem.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Compression.ZipFile.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.FileSystem.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.FileSystem.DriveInfo.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.FileSystem.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.FileSystem.Watcher.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.IsolatedStorage.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.MemoryMappedFiles.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Pipes.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.UnmanagedMemoryStream.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Expressions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Parallel.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Queryable.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Memory.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Http.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.HttpListener.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Mail.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.NameResolution.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.NetworkInformation.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Ping.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Requests.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Security.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.ServicePoint.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Sockets.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebClient.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebHeaderCollection.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebProxy.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebSockets.Client.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebSockets.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Numerics.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Numerics.Vectors.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ObjectModel.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.DispatchProxy.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Emit.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Emit.ILGeneration.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Emit.Lightweight.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Metadata.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.TypeExtensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Resources.Reader.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Resources.ResourceManager.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Resources.Writer.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.CompilerServices.VisualC.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Handles.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.InteropServices.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.InteropServices.RuntimeInformation.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.InteropServices.WindowsRuntime.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Loader.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Numerics.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Formatters.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Json.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Xml.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Claims.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.Algorithms.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.Csp.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.Encoding.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.X509Certificates.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Principal.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.SecureString.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ServiceModel.Web.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ServiceProcess.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Text.Encoding.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Text.Encoding.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Text.RegularExpressions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Overlapped.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Tasks.Dataflow.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Tasks.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Tasks.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Tasks.Parallel.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Thread.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.ThreadPool.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Timer.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Transactions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Transactions.Local.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ValueTuple.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Web.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Web.HttpUtility.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Windows.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.Linq.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.ReaderWriter.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.Serialization.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XDocument.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XmlDocument.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XmlSerializer.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XPath.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XPath.XDocument.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\WindowsBase.dll +microsoft.netcore.app\2.1.0\runtime.json +microsoft.netcore.app\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnetapphost\2.1.0\.signature.p7s +microsoft.netcore.dotnetapphost\2.1.0\LICENSE.TXT +microsoft.netcore.dotnetapphost\2.1.0\microsoft.netcore.dotnetapphost.2.1.0.nupkg +microsoft.netcore.dotnetapphost\2.1.0\microsoft.netcore.dotnetapphost.2.1.0.nupkg.sha512 +microsoft.netcore.dotnetapphost\2.1.0\microsoft.netcore.dotnetapphost.nuspec +microsoft.netcore.dotnetapphost\2.1.0\runtime.json +microsoft.netcore.dotnetapphost\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostpolicy\2.1.0\.signature.p7s +microsoft.netcore.dotnethostpolicy\2.1.0\LICENSE.TXT +microsoft.netcore.dotnethostpolicy\2.1.0\microsoft.netcore.dotnethostpolicy.2.1.0.nupkg +microsoft.netcore.dotnethostpolicy\2.1.0\microsoft.netcore.dotnethostpolicy.2.1.0.nupkg.sha512 +microsoft.netcore.dotnethostpolicy\2.1.0\microsoft.netcore.dotnethostpolicy.nuspec +microsoft.netcore.dotnethostpolicy\2.1.0\runtime.json +microsoft.netcore.dotnethostpolicy\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostresolver\2.1.0\.signature.p7s +microsoft.netcore.dotnethostresolver\2.1.0\LICENSE.TXT +microsoft.netcore.dotnethostresolver\2.1.0\microsoft.netcore.dotnethostresolver.2.1.0.nupkg +microsoft.netcore.dotnethostresolver\2.1.0\microsoft.netcore.dotnethostresolver.2.1.0.nupkg.sha512 +microsoft.netcore.dotnethostresolver\2.1.0\microsoft.netcore.dotnethostresolver.nuspec +microsoft.netcore.dotnethostresolver\2.1.0\runtime.json +microsoft.netcore.dotnethostresolver\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.targets\2.1.0\.signature.p7s +microsoft.netcore.targets\2.1.0\lib\netstandard1.0\_._ +microsoft.netcore.targets\2.1.0\LICENSE.TXT +microsoft.netcore.targets\2.1.0\microsoft.netcore.targets.2.1.0.nupkg +microsoft.netcore.targets\2.1.0\microsoft.netcore.targets.2.1.0.nupkg.sha512 +microsoft.netcore.targets\2.1.0\microsoft.netcore.targets.nuspec +microsoft.netcore.targets\2.1.0\runtime.json +microsoft.netcore.targets\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.targets\2.1.0\useSharedDesignerContext.txt +microsoft.netcore.targets\2.1.0\version.txt +microsoft.visualstudio.web.codegeneration.contracts\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.3\microsoft.visualstudio.web.codegeneration.contracts.2.1.3.nupkg +microsoft.visualstudio.web.codegeneration.contracts\2.1.3\microsoft.visualstudio.web.codegeneration.contracts.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.3\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.3\microsoft.visualstudio.web.codegeneration.core.2.1.3.nupkg +microsoft.visualstudio.web.codegeneration.core\2.1.3\microsoft.visualstudio.web.codegeneration.core.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.3\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.3\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.3\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.3\microsoft.visualstudio.web.codegeneration.design.2.1.3.nupkg +microsoft.visualstudio.web.codegeneration.design\2.1.3\microsoft.visualstudio.web.codegeneration.design.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.3\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.3\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.3\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.3\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.3\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.3.nupkg +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.3\microsoft.visualstudio.web.codegeneration.templating.2.1.3.nupkg +microsoft.visualstudio.web.codegeneration.templating\2.1.3\microsoft.visualstudio.web.codegeneration.templating.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.3\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.3\microsoft.visualstudio.web.codegeneration.utils.2.1.3.nupkg +microsoft.visualstudio.web.codegeneration.utils\2.1.3\microsoft.visualstudio.web.codegeneration.utils.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.3\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.3\microsoft.visualstudio.web.codegeneration.2.1.3.nupkg +microsoft.visualstudio.web.codegeneration\2.1.3\microsoft.visualstudio.web.codegeneration.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.3\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\microsoft.visualstudio.web.codegenerators.mvc.2.1.3.nupkg +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\microsoft.visualstudio.web.codegenerators.mvc.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\List.cshtml diff --git a/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.4.txt b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.4.txt new file mode 100644 index 0000000000..89337174bc --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.4.txt @@ -0,0 +1,195 @@ +microsoft.visualstudio.web.codegeneration.contracts\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.4\microsoft.visualstudio.web.codegeneration.contracts.2.1.4.nupkg +microsoft.visualstudio.web.codegeneration.contracts\2.1.4\microsoft.visualstudio.web.codegeneration.contracts.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.4\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.4\microsoft.visualstudio.web.codegeneration.core.2.1.4.nupkg +microsoft.visualstudio.web.codegeneration.core\2.1.4\microsoft.visualstudio.web.codegeneration.core.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.4\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.4\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.4\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.4\microsoft.visualstudio.web.codegeneration.design.2.1.4.nupkg +microsoft.visualstudio.web.codegeneration.design\2.1.4\microsoft.visualstudio.web.codegeneration.design.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.4\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.4\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.4\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.4\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.4\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.4.nupkg +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.4\microsoft.visualstudio.web.codegeneration.templating.2.1.4.nupkg +microsoft.visualstudio.web.codegeneration.templating\2.1.4\microsoft.visualstudio.web.codegeneration.templating.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.4\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.4\microsoft.visualstudio.web.codegeneration.utils.2.1.4.nupkg +microsoft.visualstudio.web.codegeneration.utils\2.1.4\microsoft.visualstudio.web.codegeneration.utils.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.4\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.4\microsoft.visualstudio.web.codegeneration.2.1.4.nupkg +microsoft.visualstudio.web.codegeneration\2.1.4\microsoft.visualstudio.web.codegeneration.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.4\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\microsoft.visualstudio.web.codegenerators.mvc.2.1.4.nupkg +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\microsoft.visualstudio.web.codegenerators.mvc.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\List.cshtml diff --git a/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.5.txt b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.5.txt new file mode 100644 index 0000000000..99f4fc5db2 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.5.txt @@ -0,0 +1,214 @@ +microsoft.aspnetcore.razor.design\2.1.2\.signature.p7s +microsoft.aspnetcore.razor.design\2.1.2\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets +microsoft.aspnetcore.razor.design\2.1.2\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.1.2\buildMultiTargeting\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.1.2\microsoft.aspnetcore.razor.design.2.1.2.nupkg +microsoft.aspnetcore.razor.design\2.1.2\microsoft.aspnetcore.razor.design.2.1.2.nupkg.sha512 +microsoft.aspnetcore.razor.design\2.1.2\microsoft.aspnetcore.razor.design.nuspec +microsoft.aspnetcore.razor.design\2.1.2\tasks\net46\Microsoft.AspNetCore.Razor.Tasks.dll +microsoft.aspnetcore.razor.design\2.1.2\tasks\netstandard2.0\Microsoft.AspNetCore.Razor.Tasks.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Microsoft.CodeAnalysis.CSharp.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Microsoft.CodeAnalysis.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Microsoft.CodeAnalysis.Razor.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Newtonsoft.Json.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\runtimes\unix\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\rzc.deps.json +microsoft.aspnetcore.razor.design\2.1.2\tools\rzc.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\rzc.runtimeconfig.json +microsoft.visualstudio.web.codegeneration.contracts\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.5\microsoft.visualstudio.web.codegeneration.contracts.2.1.5.nupkg +microsoft.visualstudio.web.codegeneration.contracts\2.1.5\microsoft.visualstudio.web.codegeneration.contracts.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.5\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.5\microsoft.visualstudio.web.codegeneration.core.2.1.5.nupkg +microsoft.visualstudio.web.codegeneration.core\2.1.5\microsoft.visualstudio.web.codegeneration.core.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.5\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.5\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.5\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.5\microsoft.visualstudio.web.codegeneration.design.2.1.5.nupkg +microsoft.visualstudio.web.codegeneration.design\2.1.5\microsoft.visualstudio.web.codegeneration.design.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.5\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.5\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.5\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.5\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.5\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.5.nupkg +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.5\microsoft.visualstudio.web.codegeneration.templating.2.1.5.nupkg +microsoft.visualstudio.web.codegeneration.templating\2.1.5\microsoft.visualstudio.web.codegeneration.templating.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.5\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.5\microsoft.visualstudio.web.codegeneration.utils.2.1.5.nupkg +microsoft.visualstudio.web.codegeneration.utils\2.1.5\microsoft.visualstudio.web.codegeneration.utils.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.5\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.5\microsoft.visualstudio.web.codegeneration.2.1.5.nupkg +microsoft.visualstudio.web.codegeneration\2.1.5\microsoft.visualstudio.web.codegeneration.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.5\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\microsoft.visualstudio.web.codegenerators.mvc.2.1.5.nupkg +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\microsoft.visualstudio.web.codegenerators.mvc.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\List.cshtml diff --git a/src/PackageArchive/Archive.CiServer.Patch/Archive.CiServer.Patch.zipproj b/src/PackageArchive/Archive.CiServer.Patch/Archive.CiServer.Patch.zipproj new file mode 100644 index 0000000000..b7c357f50f --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch/Archive.CiServer.Patch.zipproj @@ -0,0 +1,13 @@ + + + + + + nuGetPackagesArchive-ci-server-$(PackageVersion).patch.zip + true + false + false + + + + diff --git a/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.1.txt b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.1.txt new file mode 100644 index 0000000000..76d662d026 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.1.txt @@ -0,0 +1,6141 @@ +libuv\1.10.0\libuv.1.10.0.nupkg.sha512 +libuv\1.10.0\libuv.nuspec +libuv\1.10.0\License.txt +libuv\1.10.0\runtimes\linux-arm\native\libuv.so +libuv\1.10.0\runtimes\linux-arm64\native\libuv.so +libuv\1.10.0\runtimes\linux-armel\native\libuv.so +libuv\1.10.0\runtimes\linux-x64\native\libuv.so +libuv\1.10.0\runtimes\osx\native\libuv.dylib +libuv\1.10.0\runtimes\win-arm\native\libuv.dll +libuv\1.10.0\runtimes\win-x64\native\libuv.dll +libuv\1.10.0\runtimes\win-x86\native\libuv.dll +messagepack\1.7.3.4\lib\net45\MessagePack.dll +messagepack\1.7.3.4\lib\net47\MessagePack.dll +messagepack\1.7.3.4\lib\netstandard1.6\MessagePack.dll +messagepack\1.7.3.4\lib\netstandard2.0\MessagePack.dll +messagepack\1.7.3.4\messagepack.1.7.3.4.nupkg.sha512 +messagepack\1.7.3.4\messagepack.nuspec +microsoft.applicationinsights.aspnetcore\2.1.1\lib\net451\Microsoft.ApplicationInsights.AspNetCore.dll +microsoft.applicationinsights.aspnetcore\2.1.1\lib\netstandard1.6\Microsoft.ApplicationInsights.AspNetCore.dll +microsoft.applicationinsights.aspnetcore\2.1.1\microsoft.applicationinsights.aspnetcore.2.1.1.nupkg.sha512 +microsoft.applicationinsights.aspnetcore\2.1.1\microsoft.applicationinsights.aspnetcore.nuspec +microsoft.applicationinsights.dependencycollector\2.4.1\content\ApplicationInsights.config.install.xdt +microsoft.applicationinsights.dependencycollector\2.4.1\content\ApplicationInsights.config.transform +microsoft.applicationinsights.dependencycollector\2.4.1\content\ApplicationInsights.config.uninstall.xdt +microsoft.applicationinsights.dependencycollector\2.4.1\lib\net40\Microsoft.AI.DependencyCollector.dll +microsoft.applicationinsights.dependencycollector\2.4.1\lib\net45\Microsoft.AI.DependencyCollector.dll +microsoft.applicationinsights.dependencycollector\2.4.1\lib\netstandard1.6\Microsoft.AI.DependencyCollector.dll +microsoft.applicationinsights.dependencycollector\2.4.1\microsoft.applicationinsights.dependencycollector.2.4.1.nupkg.sha512 +microsoft.applicationinsights.dependencycollector\2.4.1\microsoft.applicationinsights.dependencycollector.nuspec +microsoft.applicationinsights\2.4.0\lib\net40\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\net45\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\net46\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\netstandard1.3\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\portable-win81+wpa81\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\uap10.0\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\lib\wp8\Microsoft.ApplicationInsights.dll +microsoft.applicationinsights\2.4.0\microsoft.applicationinsights.2.4.0.nupkg.sha512 +microsoft.applicationinsights\2.4.0\microsoft.applicationinsights.nuspec +microsoft.aspnet.webapi.client\5.2.6\.signature.p7s +microsoft.aspnet.webapi.client\5.2.6\lib\net45\System.Net.Http.Formatting.dll +microsoft.aspnet.webapi.client\5.2.6\lib\netstandard2.0\System.Net.Http.Formatting.dll +microsoft.aspnet.webapi.client\5.2.6\lib\portable-wp8+netcore45+net45+wp81+wpa81\System.Net.Http.Formatting.dll +microsoft.aspnet.webapi.client\5.2.6\microsoft.aspnet.webapi.client.5.2.6.nupkg.sha512 +microsoft.aspnet.webapi.client\5.2.6\microsoft.aspnet.webapi.client.nuspec +microsoft.aspnetcore.all\2.1.1\.signature.p7s +microsoft.aspnetcore.all\2.1.1\build\netcoreapp2.1\Microsoft.AspNetCore.All.props +microsoft.aspnetcore.all\2.1.1\build\netcoreapp2.1\Microsoft.AspNetCore.All.targets +microsoft.aspnetcore.all\2.1.1\lib\netcoreapp2.1\_._ +microsoft.aspnetcore.all\2.1.1\microsoft.aspnetcore.all.2.1.1.nupkg.sha512 +microsoft.aspnetcore.all\2.1.1\microsoft.aspnetcore.all.nuspec +microsoft.aspnetcore.antiforgery\2.1.1\.signature.p7s +microsoft.aspnetcore.antiforgery\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Antiforgery.dll +microsoft.aspnetcore.antiforgery\2.1.1\microsoft.aspnetcore.antiforgery.2.1.1.nupkg.sha512 +microsoft.aspnetcore.antiforgery\2.1.1\microsoft.aspnetcore.antiforgery.nuspec +microsoft.aspnetcore.app\2.1.1\.signature.p7s +microsoft.aspnetcore.app\2.1.1\build\netcoreapp2.1\Microsoft.AspNetCore.App.props +microsoft.aspnetcore.app\2.1.1\build\netcoreapp2.1\Microsoft.AspNetCore.App.targets +microsoft.aspnetcore.app\2.1.1\lib\netcoreapp2.1\_._ +microsoft.aspnetcore.app\2.1.1\microsoft.aspnetcore.app.2.1.1.nupkg.sha512 +microsoft.aspnetcore.app\2.1.1\microsoft.aspnetcore.app.nuspec +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\.signature.p7s +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\lib\net461\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\lib\netcoreapp2.0\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\microsoft.aspnetcore.applicationinsights.hostingstartup.2.1.1.nupkg.sha512 +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\microsoft.aspnetcore.applicationinsights.hostingstartup.nuspec +microsoft.aspnetcore.authentication.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Abstractions.dll +microsoft.aspnetcore.authentication.abstractions\2.1.1\microsoft.aspnetcore.authentication.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.abstractions\2.1.1\microsoft.aspnetcore.authentication.abstractions.nuspec +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureAD.UI.dll +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureAD.UI.Views.dll +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\microsoft.aspnetcore.authentication.azuread.ui.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\microsoft.aspnetcore.authentication.azuread.ui.nuspec +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.dll +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Views.dll +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\microsoft.aspnetcore.authentication.azureadb2c.ui.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\microsoft.aspnetcore.authentication.azureadb2c.ui.nuspec +microsoft.aspnetcore.authentication.cookies\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.cookies\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Cookies.dll +microsoft.aspnetcore.authentication.cookies\2.1.1\microsoft.aspnetcore.authentication.cookies.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.cookies\2.1.1\microsoft.aspnetcore.authentication.cookies.nuspec +microsoft.aspnetcore.authentication.core\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.core\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Core.dll +microsoft.aspnetcore.authentication.core\2.1.1\microsoft.aspnetcore.authentication.core.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.core\2.1.1\microsoft.aspnetcore.authentication.core.nuspec +microsoft.aspnetcore.authentication.facebook\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.facebook\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Facebook.dll +microsoft.aspnetcore.authentication.facebook\2.1.1\microsoft.aspnetcore.authentication.facebook.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.facebook\2.1.1\microsoft.aspnetcore.authentication.facebook.nuspec +microsoft.aspnetcore.authentication.google\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.google\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Google.dll +microsoft.aspnetcore.authentication.google\2.1.1\microsoft.aspnetcore.authentication.google.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.google\2.1.1\microsoft.aspnetcore.authentication.google.nuspec +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.JwtBearer.dll +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\microsoft.aspnetcore.authentication.jwtbearer.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\microsoft.aspnetcore.authentication.jwtbearer.nuspec +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.MicrosoftAccount.dll +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\microsoft.aspnetcore.authentication.microsoftaccount.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\microsoft.aspnetcore.authentication.microsoftaccount.nuspec +microsoft.aspnetcore.authentication.oauth\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.oauth\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.OAuth.dll +microsoft.aspnetcore.authentication.oauth\2.1.1\microsoft.aspnetcore.authentication.oauth.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.oauth\2.1.1\microsoft.aspnetcore.authentication.oauth.nuspec +microsoft.aspnetcore.authentication.openidconnect\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.openidconnect\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.OpenIdConnect.dll +microsoft.aspnetcore.authentication.openidconnect\2.1.1\microsoft.aspnetcore.authentication.openidconnect.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.openidconnect\2.1.1\microsoft.aspnetcore.authentication.openidconnect.nuspec +microsoft.aspnetcore.authentication.twitter\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.twitter\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Twitter.dll +microsoft.aspnetcore.authentication.twitter\2.1.1\microsoft.aspnetcore.authentication.twitter.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.twitter\2.1.1\microsoft.aspnetcore.authentication.twitter.nuspec +microsoft.aspnetcore.authentication.wsfederation\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication.wsfederation\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.WsFederation.dll +microsoft.aspnetcore.authentication.wsfederation\2.1.1\microsoft.aspnetcore.authentication.wsfederation.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication.wsfederation\2.1.1\microsoft.aspnetcore.authentication.wsfederation.nuspec +microsoft.aspnetcore.authentication\2.1.1\.signature.p7s +microsoft.aspnetcore.authentication\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.dll +microsoft.aspnetcore.authentication\2.1.1\microsoft.aspnetcore.authentication.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authentication\2.1.1\microsoft.aspnetcore.authentication.nuspec +microsoft.aspnetcore.authorization.policy\2.1.1\.signature.p7s +microsoft.aspnetcore.authorization.policy\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.Policy.dll +microsoft.aspnetcore.authorization.policy\2.1.1\microsoft.aspnetcore.authorization.policy.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authorization.policy\2.1.1\microsoft.aspnetcore.authorization.policy.nuspec +microsoft.aspnetcore.authorization\2.1.1\.signature.p7s +microsoft.aspnetcore.authorization\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.dll +microsoft.aspnetcore.authorization\2.1.1\microsoft.aspnetcore.authorization.2.1.1.nupkg.sha512 +microsoft.aspnetcore.authorization\2.1.1\microsoft.aspnetcore.authorization.nuspec +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\.signature.p7s +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\lib\net461\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\lib\netcoreapp2.0\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\microsoft.aspnetcore.azureappservices.hostingstartup.2.1.1.nupkg.sha512 +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\microsoft.aspnetcore.azureappservices.hostingstartup.nuspec +microsoft.aspnetcore.azureappservicesintegration\2.1.1\.signature.p7s +microsoft.aspnetcore.azureappservicesintegration\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.AzureAppServicesIntegration.dll +microsoft.aspnetcore.azureappservicesintegration\2.1.1\microsoft.aspnetcore.azureappservicesintegration.2.1.1.nupkg.sha512 +microsoft.aspnetcore.azureappservicesintegration\2.1.1\microsoft.aspnetcore.azureappservicesintegration.nuspec +microsoft.aspnetcore.connections.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.connections.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Connections.Abstractions.dll +microsoft.aspnetcore.connections.abstractions\2.1.1\microsoft.aspnetcore.connections.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.connections.abstractions\2.1.1\microsoft.aspnetcore.connections.abstractions.nuspec +microsoft.aspnetcore.cookiepolicy\2.1.1\.signature.p7s +microsoft.aspnetcore.cookiepolicy\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.CookiePolicy.dll +microsoft.aspnetcore.cookiepolicy\2.1.1\microsoft.aspnetcore.cookiepolicy.2.1.1.nupkg.sha512 +microsoft.aspnetcore.cookiepolicy\2.1.1\microsoft.aspnetcore.cookiepolicy.nuspec +microsoft.aspnetcore.cors\2.1.1\.signature.p7s +microsoft.aspnetcore.cors\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Cors.dll +microsoft.aspnetcore.cors\2.1.1\microsoft.aspnetcore.cors.2.1.1.nupkg.sha512 +microsoft.aspnetcore.cors\2.1.1\microsoft.aspnetcore.cors.nuspec +microsoft.aspnetcore.cryptography.internal\2.1.1\.signature.p7s +microsoft.aspnetcore.cryptography.internal\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.Internal.dll +microsoft.aspnetcore.cryptography.internal\2.1.1\microsoft.aspnetcore.cryptography.internal.2.1.1.nupkg.sha512 +microsoft.aspnetcore.cryptography.internal\2.1.1\microsoft.aspnetcore.cryptography.internal.nuspec +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\.signature.p7s +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\lib\netcoreapp2.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\microsoft.aspnetcore.cryptography.keyderivation.2.1.1.nupkg.sha512 +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\microsoft.aspnetcore.cryptography.keyderivation.nuspec +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Abstractions.dll +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\microsoft.aspnetcore.dataprotection.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\microsoft.aspnetcore.dataprotection.abstractions.nuspec +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.AzureKeyVault.dll +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\microsoft.aspnetcore.dataprotection.azurekeyvault.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\microsoft.aspnetcore.dataprotection.azurekeyvault.nuspec +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.AzureStorage.dll +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\microsoft.aspnetcore.dataprotection.azurestorage.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\microsoft.aspnetcore.dataprotection.azurestorage.nuspec +microsoft.aspnetcore.dataprotection.extensions\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection.extensions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Extensions.dll +microsoft.aspnetcore.dataprotection.extensions\2.1.1\microsoft.aspnetcore.dataprotection.extensions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection.extensions\2.1.1\microsoft.aspnetcore.dataprotection.extensions.nuspec +microsoft.aspnetcore.dataprotection\2.1.1\.signature.p7s +microsoft.aspnetcore.dataprotection\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.dll +microsoft.aspnetcore.dataprotection\2.1.1\microsoft.aspnetcore.dataprotection.2.1.1.nupkg.sha512 +microsoft.aspnetcore.dataprotection\2.1.1\microsoft.aspnetcore.dataprotection.nuspec +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.Abstractions.dll +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\microsoft.aspnetcore.diagnostics.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\microsoft.aspnetcore.diagnostics.abstractions.nuspec +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\.signature.p7s +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.dll +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\microsoft.aspnetcore.diagnostics.entityframeworkcore.2.1.1.nupkg.sha512 +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\microsoft.aspnetcore.diagnostics.entityframeworkcore.nuspec +microsoft.aspnetcore.diagnostics\2.1.1\.signature.p7s +microsoft.aspnetcore.diagnostics\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.dll +microsoft.aspnetcore.diagnostics\2.1.1\microsoft.aspnetcore.diagnostics.2.1.1.nupkg.sha512 +microsoft.aspnetcore.diagnostics\2.1.1\microsoft.aspnetcore.diagnostics.nuspec +microsoft.aspnetcore.hostfiltering\2.1.1\.signature.p7s +microsoft.aspnetcore.hostfiltering\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.HostFiltering.dll +microsoft.aspnetcore.hostfiltering\2.1.1\microsoft.aspnetcore.hostfiltering.2.1.1.nupkg.sha512 +microsoft.aspnetcore.hostfiltering\2.1.1\microsoft.aspnetcore.hostfiltering.nuspec +microsoft.aspnetcore.hosting.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.hosting.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll +microsoft.aspnetcore.hosting.abstractions\2.1.1\microsoft.aspnetcore.hosting.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.hosting.abstractions\2.1.1\microsoft.aspnetcore.hosting.abstractions.nuspec +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\microsoft.aspnetcore.hosting.server.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\microsoft.aspnetcore.hosting.server.abstractions.nuspec +microsoft.aspnetcore.hosting\2.1.1\.signature.p7s +microsoft.aspnetcore.hosting\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.dll +microsoft.aspnetcore.hosting\2.1.1\microsoft.aspnetcore.hosting.2.1.1.nupkg.sha512 +microsoft.aspnetcore.hosting\2.1.1\microsoft.aspnetcore.hosting.nuspec +microsoft.aspnetcore.html.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.html.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Html.Abstractions.dll +microsoft.aspnetcore.html.abstractions\2.1.1\microsoft.aspnetcore.html.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.html.abstractions\2.1.1\microsoft.aspnetcore.html.abstractions.nuspec +microsoft.aspnetcore.http.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.http.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll +microsoft.aspnetcore.http.abstractions\2.1.1\microsoft.aspnetcore.http.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.http.abstractions\2.1.1\microsoft.aspnetcore.http.abstractions.nuspec +microsoft.aspnetcore.http.connections.common\1.0.1\.signature.p7s +microsoft.aspnetcore.http.connections.common\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Connections.Common.dll +microsoft.aspnetcore.http.connections.common\1.0.1\microsoft.aspnetcore.http.connections.common.1.0.1.nupkg.sha512 +microsoft.aspnetcore.http.connections.common\1.0.1\microsoft.aspnetcore.http.connections.common.nuspec +microsoft.aspnetcore.http.connections\1.0.1\.signature.p7s +microsoft.aspnetcore.http.connections\1.0.1\lib\netcoreapp2.1\Microsoft.AspNetCore.Http.Connections.dll +microsoft.aspnetcore.http.connections\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Connections.dll +microsoft.aspnetcore.http.connections\1.0.1\microsoft.aspnetcore.http.connections.1.0.1.nupkg.sha512 +microsoft.aspnetcore.http.connections\1.0.1\microsoft.aspnetcore.http.connections.nuspec +microsoft.aspnetcore.http.extensions\2.1.1\.signature.p7s +microsoft.aspnetcore.http.extensions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll +microsoft.aspnetcore.http.extensions\2.1.1\microsoft.aspnetcore.http.extensions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.http.extensions\2.1.1\microsoft.aspnetcore.http.extensions.nuspec +microsoft.aspnetcore.http.features\2.1.1\.signature.p7s +microsoft.aspnetcore.http.features\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll +microsoft.aspnetcore.http.features\2.1.1\microsoft.aspnetcore.http.features.2.1.1.nupkg.sha512 +microsoft.aspnetcore.http.features\2.1.1\microsoft.aspnetcore.http.features.nuspec +microsoft.aspnetcore.http\2.1.1\.signature.p7s +microsoft.aspnetcore.http\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.dll +microsoft.aspnetcore.http\2.1.1\microsoft.aspnetcore.http.2.1.1.nupkg.sha512 +microsoft.aspnetcore.http\2.1.1\microsoft.aspnetcore.http.nuspec +microsoft.aspnetcore.httpoverrides\2.1.1\.signature.p7s +microsoft.aspnetcore.httpoverrides\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.HttpOverrides.dll +microsoft.aspnetcore.httpoverrides\2.1.1\microsoft.aspnetcore.httpoverrides.2.1.1.nupkg.sha512 +microsoft.aspnetcore.httpoverrides\2.1.1\microsoft.aspnetcore.httpoverrides.nuspec +microsoft.aspnetcore.httpspolicy\2.1.1\.signature.p7s +microsoft.aspnetcore.httpspolicy\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.HttpsPolicy.dll +microsoft.aspnetcore.httpspolicy\2.1.1\microsoft.aspnetcore.httpspolicy.2.1.1.nupkg.sha512 +microsoft.aspnetcore.httpspolicy\2.1.1\microsoft.aspnetcore.httpspolicy.nuspec +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\.signature.p7s +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\microsoft.aspnetcore.identity.entityframeworkcore.2.1.1.nupkg.sha512 +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\microsoft.aspnetcore.identity.entityframeworkcore.nuspec +microsoft.aspnetcore.identity.ui\2.1.1\.signature.p7s +microsoft.aspnetcore.identity.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.dll +microsoft.aspnetcore.identity.ui\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.Views.dll +microsoft.aspnetcore.identity.ui\2.1.1\microsoft.aspnetcore.identity.ui.2.1.1.nupkg.sha512 +microsoft.aspnetcore.identity.ui\2.1.1\microsoft.aspnetcore.identity.ui.nuspec +microsoft.aspnetcore.identity.ui\2.1.1\THIRD-PARTY-NOTICES +microsoft.aspnetcore.identity\2.1.1\.signature.p7s +microsoft.aspnetcore.identity\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Identity.dll +microsoft.aspnetcore.identity\2.1.1\microsoft.aspnetcore.identity.2.1.1.nupkg.sha512 +microsoft.aspnetcore.identity\2.1.1\microsoft.aspnetcore.identity.nuspec +microsoft.aspnetcore.jsonpatch\2.1.1\.signature.p7s +microsoft.aspnetcore.jsonpatch\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.JsonPatch.dll +microsoft.aspnetcore.jsonpatch\2.1.1\microsoft.aspnetcore.jsonpatch.2.1.1.nupkg.sha512 +microsoft.aspnetcore.jsonpatch\2.1.1\microsoft.aspnetcore.jsonpatch.nuspec +microsoft.aspnetcore.localization.routing\2.1.1\.signature.p7s +microsoft.aspnetcore.localization.routing\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Localization.Routing.dll +microsoft.aspnetcore.localization.routing\2.1.1\microsoft.aspnetcore.localization.routing.2.1.1.nupkg.sha512 +microsoft.aspnetcore.localization.routing\2.1.1\microsoft.aspnetcore.localization.routing.nuspec +microsoft.aspnetcore.localization\2.1.1\.signature.p7s +microsoft.aspnetcore.localization\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Localization.dll +microsoft.aspnetcore.localization\2.1.1\microsoft.aspnetcore.localization.2.1.1.nupkg.sha512 +microsoft.aspnetcore.localization\2.1.1\microsoft.aspnetcore.localization.nuspec +microsoft.aspnetcore.middlewareanalysis\2.1.1\.signature.p7s +microsoft.aspnetcore.middlewareanalysis\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.MiddlewareAnalysis.dll +microsoft.aspnetcore.middlewareanalysis\2.1.1\microsoft.aspnetcore.middlewareanalysis.2.1.1.nupkg.sha512 +microsoft.aspnetcore.middlewareanalysis\2.1.1\microsoft.aspnetcore.middlewareanalysis.nuspec +microsoft.aspnetcore.mvc.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Abstractions.dll +microsoft.aspnetcore.mvc.abstractions\2.1.1\microsoft.aspnetcore.mvc.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.abstractions\2.1.1\microsoft.aspnetcore.mvc.abstractions.nuspec +microsoft.aspnetcore.mvc.analyzers\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.analyzers\2.1.1\analyzers\dotnet\cs\Microsoft.AspNetCore.Mvc.Analyzers.dll +microsoft.aspnetcore.mvc.analyzers\2.1.1\microsoft.aspnetcore.mvc.analyzers.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.analyzers\2.1.1\microsoft.aspnetcore.mvc.analyzers.nuspec +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ApiExplorer.dll +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\microsoft.aspnetcore.mvc.apiexplorer.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\microsoft.aspnetcore.mvc.apiexplorer.nuspec +microsoft.aspnetcore.mvc.core\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.core\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll +microsoft.aspnetcore.mvc.core\2.1.1\microsoft.aspnetcore.mvc.core.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.core\2.1.1\microsoft.aspnetcore.mvc.core.nuspec +microsoft.aspnetcore.mvc.cors\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.cors\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Cors.dll +microsoft.aspnetcore.mvc.cors\2.1.1\microsoft.aspnetcore.mvc.cors.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.cors\2.1.1\microsoft.aspnetcore.mvc.cors.nuspec +microsoft.aspnetcore.mvc.dataannotations\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.dataannotations\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.DataAnnotations.dll +microsoft.aspnetcore.mvc.dataannotations\2.1.1\microsoft.aspnetcore.mvc.dataannotations.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.dataannotations\2.1.1\microsoft.aspnetcore.mvc.dataannotations.nuspec +microsoft.aspnetcore.mvc.formatters.json\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.formatters.json\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Formatters.Json.dll +microsoft.aspnetcore.mvc.formatters.json\2.1.1\microsoft.aspnetcore.mvc.formatters.json.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.formatters.json\2.1.1\microsoft.aspnetcore.mvc.formatters.json.nuspec +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Formatters.Xml.dll +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\microsoft.aspnetcore.mvc.formatters.xml.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\microsoft.aspnetcore.mvc.formatters.xml.nuspec +microsoft.aspnetcore.mvc.localization\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.localization\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Localization.dll +microsoft.aspnetcore.mvc.localization\2.1.1\microsoft.aspnetcore.mvc.localization.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.localization\2.1.1\microsoft.aspnetcore.mvc.localization.nuspec +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.props +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.targets +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\lib\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\microsoft.aspnetcore.mvc.razor.extensions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\microsoft.aspnetcore.mvc.razor.extensions.nuspec +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation-x64.exe +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation-x86.exe +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.dll +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.targets +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.Tasks.dll +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\microsoft.aspnetcore.mvc.razor.viewcompilation.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\microsoft.aspnetcore.mvc.razor.viewcompilation.nuspec +microsoft.aspnetcore.mvc.razor\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.razor\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.dll +microsoft.aspnetcore.mvc.razor\2.1.1\microsoft.aspnetcore.mvc.razor.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.razor\2.1.1\microsoft.aspnetcore.mvc.razor.nuspec +microsoft.aspnetcore.mvc.razorpages\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.razorpages\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.RazorPages.dll +microsoft.aspnetcore.mvc.razorpages\2.1.1\microsoft.aspnetcore.mvc.razorpages.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.razorpages\2.1.1\microsoft.aspnetcore.mvc.razorpages.nuspec +microsoft.aspnetcore.mvc.taghelpers\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.taghelpers\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.TagHelpers.dll +microsoft.aspnetcore.mvc.taghelpers\2.1.1\microsoft.aspnetcore.mvc.taghelpers.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.taghelpers\2.1.1\microsoft.aspnetcore.mvc.taghelpers.nuspec +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ViewFeatures.dll +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\microsoft.aspnetcore.mvc.viewfeatures.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\microsoft.aspnetcore.mvc.viewfeatures.nuspec +microsoft.aspnetcore.mvc\2.1.1\.signature.p7s +microsoft.aspnetcore.mvc\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.dll +microsoft.aspnetcore.mvc\2.1.1\microsoft.aspnetcore.mvc.2.1.1.nupkg.sha512 +microsoft.aspnetcore.mvc\2.1.1\microsoft.aspnetcore.mvc.nuspec +microsoft.aspnetcore.nodeservices\2.1.1\.signature.p7s +microsoft.aspnetcore.nodeservices\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.NodeServices.dll +microsoft.aspnetcore.nodeservices\2.1.1\microsoft.aspnetcore.nodeservices.2.1.1.nupkg.sha512 +microsoft.aspnetcore.nodeservices\2.1.1\microsoft.aspnetcore.nodeservices.nuspec +microsoft.aspnetcore.owin\2.1.1\.signature.p7s +microsoft.aspnetcore.owin\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Owin.dll +microsoft.aspnetcore.owin\2.1.1\microsoft.aspnetcore.owin.2.1.1.nupkg.sha512 +microsoft.aspnetcore.owin\2.1.1\microsoft.aspnetcore.owin.nuspec +microsoft.aspnetcore.razor.design\2.1.1\.signature.p7s +microsoft.aspnetcore.razor.design\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets +microsoft.aspnetcore.razor.design\2.1.1\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.1.1\buildMultiTargeting\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.1.1\microsoft.aspnetcore.razor.design.2.1.1.nupkg.sha512 +microsoft.aspnetcore.razor.design\2.1.1\microsoft.aspnetcore.razor.design.nuspec +microsoft.aspnetcore.razor.design\2.1.1\tasks\net46\Microsoft.AspNetCore.Razor.Tasks.dll +microsoft.aspnetcore.razor.design\2.1.1\tasks\netstandard2.0\Microsoft.AspNetCore.Razor.Tasks.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Microsoft.CodeAnalysis.CSharp.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Microsoft.CodeAnalysis.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Microsoft.CodeAnalysis.Razor.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\Newtonsoft.Json.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\runtimes\unix\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\rzc.deps.json +microsoft.aspnetcore.razor.design\2.1.1\tools\rzc.dll +microsoft.aspnetcore.razor.design\2.1.1\tools\rzc.runtimeconfig.json +microsoft.aspnetcore.razor.language\2.1.1\.signature.p7s +microsoft.aspnetcore.razor.language\2.1.1\lib\net46\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.language\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.language\2.1.1\microsoft.aspnetcore.razor.language.2.1.1.nupkg.sha512 +microsoft.aspnetcore.razor.language\2.1.1\microsoft.aspnetcore.razor.language.nuspec +microsoft.aspnetcore.razor.runtime\2.1.1\.signature.p7s +microsoft.aspnetcore.razor.runtime\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Razor.Runtime.dll +microsoft.aspnetcore.razor.runtime\2.1.1\microsoft.aspnetcore.razor.runtime.2.1.1.nupkg.sha512 +microsoft.aspnetcore.razor.runtime\2.1.1\microsoft.aspnetcore.razor.runtime.nuspec +microsoft.aspnetcore.razor\2.1.1\.signature.p7s +microsoft.aspnetcore.razor\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Razor.dll +microsoft.aspnetcore.razor\2.1.1\microsoft.aspnetcore.razor.2.1.1.nupkg.sha512 +microsoft.aspnetcore.razor\2.1.1\microsoft.aspnetcore.razor.nuspec +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCaching.Abstractions.dll +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\microsoft.aspnetcore.responsecaching.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\microsoft.aspnetcore.responsecaching.abstractions.nuspec +microsoft.aspnetcore.responsecaching\2.1.1\.signature.p7s +microsoft.aspnetcore.responsecaching\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCaching.dll +microsoft.aspnetcore.responsecaching\2.1.1\microsoft.aspnetcore.responsecaching.2.1.1.nupkg.sha512 +microsoft.aspnetcore.responsecaching\2.1.1\microsoft.aspnetcore.responsecaching.nuspec +microsoft.aspnetcore.responsecompression\2.1.1\.signature.p7s +microsoft.aspnetcore.responsecompression\2.1.1\lib\net461\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.1.1\microsoft.aspnetcore.responsecompression.2.1.1.nupkg.sha512 +microsoft.aspnetcore.responsecompression\2.1.1\microsoft.aspnetcore.responsecompression.nuspec +microsoft.aspnetcore.rewrite\2.1.1\.signature.p7s +microsoft.aspnetcore.rewrite\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Rewrite.dll +microsoft.aspnetcore.rewrite\2.1.1\microsoft.aspnetcore.rewrite.2.1.1.nupkg.sha512 +microsoft.aspnetcore.rewrite\2.1.1\microsoft.aspnetcore.rewrite.nuspec +microsoft.aspnetcore.routing.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.routing.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Routing.Abstractions.dll +microsoft.aspnetcore.routing.abstractions\2.1.1\microsoft.aspnetcore.routing.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.routing.abstractions\2.1.1\microsoft.aspnetcore.routing.abstractions.nuspec +microsoft.aspnetcore.routing\2.1.1\.signature.p7s +microsoft.aspnetcore.routing\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Routing.dll +microsoft.aspnetcore.routing\2.1.1\microsoft.aspnetcore.routing.2.1.1.nupkg.sha512 +microsoft.aspnetcore.routing\2.1.1\microsoft.aspnetcore.routing.nuspec +microsoft.aspnetcore.server.httpsys\2.1.1\.signature.p7s +microsoft.aspnetcore.server.httpsys\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.HttpSys.dll +microsoft.aspnetcore.server.httpsys\2.1.1\microsoft.aspnetcore.server.httpsys.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.httpsys\2.1.1\microsoft.aspnetcore.server.httpsys.nuspec +microsoft.aspnetcore.server.iisintegration\2.1.1\.signature.p7s +microsoft.aspnetcore.server.iisintegration\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.IISIntegration.dll +microsoft.aspnetcore.server.iisintegration\2.1.1\microsoft.aspnetcore.server.iisintegration.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.iisintegration\2.1.1\microsoft.aspnetcore.server.iisintegration.nuspec +microsoft.aspnetcore.server.kestrel.core\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.core\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Core.dll +microsoft.aspnetcore.server.kestrel.core\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll +microsoft.aspnetcore.server.kestrel.core\2.1.1\microsoft.aspnetcore.server.kestrel.core.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.core\2.1.1\microsoft.aspnetcore.server.kestrel.core.nuspec +microsoft.aspnetcore.server.kestrel.https\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.https\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Https.dll +microsoft.aspnetcore.server.kestrel.https\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Https.dll +microsoft.aspnetcore.server.kestrel.https\2.1.1\microsoft.aspnetcore.server.kestrel.https.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.https\2.1.1\microsoft.aspnetcore.server.kestrel.https.nuspec +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\microsoft.aspnetcore.server.kestrel.transport.abstractions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\microsoft.aspnetcore.server.kestrel.transport.abstractions.nuspec +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\microsoft.aspnetcore.server.kestrel.transport.libuv.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\microsoft.aspnetcore.server.kestrel.transport.libuv.nuspec +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\microsoft.aspnetcore.server.kestrel.transport.sockets.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\microsoft.aspnetcore.server.kestrel.transport.sockets.nuspec +microsoft.aspnetcore.server.kestrel\2.1.1\.signature.p7s +microsoft.aspnetcore.server.kestrel\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.dll +microsoft.aspnetcore.server.kestrel\2.1.1\microsoft.aspnetcore.server.kestrel.2.1.1.nupkg.sha512 +microsoft.aspnetcore.server.kestrel\2.1.1\microsoft.aspnetcore.server.kestrel.nuspec +microsoft.aspnetcore.session\2.1.1\.signature.p7s +microsoft.aspnetcore.session\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Session.dll +microsoft.aspnetcore.session\2.1.1\microsoft.aspnetcore.session.2.1.1.nupkg.sha512 +microsoft.aspnetcore.session\2.1.1\microsoft.aspnetcore.session.nuspec +microsoft.aspnetcore.signalr.common\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr.common\1.0.1\lib\netcoreapp2.1\Microsoft.AspNetCore.SignalR.Common.dll +microsoft.aspnetcore.signalr.common\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Common.dll +microsoft.aspnetcore.signalr.common\1.0.1\microsoft.aspnetcore.signalr.common.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr.common\1.0.1\microsoft.aspnetcore.signalr.common.nuspec +microsoft.aspnetcore.signalr.core\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr.core\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Core.dll +microsoft.aspnetcore.signalr.core\1.0.1\microsoft.aspnetcore.signalr.core.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr.core\1.0.1\microsoft.aspnetcore.signalr.core.nuspec +microsoft.aspnetcore.signalr.protocols.json\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr.protocols.json\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Protocols.Json.dll +microsoft.aspnetcore.signalr.protocols.json\1.0.1\microsoft.aspnetcore.signalr.protocols.json.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr.protocols.json\1.0.1\microsoft.aspnetcore.signalr.protocols.json.nuspec +microsoft.aspnetcore.signalr.redis\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr.redis\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Redis.dll +microsoft.aspnetcore.signalr.redis\1.0.1\microsoft.aspnetcore.signalr.redis.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr.redis\1.0.1\microsoft.aspnetcore.signalr.redis.nuspec +microsoft.aspnetcore.signalr\1.0.1\.signature.p7s +microsoft.aspnetcore.signalr\1.0.1\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.dll +microsoft.aspnetcore.signalr\1.0.1\microsoft.aspnetcore.signalr.1.0.1.nupkg.sha512 +microsoft.aspnetcore.signalr\1.0.1\microsoft.aspnetcore.signalr.nuspec +microsoft.aspnetcore.spaservices.extensions\2.1.1\.signature.p7s +microsoft.aspnetcore.spaservices.extensions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.SpaServices.Extensions.dll +microsoft.aspnetcore.spaservices.extensions\2.1.1\microsoft.aspnetcore.spaservices.extensions.2.1.1.nupkg.sha512 +microsoft.aspnetcore.spaservices.extensions\2.1.1\microsoft.aspnetcore.spaservices.extensions.nuspec +microsoft.aspnetcore.spaservices\2.1.1\.signature.p7s +microsoft.aspnetcore.spaservices\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.SpaServices.dll +microsoft.aspnetcore.spaservices\2.1.1\microsoft.aspnetcore.spaservices.2.1.1.nupkg.sha512 +microsoft.aspnetcore.spaservices\2.1.1\microsoft.aspnetcore.spaservices.nuspec +microsoft.aspnetcore.staticfiles\2.1.1\.signature.p7s +microsoft.aspnetcore.staticfiles\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.StaticFiles.dll +microsoft.aspnetcore.staticfiles\2.1.1\microsoft.aspnetcore.staticfiles.2.1.1.nupkg.sha512 +microsoft.aspnetcore.staticfiles\2.1.1\microsoft.aspnetcore.staticfiles.nuspec +microsoft.aspnetcore.websockets\2.1.1\.signature.p7s +microsoft.aspnetcore.websockets\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.WebSockets.dll +microsoft.aspnetcore.websockets\2.1.1\microsoft.aspnetcore.websockets.2.1.1.nupkg.sha512 +microsoft.aspnetcore.websockets\2.1.1\microsoft.aspnetcore.websockets.nuspec +microsoft.aspnetcore.webutilities\2.1.1\.signature.p7s +microsoft.aspnetcore.webutilities\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.WebUtilities.dll +microsoft.aspnetcore.webutilities\2.1.1\microsoft.aspnetcore.webutilities.2.1.1.nupkg.sha512 +microsoft.aspnetcore.webutilities\2.1.1\microsoft.aspnetcore.webutilities.nuspec +microsoft.aspnetcore\2.1.1\.signature.p7s +microsoft.aspnetcore\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.dll +microsoft.aspnetcore\2.1.1\microsoft.aspnetcore.2.1.1.nupkg.sha512 +microsoft.aspnetcore\2.1.1\microsoft.aspnetcore.nuspec +microsoft.azure.keyvault.webkey\2.0.7\lib\net452\Microsoft.Azure.KeyVault.WebKey.dll +microsoft.azure.keyvault.webkey\2.0.7\lib\net452\Microsoft.Azure.KeyVault.WebKey.runtimeconfig.json +microsoft.azure.keyvault.webkey\2.0.7\lib\netstandard1.4\Microsoft.Azure.KeyVault.WebKey.dll +microsoft.azure.keyvault.webkey\2.0.7\lib\netstandard1.4\Microsoft.Azure.KeyVault.WebKey.runtimeconfig.json +microsoft.azure.keyvault.webkey\2.0.7\microsoft.azure.keyvault.webkey.2.0.7.nupkg.sha512 +microsoft.azure.keyvault.webkey\2.0.7\microsoft.azure.keyvault.webkey.nuspec +microsoft.azure.keyvault\2.3.2\lib\net452\Microsoft.Azure.KeyVault.dll +microsoft.azure.keyvault\2.3.2\lib\net452\Microsoft.Azure.KeyVault.runtimeconfig.json +microsoft.azure.keyvault\2.3.2\lib\netstandard1.4\Microsoft.Azure.KeyVault.dll +microsoft.azure.keyvault\2.3.2\lib\netstandard1.4\Microsoft.Azure.KeyVault.runtimeconfig.json +microsoft.azure.keyvault\2.3.2\microsoft.azure.keyvault.2.3.2.nupkg.sha512 +microsoft.azure.keyvault\2.3.2\microsoft.azure.keyvault.nuspec +microsoft.azure.services.appauthentication\1.0.1\build\Microsoft.Azure.Services.AppAuthentication.targets +microsoft.azure.services.appauthentication\1.0.1\lib\net452\Microsoft.Azure.Services.AppAuthentication.dll +microsoft.azure.services.appauthentication\1.0.1\lib\net452\Microsoft.Azure.Services.AppAuthentication.runtimeconfig.json +microsoft.azure.services.appauthentication\1.0.1\lib\netstandard1.4\Microsoft.Azure.Services.AppAuthentication.dll +microsoft.azure.services.appauthentication\1.0.1\lib\netstandard1.4\Microsoft.Azure.Services.AppAuthentication.runtimeconfig.json +microsoft.azure.services.appauthentication\1.0.1\microsoft.azure.services.appauthentication.1.0.1.nupkg.sha512 +microsoft.azure.services.appauthentication\1.0.1\microsoft.azure.services.appauthentication.nuspec +microsoft.codeanalysis.analyzers\1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll +microsoft.codeanalysis.analyzers\1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll +microsoft.codeanalysis.analyzers\1.1.0\analyzers\dotnet\vb\Microsoft.CodeAnalysis.Analyzers.dll +microsoft.codeanalysis.analyzers\1.1.0\analyzers\dotnet\vb\Microsoft.CodeAnalysis.VisualBasic.Analyzers.dll +microsoft.codeanalysis.analyzers\1.1.0\microsoft.codeanalysis.analyzers.1.1.0.nupkg.sha512 +microsoft.codeanalysis.analyzers\1.1.0\microsoft.codeanalysis.analyzers.nuspec +microsoft.codeanalysis.analyzers\1.1.0\ThirdPartyNotices.rtf +microsoft.codeanalysis.analyzers\1.1.0\tools\install.ps1 +microsoft.codeanalysis.analyzers\1.1.0\tools\uninstall.ps1 +microsoft.codeanalysis.common\2.8.0\.signature.p7s +microsoft.codeanalysis.common\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.dll +microsoft.codeanalysis.common\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.pdb +microsoft.codeanalysis.common\2.8.0\microsoft.codeanalysis.common.2.8.0.nupkg.sha512 +microsoft.codeanalysis.common\2.8.0\microsoft.codeanalysis.common.nuspec +microsoft.codeanalysis.csharp.workspaces\2.8.0\.signature.p7s +microsoft.codeanalysis.csharp.workspaces\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Workspaces.dll +microsoft.codeanalysis.csharp.workspaces\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Workspaces.pdb +microsoft.codeanalysis.csharp.workspaces\2.8.0\microsoft.codeanalysis.csharp.workspaces.2.8.0.nupkg.sha512 +microsoft.codeanalysis.csharp.workspaces\2.8.0\microsoft.codeanalysis.csharp.workspaces.nuspec +microsoft.codeanalysis.csharp\2.8.0\.signature.p7s +microsoft.codeanalysis.csharp\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll +microsoft.codeanalysis.csharp\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.pdb +microsoft.codeanalysis.csharp\2.8.0\microsoft.codeanalysis.csharp.2.8.0.nupkg.sha512 +microsoft.codeanalysis.csharp\2.8.0\microsoft.codeanalysis.csharp.nuspec +microsoft.codeanalysis.razor\2.1.1\.signature.p7s +microsoft.codeanalysis.razor\2.1.1\lib\net46\Microsoft.CodeAnalysis.Razor.dll +microsoft.codeanalysis.razor\2.1.1\lib\netstandard2.0\Microsoft.CodeAnalysis.Razor.dll +microsoft.codeanalysis.razor\2.1.1\microsoft.codeanalysis.razor.2.1.1.nupkg.sha512 +microsoft.codeanalysis.razor\2.1.1\microsoft.codeanalysis.razor.nuspec +microsoft.codeanalysis.workspaces.common\2.8.0\.signature.p7s +microsoft.codeanalysis.workspaces.common\2.8.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.Desktop.dll +microsoft.codeanalysis.workspaces.common\2.8.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.Desktop.pdb +microsoft.codeanalysis.workspaces.common\2.8.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.dll +microsoft.codeanalysis.workspaces.common\2.8.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.pdb +microsoft.codeanalysis.workspaces.common\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.Workspaces.dll +microsoft.codeanalysis.workspaces.common\2.8.0\lib\netstandard1.3\Microsoft.CodeAnalysis.Workspaces.pdb +microsoft.codeanalysis.workspaces.common\2.8.0\microsoft.codeanalysis.workspaces.common.2.8.0.nupkg.sha512 +microsoft.codeanalysis.workspaces.common\2.8.0\microsoft.codeanalysis.workspaces.common.nuspec +microsoft.csharp\4.0.1\dotnet_library_license.txt +microsoft.csharp\4.0.1\lib\MonoAndroid10\_._ +microsoft.csharp\4.0.1\lib\MonoTouch10\_._ +microsoft.csharp\4.0.1\lib\net45\_._ +microsoft.csharp\4.0.1\lib\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.0.1\lib\netstandard1.3\Microsoft.CSharp.dll +microsoft.csharp\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.0.1\lib\win8\_._ +microsoft.csharp\4.0.1\lib\wp80\_._ +microsoft.csharp\4.0.1\lib\wpa81\_._ +microsoft.csharp\4.0.1\lib\xamarinios10\_._ +microsoft.csharp\4.0.1\lib\xamarinmac20\_._ +microsoft.csharp\4.0.1\lib\xamarintvos10\_._ +microsoft.csharp\4.0.1\lib\xamarinwatchos10\_._ +microsoft.csharp\4.0.1\microsoft.csharp.4.0.1.nupkg.sha512 +microsoft.csharp\4.0.1\microsoft.csharp.nuspec +microsoft.csharp\4.0.1\ref\MonoAndroid10\_._ +microsoft.csharp\4.0.1\ref\MonoTouch10\_._ +microsoft.csharp\4.0.1\ref\net45\_._ +microsoft.csharp\4.0.1\ref\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.0.1\ref\netstandard1.0\Microsoft.CSharp.dll +microsoft.csharp\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.0.1\ref\win8\_._ +microsoft.csharp\4.0.1\ref\wp80\_._ +microsoft.csharp\4.0.1\ref\wpa81\_._ +microsoft.csharp\4.0.1\ref\xamarinios10\_._ +microsoft.csharp\4.0.1\ref\xamarinmac20\_._ +microsoft.csharp\4.0.1\ref\xamarintvos10\_._ +microsoft.csharp\4.0.1\ref\xamarinwatchos10\_._ +microsoft.csharp\4.0.1\ThirdPartyNotices.txt +microsoft.csharp\4.3.0\dotnet_library_license.txt +microsoft.csharp\4.3.0\lib\MonoAndroid10\_._ +microsoft.csharp\4.3.0\lib\MonoTouch10\_._ +microsoft.csharp\4.3.0\lib\net45\_._ +microsoft.csharp\4.3.0\lib\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.3.0\lib\netstandard1.3\Microsoft.CSharp.dll +microsoft.csharp\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.3.0\lib\win8\_._ +microsoft.csharp\4.3.0\lib\wp80\_._ +microsoft.csharp\4.3.0\lib\wpa81\_._ +microsoft.csharp\4.3.0\lib\xamarinios10\_._ +microsoft.csharp\4.3.0\lib\xamarinmac20\_._ +microsoft.csharp\4.3.0\lib\xamarintvos10\_._ +microsoft.csharp\4.3.0\lib\xamarinwatchos10\_._ +microsoft.csharp\4.3.0\microsoft.csharp.4.3.0.nupkg.sha512 +microsoft.csharp\4.3.0\microsoft.csharp.nuspec +microsoft.csharp\4.3.0\ref\MonoAndroid10\_._ +microsoft.csharp\4.3.0\ref\MonoTouch10\_._ +microsoft.csharp\4.3.0\ref\net45\_._ +microsoft.csharp\4.3.0\ref\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.3.0\ref\netstandard1.0\Microsoft.CSharp.dll +microsoft.csharp\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.3.0\ref\win8\_._ +microsoft.csharp\4.3.0\ref\wp80\_._ +microsoft.csharp\4.3.0\ref\wpa81\_._ +microsoft.csharp\4.3.0\ref\xamarinios10\_._ +microsoft.csharp\4.3.0\ref\xamarinmac20\_._ +microsoft.csharp\4.3.0\ref\xamarintvos10\_._ +microsoft.csharp\4.3.0\ref\xamarinwatchos10\_._ +microsoft.csharp\4.3.0\ThirdPartyNotices.txt +microsoft.csharp\4.5.0\.signature.p7s +microsoft.csharp\4.5.0\lib\MonoAndroid10\_._ +microsoft.csharp\4.5.0\lib\MonoTouch10\_._ +microsoft.csharp\4.5.0\lib\net45\_._ +microsoft.csharp\4.5.0\lib\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\lib\netcoreapp2.0\_._ +microsoft.csharp\4.5.0\lib\netstandard1.3\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\lib\netstandard2.0\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\lib\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.5.0\lib\uap10.0.16299\_._ +microsoft.csharp\4.5.0\lib\win8\_._ +microsoft.csharp\4.5.0\lib\wp80\_._ +microsoft.csharp\4.5.0\lib\wpa81\_._ +microsoft.csharp\4.5.0\lib\xamarinios10\_._ +microsoft.csharp\4.5.0\lib\xamarinmac20\_._ +microsoft.csharp\4.5.0\lib\xamarintvos10\_._ +microsoft.csharp\4.5.0\lib\xamarinwatchos10\_._ +microsoft.csharp\4.5.0\LICENSE.TXT +microsoft.csharp\4.5.0\microsoft.csharp.4.5.0.nupkg.sha512 +microsoft.csharp\4.5.0\microsoft.csharp.nuspec +microsoft.csharp\4.5.0\ref\MonoAndroid10\_._ +microsoft.csharp\4.5.0\ref\MonoTouch10\_._ +microsoft.csharp\4.5.0\ref\net45\_._ +microsoft.csharp\4.5.0\ref\netcore50\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\ref\netcoreapp2.0\_._ +microsoft.csharp\4.5.0\ref\netstandard1.0\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\ref\netstandard2.0\Microsoft.CSharp.dll +microsoft.csharp\4.5.0\ref\portable-net45+win8+wp8+wpa81\_._ +microsoft.csharp\4.5.0\ref\uap10.0.16299\_._ +microsoft.csharp\4.5.0\ref\win8\_._ +microsoft.csharp\4.5.0\ref\wp80\_._ +microsoft.csharp\4.5.0\ref\wpa81\_._ +microsoft.csharp\4.5.0\ref\xamarinios10\_._ +microsoft.csharp\4.5.0\ref\xamarinmac20\_._ +microsoft.csharp\4.5.0\ref\xamarintvos10\_._ +microsoft.csharp\4.5.0\ref\xamarinwatchos10\_._ +microsoft.csharp\4.5.0\THIRD-PARTY-NOTICES.TXT +microsoft.csharp\4.5.0\useSharedDesignerContext.txt +microsoft.csharp\4.5.0\version.txt +microsoft.data.edm\5.8.2\lib\net40\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\net40\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\net40\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\netstandard1.1\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\de\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\es\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\fr\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\it\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\ja\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\ko\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\Microsoft.Data.Edm.dll +microsoft.data.edm\5.8.2\lib\sl4\ru\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\zh-Hans\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\lib\sl4\zh-Hant\Microsoft.Data.Edm.resources.dll +microsoft.data.edm\5.8.2\microsoft.data.edm.5.8.2.nupkg.sha512 +microsoft.data.edm\5.8.2\microsoft.data.edm.nuspec +microsoft.data.odata\5.8.2\lib\net40\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\net40\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\net40\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\netstandard1.1\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\de\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\es\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\fr\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\it\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\ja\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\ko\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\Microsoft.Data.OData.dll +microsoft.data.odata\5.8.2\lib\sl4\ru\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\zh-Hans\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\lib\sl4\zh-Hant\Microsoft.Data.OData.resources.dll +microsoft.data.odata\5.8.2\microsoft.data.odata.5.8.2.nupkg.sha512 +microsoft.data.odata\5.8.2\microsoft.data.odata.nuspec +microsoft.data.sqlite.core\2.1.0\.signature.p7s +microsoft.data.sqlite.core\2.1.0\lib\netstandard2.0\Microsoft.Data.Sqlite.dll +microsoft.data.sqlite.core\2.1.0\microsoft.data.sqlite.core.2.1.0.nupkg.sha512 +microsoft.data.sqlite.core\2.1.0\microsoft.data.sqlite.core.nuspec +microsoft.data.sqlite\2.1.0\.signature.p7s +microsoft.data.sqlite\2.1.0\lib\netstandard2.0\_._ +microsoft.data.sqlite\2.1.0\microsoft.data.sqlite.2.1.0.nupkg.sha512 +microsoft.data.sqlite\2.1.0\microsoft.data.sqlite.nuspec +microsoft.dotnet.platformabstractions\2.1.0\.signature.p7s +microsoft.dotnet.platformabstractions\2.1.0\lib\net45\Microsoft.DotNet.PlatformAbstractions.dll +microsoft.dotnet.platformabstractions\2.1.0\lib\netstandard1.3\Microsoft.DotNet.PlatformAbstractions.dll +microsoft.dotnet.platformabstractions\2.1.0\LICENSE.TXT +microsoft.dotnet.platformabstractions\2.1.0\microsoft.dotnet.platformabstractions.2.1.0.nupkg.sha512 +microsoft.dotnet.platformabstractions\2.1.0\microsoft.dotnet.platformabstractions.nuspec +microsoft.dotnet.platformabstractions\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.entityframeworkcore.abstractions\2.1.1\.signature.p7s +microsoft.entityframeworkcore.abstractions\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Abstractions.dll +microsoft.entityframeworkcore.abstractions\2.1.1\microsoft.entityframeworkcore.abstractions.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.abstractions\2.1.1\microsoft.entityframeworkcore.abstractions.nuspec +microsoft.entityframeworkcore.analyzers\2.1.1\.signature.p7s +microsoft.entityframeworkcore.analyzers\2.1.1\analyzers\dotnet\cs\Microsoft.EntityFrameworkCore.Analyzers.dll +microsoft.entityframeworkcore.analyzers\2.1.1\microsoft.entityframeworkcore.analyzers.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.analyzers\2.1.1\microsoft.entityframeworkcore.analyzers.nuspec +microsoft.entityframeworkcore.design\2.1.1\.signature.p7s +microsoft.entityframeworkcore.design\2.1.1\build\net461\Microsoft.EntityFrameworkCore.Design.props +microsoft.entityframeworkcore.design\2.1.1\build\netcoreapp2.0\Microsoft.EntityFrameworkCore.Design.props +microsoft.entityframeworkcore.design\2.1.1\lib\net461\Microsoft.EntityFrameworkCore.Design.dll +microsoft.entityframeworkcore.design\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Design.dll +microsoft.entityframeworkcore.design\2.1.1\microsoft.entityframeworkcore.design.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.design\2.1.1\microsoft.entityframeworkcore.design.nuspec +microsoft.entityframeworkcore.inmemory\2.1.1\.signature.p7s +microsoft.entityframeworkcore.inmemory\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.InMemory.dll +microsoft.entityframeworkcore.inmemory\2.1.1\microsoft.entityframeworkcore.inmemory.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.inmemory\2.1.1\microsoft.entityframeworkcore.inmemory.nuspec +microsoft.entityframeworkcore.relational\2.1.1\.signature.p7s +microsoft.entityframeworkcore.relational\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Relational.dll +microsoft.entityframeworkcore.relational\2.1.1\microsoft.entityframeworkcore.relational.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.relational\2.1.1\microsoft.entityframeworkcore.relational.nuspec +microsoft.entityframeworkcore.sqlite.core\2.1.1\.signature.p7s +microsoft.entityframeworkcore.sqlite.core\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Sqlite.dll +microsoft.entityframeworkcore.sqlite.core\2.1.1\microsoft.entityframeworkcore.sqlite.core.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.sqlite.core\2.1.1\microsoft.entityframeworkcore.sqlite.core.nuspec +microsoft.entityframeworkcore.sqlite\2.1.1\.signature.p7s +microsoft.entityframeworkcore.sqlite\2.1.1\lib\netstandard2.0\_._ +microsoft.entityframeworkcore.sqlite\2.1.1\microsoft.entityframeworkcore.sqlite.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.sqlite\2.1.1\microsoft.entityframeworkcore.sqlite.nuspec +microsoft.entityframeworkcore.sqlserver\2.1.1\.signature.p7s +microsoft.entityframeworkcore.sqlserver\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.SqlServer.dll +microsoft.entityframeworkcore.sqlserver\2.1.1\microsoft.entityframeworkcore.sqlserver.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.sqlserver\2.1.1\microsoft.entityframeworkcore.sqlserver.nuspec +microsoft.entityframeworkcore.tools\2.1.1\.signature.p7s +microsoft.entityframeworkcore.tools\2.1.1\lib\netstandard2.0\_._ +microsoft.entityframeworkcore.tools\2.1.1\microsoft.entityframeworkcore.tools.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore.tools\2.1.1\microsoft.entityframeworkcore.tools.nuspec +microsoft.entityframeworkcore.tools\2.1.1\tools\about_EntityFrameworkCore.help.txt +microsoft.entityframeworkcore.tools\2.1.1\tools\EntityFrameworkCore.PowerShell2.psd1 +microsoft.entityframeworkcore.tools\2.1.1\tools\EntityFrameworkCore.PowerShell2.psm1 +microsoft.entityframeworkcore.tools\2.1.1\tools\EntityFrameworkCore.psd1 +microsoft.entityframeworkcore.tools\2.1.1\tools\EntityFrameworkCore.psm1 +microsoft.entityframeworkcore.tools\2.1.1\tools\init.ps1 +microsoft.entityframeworkcore.tools\2.1.1\tools\install.ps1 +microsoft.entityframeworkcore.tools\2.1.1\tools\net461\any\ef.exe +microsoft.entityframeworkcore.tools\2.1.1\tools\net461\win-x86\ef.exe +microsoft.entityframeworkcore.tools\2.1.1\tools\netcoreapp2.0\any\ef.dll +microsoft.entityframeworkcore.tools\2.1.1\tools\netcoreapp2.0\any\ef.runtimeconfig.json +microsoft.entityframeworkcore\2.1.1\.signature.p7s +microsoft.entityframeworkcore\2.1.1\lib\netstandard2.0\Microsoft.EntityFrameworkCore.dll +microsoft.entityframeworkcore\2.1.1\microsoft.entityframeworkcore.2.1.1.nupkg.sha512 +microsoft.entityframeworkcore\2.1.1\microsoft.entityframeworkcore.nuspec +microsoft.extensions.caching.abstractions\2.1.1\.signature.p7s +microsoft.extensions.caching.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Caching.Abstractions.dll +microsoft.extensions.caching.abstractions\2.1.1\microsoft.extensions.caching.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.caching.abstractions\2.1.1\microsoft.extensions.caching.abstractions.nuspec +microsoft.extensions.caching.memory\2.1.1\.signature.p7s +microsoft.extensions.caching.memory\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Caching.Memory.dll +microsoft.extensions.caching.memory\2.1.1\microsoft.extensions.caching.memory.2.1.1.nupkg.sha512 +microsoft.extensions.caching.memory\2.1.1\microsoft.extensions.caching.memory.nuspec +microsoft.extensions.caching.redis\2.1.1\.signature.p7s +microsoft.extensions.caching.redis\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Caching.Redis.dll +microsoft.extensions.caching.redis\2.1.1\microsoft.extensions.caching.redis.2.1.1.nupkg.sha512 +microsoft.extensions.caching.redis\2.1.1\microsoft.extensions.caching.redis.nuspec +microsoft.extensions.caching.sqlserver\2.1.1\.signature.p7s +microsoft.extensions.caching.sqlserver\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Caching.SqlServer.dll +microsoft.extensions.caching.sqlserver\2.1.1\microsoft.extensions.caching.sqlserver.2.1.1.nupkg.sha512 +microsoft.extensions.caching.sqlserver\2.1.1\microsoft.extensions.caching.sqlserver.nuspec +microsoft.extensions.configuration.abstractions\2.1.1\.signature.p7s +microsoft.extensions.configuration.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll +microsoft.extensions.configuration.abstractions\2.1.1\microsoft.extensions.configuration.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.abstractions\2.1.1\microsoft.extensions.configuration.abstractions.nuspec +microsoft.extensions.configuration.azurekeyvault\2.1.1\.signature.p7s +microsoft.extensions.configuration.azurekeyvault\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.AzureKeyVault.dll +microsoft.extensions.configuration.azurekeyvault\2.1.1\microsoft.extensions.configuration.azurekeyvault.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.azurekeyvault\2.1.1\microsoft.extensions.configuration.azurekeyvault.nuspec +microsoft.extensions.configuration.binder\2.1.1\.signature.p7s +microsoft.extensions.configuration.binder\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll +microsoft.extensions.configuration.binder\2.1.1\microsoft.extensions.configuration.binder.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.binder\2.1.1\microsoft.extensions.configuration.binder.nuspec +microsoft.extensions.configuration.commandline\2.1.1\.signature.p7s +microsoft.extensions.configuration.commandline\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.CommandLine.dll +microsoft.extensions.configuration.commandline\2.1.1\microsoft.extensions.configuration.commandline.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.commandline\2.1.1\microsoft.extensions.configuration.commandline.nuspec +microsoft.extensions.configuration.environmentvariables\2.1.1\.signature.p7s +microsoft.extensions.configuration.environmentvariables\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll +microsoft.extensions.configuration.environmentvariables\2.1.1\microsoft.extensions.configuration.environmentvariables.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.environmentvariables\2.1.1\microsoft.extensions.configuration.environmentvariables.nuspec +microsoft.extensions.configuration.fileextensions\2.1.1\.signature.p7s +microsoft.extensions.configuration.fileextensions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.FileExtensions.dll +microsoft.extensions.configuration.fileextensions\2.1.1\microsoft.extensions.configuration.fileextensions.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.fileextensions\2.1.1\microsoft.extensions.configuration.fileextensions.nuspec +microsoft.extensions.configuration.ini\2.1.1\.signature.p7s +microsoft.extensions.configuration.ini\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Ini.dll +microsoft.extensions.configuration.ini\2.1.1\microsoft.extensions.configuration.ini.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.ini\2.1.1\microsoft.extensions.configuration.ini.nuspec +microsoft.extensions.configuration.json\2.1.1\.signature.p7s +microsoft.extensions.configuration.json\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Json.dll +microsoft.extensions.configuration.json\2.1.1\microsoft.extensions.configuration.json.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.json\2.1.1\microsoft.extensions.configuration.json.nuspec +microsoft.extensions.configuration.keyperfile\2.1.1\.signature.p7s +microsoft.extensions.configuration.keyperfile\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.KeyPerFile.dll +microsoft.extensions.configuration.keyperfile\2.1.1\microsoft.extensions.configuration.keyperfile.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.keyperfile\2.1.1\microsoft.extensions.configuration.keyperfile.nuspec +microsoft.extensions.configuration.usersecrets\2.1.1\.signature.p7s +microsoft.extensions.configuration.usersecrets\2.1.1\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.props +microsoft.extensions.configuration.usersecrets\2.1.1\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.targets +microsoft.extensions.configuration.usersecrets\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.dll +microsoft.extensions.configuration.usersecrets\2.1.1\microsoft.extensions.configuration.usersecrets.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.usersecrets\2.1.1\microsoft.extensions.configuration.usersecrets.nuspec +microsoft.extensions.configuration.xml\2.1.1\.signature.p7s +microsoft.extensions.configuration.xml\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Xml.dll +microsoft.extensions.configuration.xml\2.1.1\microsoft.extensions.configuration.xml.2.1.1.nupkg.sha512 +microsoft.extensions.configuration.xml\2.1.1\microsoft.extensions.configuration.xml.nuspec +microsoft.extensions.configuration\2.1.1\.signature.p7s +microsoft.extensions.configuration\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll +microsoft.extensions.configuration\2.1.1\microsoft.extensions.configuration.2.1.1.nupkg.sha512 +microsoft.extensions.configuration\2.1.1\microsoft.extensions.configuration.nuspec +microsoft.extensions.dependencyinjection.abstractions\2.1.1\.signature.p7s +microsoft.extensions.dependencyinjection.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll +microsoft.extensions.dependencyinjection.abstractions\2.1.1\microsoft.extensions.dependencyinjection.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.dependencyinjection.abstractions\2.1.1\microsoft.extensions.dependencyinjection.abstractions.nuspec +microsoft.extensions.dependencyinjection\2.1.1\.signature.p7s +microsoft.extensions.dependencyinjection\2.1.1\lib\net461\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.1.1\lib\netcoreapp2.0\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.1.1\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.1.1\microsoft.extensions.dependencyinjection.2.1.1.nupkg.sha512 +microsoft.extensions.dependencyinjection\2.1.1\microsoft.extensions.dependencyinjection.nuspec +microsoft.extensions.dependencymodel\2.1.0\.signature.p7s +microsoft.extensions.dependencymodel\2.1.0\lib\net451\Microsoft.Extensions.DependencyModel.dll +microsoft.extensions.dependencymodel\2.1.0\lib\netstandard1.3\Microsoft.Extensions.DependencyModel.dll +microsoft.extensions.dependencymodel\2.1.0\lib\netstandard1.6\Microsoft.Extensions.DependencyModel.dll +microsoft.extensions.dependencymodel\2.1.0\LICENSE.TXT +microsoft.extensions.dependencymodel\2.1.0\microsoft.extensions.dependencymodel.2.1.0.nupkg.sha512 +microsoft.extensions.dependencymodel\2.1.0\microsoft.extensions.dependencymodel.nuspec +microsoft.extensions.dependencymodel\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.extensions.diagnosticadapter\2.1.0\.signature.p7s +microsoft.extensions.diagnosticadapter\2.1.0\lib\net461\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.1.0\lib\netcoreapp2.0\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.1.0\lib\netstandard2.0\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.1.0\microsoft.extensions.diagnosticadapter.2.1.0.nupkg.sha512 +microsoft.extensions.diagnosticadapter\2.1.0\microsoft.extensions.diagnosticadapter.nuspec +microsoft.extensions.fileproviders.abstractions\2.1.1\.signature.p7s +microsoft.extensions.fileproviders.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Abstractions.dll +microsoft.extensions.fileproviders.abstractions\2.1.1\microsoft.extensions.fileproviders.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.fileproviders.abstractions\2.1.1\microsoft.extensions.fileproviders.abstractions.nuspec +microsoft.extensions.fileproviders.composite\2.1.1\.signature.p7s +microsoft.extensions.fileproviders.composite\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Composite.dll +microsoft.extensions.fileproviders.composite\2.1.1\microsoft.extensions.fileproviders.composite.2.1.1.nupkg.sha512 +microsoft.extensions.fileproviders.composite\2.1.1\microsoft.extensions.fileproviders.composite.nuspec +microsoft.extensions.fileproviders.embedded\2.1.1\.signature.p7s +microsoft.extensions.fileproviders.embedded\2.1.1\build\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.props +microsoft.extensions.fileproviders.embedded\2.1.1\build\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.targets +microsoft.extensions.fileproviders.embedded\2.1.1\buildMultiTargeting\Microsoft.Extensions.FileProviders.Embedded.props +microsoft.extensions.fileproviders.embedded\2.1.1\buildMultiTargeting\Microsoft.Extensions.FileProviders.Embedded.targets +microsoft.extensions.fileproviders.embedded\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.dll +microsoft.extensions.fileproviders.embedded\2.1.1\microsoft.extensions.fileproviders.embedded.2.1.1.nupkg.sha512 +microsoft.extensions.fileproviders.embedded\2.1.1\microsoft.extensions.fileproviders.embedded.nuspec +microsoft.extensions.fileproviders.embedded\2.1.1\tasks\net461\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll +microsoft.extensions.fileproviders.embedded\2.1.1\tasks\netstandard1.5\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll +microsoft.extensions.fileproviders.physical\2.1.1\.signature.p7s +microsoft.extensions.fileproviders.physical\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Physical.dll +microsoft.extensions.fileproviders.physical\2.1.1\microsoft.extensions.fileproviders.physical.2.1.1.nupkg.sha512 +microsoft.extensions.fileproviders.physical\2.1.1\microsoft.extensions.fileproviders.physical.nuspec +microsoft.extensions.filesystemglobbing\2.1.1\.signature.p7s +microsoft.extensions.filesystemglobbing\2.1.1\lib\netstandard2.0\Microsoft.Extensions.FileSystemGlobbing.dll +microsoft.extensions.filesystemglobbing\2.1.1\microsoft.extensions.filesystemglobbing.2.1.1.nupkg.sha512 +microsoft.extensions.filesystemglobbing\2.1.1\microsoft.extensions.filesystemglobbing.nuspec +microsoft.extensions.hosting.abstractions\2.1.1\.signature.p7s +microsoft.extensions.hosting.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Hosting.Abstractions.dll +microsoft.extensions.hosting.abstractions\2.1.1\microsoft.extensions.hosting.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.hosting.abstractions\2.1.1\microsoft.extensions.hosting.abstractions.nuspec +microsoft.extensions.hosting\2.1.1\.signature.p7s +microsoft.extensions.hosting\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Hosting.dll +microsoft.extensions.hosting\2.1.1\microsoft.extensions.hosting.2.1.1.nupkg.sha512 +microsoft.extensions.hosting\2.1.1\microsoft.extensions.hosting.nuspec +microsoft.extensions.http\2.1.1\.signature.p7s +microsoft.extensions.http\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Http.dll +microsoft.extensions.http\2.1.1\microsoft.extensions.http.2.1.1.nupkg.sha512 +microsoft.extensions.http\2.1.1\microsoft.extensions.http.nuspec +microsoft.extensions.identity.core\2.1.1\.signature.p7s +microsoft.extensions.identity.core\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Identity.Core.dll +microsoft.extensions.identity.core\2.1.1\microsoft.extensions.identity.core.2.1.1.nupkg.sha512 +microsoft.extensions.identity.core\2.1.1\microsoft.extensions.identity.core.nuspec +microsoft.extensions.identity.stores\2.1.1\.signature.p7s +microsoft.extensions.identity.stores\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Identity.Stores.dll +microsoft.extensions.identity.stores\2.1.1\microsoft.extensions.identity.stores.2.1.1.nupkg.sha512 +microsoft.extensions.identity.stores\2.1.1\microsoft.extensions.identity.stores.nuspec +microsoft.extensions.localization.abstractions\2.1.1\.signature.p7s +microsoft.extensions.localization.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Localization.Abstractions.dll +microsoft.extensions.localization.abstractions\2.1.1\microsoft.extensions.localization.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.localization.abstractions\2.1.1\microsoft.extensions.localization.abstractions.nuspec +microsoft.extensions.localization\2.1.1\.signature.p7s +microsoft.extensions.localization\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Localization.dll +microsoft.extensions.localization\2.1.1\microsoft.extensions.localization.2.1.1.nupkg.sha512 +microsoft.extensions.localization\2.1.1\microsoft.extensions.localization.nuspec +microsoft.extensions.logging.abstractions\2.1.1\.signature.p7s +microsoft.extensions.logging.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll +microsoft.extensions.logging.abstractions\2.1.1\microsoft.extensions.logging.abstractions.2.1.1.nupkg.sha512 +microsoft.extensions.logging.abstractions\2.1.1\microsoft.extensions.logging.abstractions.nuspec +microsoft.extensions.logging.azureappservices\2.1.1\.signature.p7s +microsoft.extensions.logging.azureappservices\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.AzureAppServices.dll +microsoft.extensions.logging.azureappservices\2.1.1\microsoft.extensions.logging.azureappservices.2.1.1.nupkg.sha512 +microsoft.extensions.logging.azureappservices\2.1.1\microsoft.extensions.logging.azureappservices.nuspec +microsoft.extensions.logging.configuration\2.1.1\.signature.p7s +microsoft.extensions.logging.configuration\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Configuration.dll +microsoft.extensions.logging.configuration\2.1.1\microsoft.extensions.logging.configuration.2.1.1.nupkg.sha512 +microsoft.extensions.logging.configuration\2.1.1\microsoft.extensions.logging.configuration.nuspec +microsoft.extensions.logging.console\2.1.1\.signature.p7s +microsoft.extensions.logging.console\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Console.dll +microsoft.extensions.logging.console\2.1.1\microsoft.extensions.logging.console.2.1.1.nupkg.sha512 +microsoft.extensions.logging.console\2.1.1\microsoft.extensions.logging.console.nuspec +microsoft.extensions.logging.debug\2.1.1\.signature.p7s +microsoft.extensions.logging.debug\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Debug.dll +microsoft.extensions.logging.debug\2.1.1\microsoft.extensions.logging.debug.2.1.1.nupkg.sha512 +microsoft.extensions.logging.debug\2.1.1\microsoft.extensions.logging.debug.nuspec +microsoft.extensions.logging.eventsource\2.1.1\.signature.p7s +microsoft.extensions.logging.eventsource\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.EventSource.dll +microsoft.extensions.logging.eventsource\2.1.1\microsoft.extensions.logging.eventsource.2.1.1.nupkg.sha512 +microsoft.extensions.logging.eventsource\2.1.1\microsoft.extensions.logging.eventsource.nuspec +microsoft.extensions.logging.tracesource\2.1.1\.signature.p7s +microsoft.extensions.logging.tracesource\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.TraceSource.dll +microsoft.extensions.logging.tracesource\2.1.1\microsoft.extensions.logging.tracesource.2.1.1.nupkg.sha512 +microsoft.extensions.logging.tracesource\2.1.1\microsoft.extensions.logging.tracesource.nuspec +microsoft.extensions.logging\2.1.1\.signature.p7s +microsoft.extensions.logging\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.dll +microsoft.extensions.logging\2.1.1\microsoft.extensions.logging.2.1.1.nupkg.sha512 +microsoft.extensions.logging\2.1.1\microsoft.extensions.logging.nuspec +microsoft.extensions.objectpool\2.1.1\.signature.p7s +microsoft.extensions.objectpool\2.1.1\lib\netstandard2.0\Microsoft.Extensions.ObjectPool.dll +microsoft.extensions.objectpool\2.1.1\microsoft.extensions.objectpool.2.1.1.nupkg.sha512 +microsoft.extensions.objectpool\2.1.1\microsoft.extensions.objectpool.nuspec +microsoft.extensions.options.configurationextensions\2.1.1\.signature.p7s +microsoft.extensions.options.configurationextensions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll +microsoft.extensions.options.configurationextensions\2.1.1\microsoft.extensions.options.configurationextensions.2.1.1.nupkg.sha512 +microsoft.extensions.options.configurationextensions\2.1.1\microsoft.extensions.options.configurationextensions.nuspec +microsoft.extensions.options\2.1.1\.signature.p7s +microsoft.extensions.options\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Options.dll +microsoft.extensions.options\2.1.1\microsoft.extensions.options.2.1.1.nupkg.sha512 +microsoft.extensions.options\2.1.1\microsoft.extensions.options.nuspec +microsoft.extensions.platformabstractions\1.1.0\lib\net451\Microsoft.Extensions.PlatformAbstractions.dll +microsoft.extensions.platformabstractions\1.1.0\lib\netstandard1.3\Microsoft.Extensions.PlatformAbstractions.dll +microsoft.extensions.platformabstractions\1.1.0\microsoft.extensions.platformabstractions.1.1.0.nupkg.sha512 +microsoft.extensions.platformabstractions\1.1.0\microsoft.extensions.platformabstractions.nuspec +microsoft.extensions.primitives\2.1.1\.signature.p7s +microsoft.extensions.primitives\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll +microsoft.extensions.primitives\2.1.1\microsoft.extensions.primitives.2.1.1.nupkg.sha512 +microsoft.extensions.primitives\2.1.1\microsoft.extensions.primitives.nuspec +microsoft.extensions.webencoders\2.1.1\.signature.p7s +microsoft.extensions.webencoders\2.1.1\lib\netstandard2.0\Microsoft.Extensions.WebEncoders.dll +microsoft.extensions.webencoders\2.1.1\microsoft.extensions.webencoders.2.1.1.nupkg.sha512 +microsoft.extensions.webencoders\2.1.1\microsoft.extensions.webencoders.nuspec +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\MonoAndroid10\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\MonoAndroid10\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\netcore45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\netcore45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\netstandard1.3\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\netstandard1.3\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\portable-net45+win\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\Xamarin.iOS10\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\lib\Xamarin.iOS10\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.14.2\microsoft.identitymodel.clients.activedirectory.3.14.2.nupkg.sha512 +microsoft.identitymodel.clients.activedirectory\3.14.2\microsoft.identitymodel.clients.activedirectory.nuspec +microsoft.identitymodel.logging\5.2.0\lib\net45\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.2.0\lib\net451\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.2.0\microsoft.identitymodel.logging.5.2.0.nupkg.sha512 +microsoft.identitymodel.logging\5.2.0\microsoft.identitymodel.logging.nuspec +microsoft.identitymodel.protocols.openidconnect\5.2.0\lib\net45\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.2.0\lib\net451\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.2.0\microsoft.identitymodel.protocols.openidconnect.5.2.0.nupkg.sha512 +microsoft.identitymodel.protocols.openidconnect\5.2.0\microsoft.identitymodel.protocols.openidconnect.nuspec +microsoft.identitymodel.protocols.wsfederation\5.2.0\lib\net45\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.2.0\lib\net451\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.2.0\microsoft.identitymodel.protocols.wsfederation.5.2.0.nupkg.sha512 +microsoft.identitymodel.protocols.wsfederation\5.2.0\microsoft.identitymodel.protocols.wsfederation.nuspec +microsoft.identitymodel.protocols\5.2.0\lib\net45\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.2.0\lib\net451\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.2.0\microsoft.identitymodel.protocols.5.2.0.nupkg.sha512 +microsoft.identitymodel.protocols\5.2.0\microsoft.identitymodel.protocols.nuspec +microsoft.identitymodel.tokens.saml\5.2.0\lib\net45\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.2.0\lib\net451\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.2.0\microsoft.identitymodel.tokens.saml.5.2.0.nupkg.sha512 +microsoft.identitymodel.tokens.saml\5.2.0\microsoft.identitymodel.tokens.saml.nuspec +microsoft.identitymodel.tokens\5.2.0\lib\net45\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.2.0\lib\net451\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.2.0\microsoft.identitymodel.tokens.5.2.0.nupkg.sha512 +microsoft.identitymodel.tokens\5.2.0\microsoft.identitymodel.tokens.nuspec +microsoft.identitymodel.xml\5.2.0\lib\net45\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.2.0\lib\net451\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.2.0\microsoft.identitymodel.xml.5.2.0.nupkg.sha512 +microsoft.identitymodel.xml\5.2.0\microsoft.identitymodel.xml.nuspec +microsoft.net.http.headers\2.1.1\.signature.p7s +microsoft.net.http.headers\2.1.1\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll +microsoft.net.http.headers\2.1.1\microsoft.net.http.headers.2.1.1.nupkg.sha512 +microsoft.net.http.headers\2.1.1\microsoft.net.http.headers.nuspec +microsoft.netcore.app\2.1.1\.signature.p7s +microsoft.netcore.app\2.1.1\build\netcoreapp2.1\Microsoft.NETCore.App.PlatformManifest.txt +microsoft.netcore.app\2.1.1\build\netcoreapp2.1\Microsoft.NETCore.App.props +microsoft.netcore.app\2.1.1\build\netcoreapp2.1\Microsoft.NETCore.App.targets +microsoft.netcore.app\2.1.1\LICENSE.TXT +microsoft.netcore.app\2.1.1\microsoft.netcore.app.2.1.1.nupkg.sha512 +microsoft.netcore.app\2.1.1\microsoft.netcore.app.nuspec +microsoft.netcore.app\2.1.1\Microsoft.NETCore.App.versions.txt +microsoft.netcore.app\2.1.1\ref\netcoreapp\_._ +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\Microsoft.CSharp.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\Microsoft.VisualBasic.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\Microsoft.Win32.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\mscorlib.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\netstandard.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.AppContext.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Buffers.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.Concurrent.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.Immutable.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.NonGeneric.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Collections.Specialized.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.Annotations.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.DataAnnotations.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.EventBasedAsync.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ComponentModel.TypeConverter.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Configuration.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Console.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Core.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Data.Common.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Data.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Contracts.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Debug.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.DiagnosticSource.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.FileVersionInfo.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Process.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.StackTrace.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.TextWriterTraceListener.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Tools.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.TraceSource.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Diagnostics.Tracing.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Drawing.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Drawing.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Dynamic.Runtime.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Globalization.Calendars.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Globalization.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Globalization.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Compression.Brotli.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Compression.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Compression.FileSystem.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Compression.ZipFile.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.FileSystem.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.FileSystem.DriveInfo.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.FileSystem.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.FileSystem.Watcher.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.IsolatedStorage.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.MemoryMappedFiles.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.Pipes.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.IO.UnmanagedMemoryStream.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Linq.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Linq.Expressions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Linq.Parallel.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Linq.Queryable.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Memory.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Http.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.HttpListener.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Mail.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.NameResolution.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.NetworkInformation.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Ping.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Requests.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Security.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.ServicePoint.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.Sockets.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebClient.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebHeaderCollection.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebProxy.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebSockets.Client.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Net.WebSockets.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Numerics.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Numerics.Vectors.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ObjectModel.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.DispatchProxy.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Emit.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Emit.ILGeneration.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Emit.Lightweight.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Metadata.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Reflection.TypeExtensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Resources.Reader.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Resources.ResourceManager.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Resources.Writer.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.CompilerServices.VisualC.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Handles.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.InteropServices.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.InteropServices.RuntimeInformation.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.InteropServices.WindowsRuntime.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Loader.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Numerics.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.Formatters.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.Json.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Runtime.Serialization.Xml.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Claims.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.Algorithms.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.Csp.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.Encoding.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.Primitives.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Cryptography.X509Certificates.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.Principal.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Security.SecureString.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ServiceModel.Web.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ServiceProcess.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Text.Encoding.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Text.Encoding.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Text.RegularExpressions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Overlapped.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Tasks.Dataflow.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Tasks.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Tasks.Extensions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Tasks.Parallel.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Thread.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.ThreadPool.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Threading.Timer.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Transactions.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Transactions.Local.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.ValueTuple.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Web.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Web.HttpUtility.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Windows.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.Linq.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.ReaderWriter.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.Serialization.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XDocument.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XmlDocument.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XmlSerializer.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XPath.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\System.Xml.XPath.XDocument.dll +microsoft.netcore.app\2.1.1\ref\netcoreapp2.1\WindowsBase.dll +microsoft.netcore.app\2.1.1\runtime.json +microsoft.netcore.app\2.1.1\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnetapphost\2.1.1\.signature.p7s +microsoft.netcore.dotnetapphost\2.1.1\LICENSE.TXT +microsoft.netcore.dotnetapphost\2.1.1\microsoft.netcore.dotnetapphost.2.1.1.nupkg.sha512 +microsoft.netcore.dotnetapphost\2.1.1\microsoft.netcore.dotnetapphost.nuspec +microsoft.netcore.dotnetapphost\2.1.1\runtime.json +microsoft.netcore.dotnetapphost\2.1.1\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostpolicy\2.1.1\.signature.p7s +microsoft.netcore.dotnethostpolicy\2.1.1\LICENSE.TXT +microsoft.netcore.dotnethostpolicy\2.1.1\microsoft.netcore.dotnethostpolicy.2.1.1.nupkg.sha512 +microsoft.netcore.dotnethostpolicy\2.1.1\microsoft.netcore.dotnethostpolicy.nuspec +microsoft.netcore.dotnethostpolicy\2.1.1\runtime.json +microsoft.netcore.dotnethostpolicy\2.1.1\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostresolver\2.1.1\.signature.p7s +microsoft.netcore.dotnethostresolver\2.1.1\LICENSE.TXT +microsoft.netcore.dotnethostresolver\2.1.1\microsoft.netcore.dotnethostresolver.2.1.1.nupkg.sha512 +microsoft.netcore.dotnethostresolver\2.1.1\microsoft.netcore.dotnethostresolver.nuspec +microsoft.netcore.dotnethostresolver\2.1.1\runtime.json +microsoft.netcore.dotnethostresolver\2.1.1\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\1.0.1\dotnet_library_license.txt +microsoft.netcore.platforms\1.0.1\lib\netstandard1.0\_._ +microsoft.netcore.platforms\1.0.1\microsoft.netcore.platforms.1.0.1.nupkg.sha512 +microsoft.netcore.platforms\1.0.1\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\1.0.1\runtime.json +microsoft.netcore.platforms\1.0.1\ThirdPartyNotices.txt +microsoft.netcore.platforms\1.0.2\dotnet_library_license.txt +microsoft.netcore.platforms\1.0.2\lib\netstandard1.0\_._ +microsoft.netcore.platforms\1.0.2\microsoft.netcore.platforms.1.0.2.nupkg.sha512 +microsoft.netcore.platforms\1.0.2\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\1.0.2\runtime.json +microsoft.netcore.platforms\1.0.2\ThirdPartyNotices.txt +microsoft.netcore.platforms\1.1.0\dotnet_library_license.txt +microsoft.netcore.platforms\1.1.0\lib\netstandard1.0\_._ +microsoft.netcore.platforms\1.1.0\microsoft.netcore.platforms.1.1.0.nupkg.sha512 +microsoft.netcore.platforms\1.1.0\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\1.1.0\runtime.json +microsoft.netcore.platforms\1.1.0\ThirdPartyNotices.txt +microsoft.netcore.platforms\2.0.0\lib\netstandard1.0\_._ +microsoft.netcore.platforms\2.0.0\LICENSE.TXT +microsoft.netcore.platforms\2.0.0\microsoft.netcore.platforms.2.0.0.nupkg.sha512 +microsoft.netcore.platforms\2.0.0\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\2.0.0\runtime.json +microsoft.netcore.platforms\2.0.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\2.0.0\useSharedDesignerContext.txt +microsoft.netcore.platforms\2.0.0\version.txt +microsoft.netcore.platforms\2.1.0\.signature.p7s +microsoft.netcore.platforms\2.1.0\lib\netstandard1.0\_._ +microsoft.netcore.platforms\2.1.0\LICENSE.TXT +microsoft.netcore.platforms\2.1.0\microsoft.netcore.platforms.2.1.0.nupkg.sha512 +microsoft.netcore.platforms\2.1.0\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\2.1.0\runtime.json +microsoft.netcore.platforms\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\2.1.0\useSharedDesignerContext.txt +microsoft.netcore.platforms\2.1.0\version.txt +microsoft.netcore.targets\1.0.1\dotnet_library_license.txt +microsoft.netcore.targets\1.0.1\lib\netstandard1.0\_._ +microsoft.netcore.targets\1.0.1\microsoft.netcore.targets.1.0.1.nupkg.sha512 +microsoft.netcore.targets\1.0.1\microsoft.netcore.targets.nuspec +microsoft.netcore.targets\1.0.1\runtime.json +microsoft.netcore.targets\1.0.1\ThirdPartyNotices.txt +microsoft.netcore.targets\1.1.0\dotnet_library_license.txt +microsoft.netcore.targets\1.1.0\lib\netstandard1.0\_._ +microsoft.netcore.targets\1.1.0\microsoft.netcore.targets.1.1.0.nupkg.sha512 +microsoft.netcore.targets\1.1.0\microsoft.netcore.targets.nuspec +microsoft.netcore.targets\1.1.0\runtime.json +microsoft.netcore.targets\1.1.0\ThirdPartyNotices.txt +microsoft.netcore.targets\2.0.0\lib\netstandard1.0\_._ +microsoft.netcore.targets\2.0.0\LICENSE.TXT +microsoft.netcore.targets\2.0.0\microsoft.netcore.targets.2.0.0.nupkg.sha512 +microsoft.netcore.targets\2.0.0\microsoft.netcore.targets.nuspec +microsoft.netcore.targets\2.0.0\runtime.json +microsoft.netcore.targets\2.0.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.targets\2.0.0\useSharedDesignerContext.txt +microsoft.netcore.targets\2.0.0\version.txt +microsoft.rest.clientruntime.azure\3.3.7\lib\net452\Microsoft.Rest.ClientRuntime.Azure.dll +microsoft.rest.clientruntime.azure\3.3.7\lib\net452\Microsoft.Rest.ClientRuntime.Azure.runtimeconfig.json +microsoft.rest.clientruntime.azure\3.3.7\lib\netstandard1.4\Microsoft.Rest.ClientRuntime.Azure.dll +microsoft.rest.clientruntime.azure\3.3.7\lib\netstandard1.4\Microsoft.Rest.ClientRuntime.Azure.runtimeconfig.json +microsoft.rest.clientruntime.azure\3.3.7\microsoft.rest.clientruntime.azure.3.3.7.nupkg.sha512 +microsoft.rest.clientruntime.azure\3.3.7\microsoft.rest.clientruntime.azure.nuspec +microsoft.rest.clientruntime\2.3.8\lib\net452\Microsoft.Rest.ClientRuntime.dll +microsoft.rest.clientruntime\2.3.8\lib\net452\Microsoft.Rest.ClientRuntime.runtimeconfig.json +microsoft.rest.clientruntime\2.3.8\lib\netstandard1.4\Microsoft.Rest.ClientRuntime.dll +microsoft.rest.clientruntime\2.3.8\lib\netstandard1.4\Microsoft.Rest.ClientRuntime.runtimeconfig.json +microsoft.rest.clientruntime\2.3.8\microsoft.rest.clientruntime.2.3.8.nupkg.sha512 +microsoft.rest.clientruntime\2.3.8\microsoft.rest.clientruntime.nuspec +microsoft.visualstudio.web.browserlink\2.1.1\.signature.p7s +microsoft.visualstudio.web.browserlink\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.BrowserLink.dll +microsoft.visualstudio.web.browserlink\2.1.1\microsoft.visualstudio.web.browserlink.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.browserlink\2.1.1\microsoft.visualstudio.web.browserlink.nuspec +microsoft.visualstudio.web.codegeneration.contracts\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.1\microsoft.visualstudio.web.codegeneration.contracts.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.1\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.1\microsoft.visualstudio.web.codegeneration.core.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.1\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.1\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.design\2.1.1\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.1\microsoft.visualstudio.web.codegeneration.design.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.1\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.1\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.xml +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.1\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.1\microsoft.visualstudio.web.codegeneration.templating.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.1\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.1\microsoft.visualstudio.web.codegeneration.utils.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.1\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.1\microsoft.visualstudio.web.codegeneration.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.1\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\microsoft.visualstudio.web.codegenerators.mvc.2.1.1.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.1\Templates\ViewGenerator\List.cshtml +microsoft.win32.primitives\4.0.1\dotnet_library_license.txt +microsoft.win32.primitives\4.0.1\lib\MonoAndroid10\_._ +microsoft.win32.primitives\4.0.1\lib\MonoTouch10\_._ +microsoft.win32.primitives\4.0.1\lib\net46\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.0.1\lib\xamarinios10\_._ +microsoft.win32.primitives\4.0.1\lib\xamarinmac20\_._ +microsoft.win32.primitives\4.0.1\lib\xamarintvos10\_._ +microsoft.win32.primitives\4.0.1\lib\xamarinwatchos10\_._ +microsoft.win32.primitives\4.0.1\microsoft.win32.primitives.4.0.1.nupkg.sha512 +microsoft.win32.primitives\4.0.1\microsoft.win32.primitives.nuspec +microsoft.win32.primitives\4.0.1\ref\MonoAndroid10\_._ +microsoft.win32.primitives\4.0.1\ref\MonoTouch10\_._ +microsoft.win32.primitives\4.0.1\ref\net46\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.0.1\ref\netstandard1.3\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.0.1\ref\xamarinios10\_._ +microsoft.win32.primitives\4.0.1\ref\xamarinmac20\_._ +microsoft.win32.primitives\4.0.1\ref\xamarintvos10\_._ +microsoft.win32.primitives\4.0.1\ref\xamarinwatchos10\_._ +microsoft.win32.primitives\4.0.1\ThirdPartyNotices.txt +microsoft.win32.primitives\4.3.0\dotnet_library_license.txt +microsoft.win32.primitives\4.3.0\lib\MonoAndroid10\_._ +microsoft.win32.primitives\4.3.0\lib\MonoTouch10\_._ +microsoft.win32.primitives\4.3.0\lib\net46\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.3.0\lib\xamarinios10\_._ +microsoft.win32.primitives\4.3.0\lib\xamarinmac20\_._ +microsoft.win32.primitives\4.3.0\lib\xamarintvos10\_._ +microsoft.win32.primitives\4.3.0\lib\xamarinwatchos10\_._ +microsoft.win32.primitives\4.3.0\microsoft.win32.primitives.4.3.0.nupkg.sha512 +microsoft.win32.primitives\4.3.0\microsoft.win32.primitives.nuspec +microsoft.win32.primitives\4.3.0\ref\MonoAndroid10\_._ +microsoft.win32.primitives\4.3.0\ref\MonoTouch10\_._ +microsoft.win32.primitives\4.3.0\ref\net46\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.3.0\ref\netstandard1.3\Microsoft.Win32.Primitives.dll +microsoft.win32.primitives\4.3.0\ref\xamarinios10\_._ +microsoft.win32.primitives\4.3.0\ref\xamarinmac20\_._ +microsoft.win32.primitives\4.3.0\ref\xamarintvos10\_._ +microsoft.win32.primitives\4.3.0\ref\xamarinwatchos10\_._ +microsoft.win32.primitives\4.3.0\ThirdPartyNotices.txt +microsoft.win32.registry\4.3.0\dotnet_library_license.txt +microsoft.win32.registry\4.3.0\lib\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\microsoft.win32.registry.4.3.0.nupkg.sha512 +microsoft.win32.registry\4.3.0\microsoft.win32.registry.nuspec +microsoft.win32.registry\4.3.0\ref\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\ref\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\runtimes\unix\lib\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\runtimes\win\lib\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\runtimes\win\lib\netcore50\_._ +microsoft.win32.registry\4.3.0\runtimes\win\lib\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.3.0\ThirdPartyNotices.txt +microsoft.win32.registry\4.5.0\.signature.p7s +microsoft.win32.registry\4.5.0\lib\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\lib\net461\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\lib\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\lib\netstandard2.0\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\LICENSE.TXT +microsoft.win32.registry\4.5.0\microsoft.win32.registry.4.5.0.nupkg.sha512 +microsoft.win32.registry\4.5.0\microsoft.win32.registry.nuspec +microsoft.win32.registry\4.5.0\ref\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\ref\net461\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\ref\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\ref\netstandard2.0\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\unix\lib\netstandard2.0\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\win\lib\net46\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\win\lib\net461\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\win\lib\netstandard1.3\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\runtimes\win\lib\netstandard2.0\Microsoft.Win32.Registry.dll +microsoft.win32.registry\4.5.0\THIRD-PARTY-NOTICES.TXT +microsoft.win32.registry\4.5.0\useSharedDesignerContext.txt +microsoft.win32.registry\4.5.0\version.txt +netstandard.library\1.6.0\dotnet_library_license.txt +netstandard.library\1.6.0\netstandard.library.1.6.0.nupkg.sha512 +netstandard.library\1.6.0\netstandard.library.nuspec +netstandard.library\1.6.0\ThirdPartyNotices.txt +netstandard.library\1.6.1\dotnet_library_license.txt +netstandard.library\1.6.1\netstandard.library.1.6.1.nupkg.sha512 +netstandard.library\1.6.1\netstandard.library.nuspec +netstandard.library\1.6.1\ThirdPartyNotices.txt +netstandard.library\2.0.3\build\netstandard2.0\NETStandard.Library.targets +netstandard.library\2.0.3\build\netstandard2.0\ref\Microsoft.Win32.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\mscorlib.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.AppContext.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Concurrent.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.NonGeneric.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Specialized.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.Composition.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.EventBasedAsync.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.TypeConverter.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Console.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Core.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Data.Common.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Data.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Contracts.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Debug.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.FileVersionInfo.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Process.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.StackTrace.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.TextWriterTraceListener.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Tools.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.TraceSource.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Tracing.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Drawing.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Drawing.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Dynamic.Runtime.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.Calendars.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.Extensions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.FileSystem.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.ZipFile.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.DriveInfo.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.Watcher.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.IsolatedStorage.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.MemoryMappedFiles.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Pipes.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.UnmanagedMemoryStream.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Expressions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Parallel.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Queryable.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Http.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.NameResolution.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.NetworkInformation.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Ping.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Requests.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Security.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Sockets.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebHeaderCollection.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebSockets.Client.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebSockets.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Numerics.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ObjectModel.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Reflection.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Reflection.Extensions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Reflection.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.Reader.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.ResourceManager.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.Writer.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.CompilerServices.VisualC.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Extensions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Handles.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.InteropServices.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.InteropServices.RuntimeInformation.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Numerics.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Formatters.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Json.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Xml.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Claims.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Algorithms.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Csp.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Encoding.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Primitives.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.X509Certificates.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Principal.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.SecureString.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ServiceModel.Web.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Text.Encoding.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Text.Encoding.Extensions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Text.RegularExpressions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Overlapped.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Tasks.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Tasks.Parallel.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Thread.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.ThreadPool.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Timer.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Transactions.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.ValueTuple.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Web.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Windows.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.Linq.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.ReaderWriter.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.Serialization.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XDocument.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XmlDocument.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XmlSerializer.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XPath.dll +netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XPath.XDocument.dll +netstandard.library\2.0.3\lib\netstandard1.0\_._ +netstandard.library\2.0.3\LICENSE.TXT +netstandard.library\2.0.3\netstandard.library.2.0.3.nupkg.sha512 +netstandard.library\2.0.3\netstandard.library.nuspec +netstandard.library\2.0.3\THIRD-PARTY-NOTICES.TXT +newtonsoft.json.bson\1.0.1\lib\net45\Newtonsoft.Json.Bson.dll +newtonsoft.json.bson\1.0.1\lib\netstandard1.3\Newtonsoft.Json.Bson.dll +newtonsoft.json.bson\1.0.1\newtonsoft.json.bson.1.0.1.nupkg.sha512 +newtonsoft.json.bson\1.0.1\newtonsoft.json.bson.nuspec +newtonsoft.json\10.0.1\lib\net20\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\net35\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\net40\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\net45\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\netstandard1.0\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\netstandard1.3\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\lib\portable-net45+win8+wpa81+wp8\Newtonsoft.Json.dll +newtonsoft.json\10.0.1\newtonsoft.json.10.0.1.nupkg.sha512 +newtonsoft.json\10.0.1\newtonsoft.json.nuspec +newtonsoft.json\10.0.1\tools\install.ps1 +newtonsoft.json\11.0.2\lib\net20\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\net35\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\net40\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\net45\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\netstandard1.0\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\netstandard1.3\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\netstandard2.0\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\portable-net40+sl5+win8+wp8+wpa81\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\lib\portable-net45+win8+wp8+wpa81\Newtonsoft.Json.dll +newtonsoft.json\11.0.2\LICENSE.md +newtonsoft.json\11.0.2\newtonsoft.json.11.0.2.nupkg.sha512 +newtonsoft.json\11.0.2\newtonsoft.json.nuspec +newtonsoft.json\9.0.1\lib\net20\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\net35\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\net40\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\net45\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\netstandard1.0\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll +newtonsoft.json\9.0.1\newtonsoft.json.9.0.1.nupkg.sha512 +newtonsoft.json\9.0.1\newtonsoft.json.nuspec +newtonsoft.json\9.0.1\tools\install.ps1 +nuget.frameworks\4.7.0\.signature.p7s +nuget.frameworks\4.7.0\lib\net40\NuGet.Frameworks.dll +nuget.frameworks\4.7.0\lib\net46\NuGet.Frameworks.dll +nuget.frameworks\4.7.0\lib\netstandard1.6\NuGet.Frameworks.dll +nuget.frameworks\4.7.0\nuget.frameworks.4.7.0.nupkg.sha512 +nuget.frameworks\4.7.0\nuget.frameworks.nuspec +remotion.linq\2.2.0\lib\net35\Remotion.Linq.dll +remotion.linq\2.2.0\lib\net40\Remotion.Linq.dll +remotion.linq\2.2.0\lib\net45\Remotion.Linq.dll +remotion.linq\2.2.0\lib\netstandard1.0\Remotion.Linq.dll +remotion.linq\2.2.0\lib\portable-net45+win+wpa81+wp80\Remotion.Linq.dll +remotion.linq\2.2.0\remotion.linq.2.2.0.nupkg.sha512 +remotion.linq\2.2.0\remotion.linq.nuspec +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\debian.8-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\fedora.23-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\fedora.24-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.native.system.data.sqlclient.sni\4.4.0\LICENSE.TXT +runtime.native.system.data.sqlclient.sni\4.4.0\runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512 +runtime.native.system.data.sqlclient.sni\4.4.0\runtime.native.system.data.sqlclient.sni.nuspec +runtime.native.system.data.sqlclient.sni\4.4.0\THIRD-PARTY-NOTICES.TXT +runtime.native.system.data.sqlclient.sni\4.4.0\useSharedDesignerContext.txt +runtime.native.system.data.sqlclient.sni\4.4.0\version.txt +runtime.native.system.io.compression\4.1.0\dotnet_library_license.txt +runtime.native.system.io.compression\4.1.0\lib\netstandard1.0\_._ +runtime.native.system.io.compression\4.1.0\runtime.native.system.io.compression.4.1.0.nupkg.sha512 +runtime.native.system.io.compression\4.1.0\runtime.native.system.io.compression.nuspec +runtime.native.system.io.compression\4.1.0\ThirdPartyNotices.txt +runtime.native.system.io.compression\4.3.0\dotnet_library_license.txt +runtime.native.system.io.compression\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.io.compression\4.3.0\runtime.native.system.io.compression.4.3.0.nupkg.sha512 +runtime.native.system.io.compression\4.3.0\runtime.native.system.io.compression.nuspec +runtime.native.system.io.compression\4.3.0\ThirdPartyNotices.txt +runtime.native.system.net.http\4.0.1\dotnet_library_license.txt +runtime.native.system.net.http\4.0.1\lib\netstandard1.0\_._ +runtime.native.system.net.http\4.0.1\runtime.native.system.net.http.4.0.1.nupkg.sha512 +runtime.native.system.net.http\4.0.1\runtime.native.system.net.http.nuspec +runtime.native.system.net.http\4.0.1\ThirdPartyNotices.txt +runtime.native.system.net.http\4.3.0\dotnet_library_license.txt +runtime.native.system.net.http\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.net.http\4.3.0\runtime.native.system.net.http.4.3.0.nupkg.sha512 +runtime.native.system.net.http\4.3.0\runtime.native.system.net.http.nuspec +runtime.native.system.net.http\4.3.0\ThirdPartyNotices.txt +runtime.native.system.net.security\4.3.0\dotnet_library_license.txt +runtime.native.system.net.security\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.net.security\4.3.0\runtime.native.system.net.security.4.3.0.nupkg.sha512 +runtime.native.system.net.security\4.3.0\runtime.native.system.net.security.nuspec +runtime.native.system.net.security\4.3.0\ThirdPartyNotices.txt +runtime.native.system.security.cryptography.apple\4.3.0\dotnet_library_license.txt +runtime.native.system.security.cryptography.apple\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.security.cryptography.apple\4.3.0\runtime.native.system.security.cryptography.apple.4.3.0.nupkg.sha512 +runtime.native.system.security.cryptography.apple\4.3.0\runtime.native.system.security.cryptography.apple.nuspec +runtime.native.system.security.cryptography.apple\4.3.0\ThirdPartyNotices.txt +runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.native.system.security.cryptography.openssl\4.3.0\lib\netstandard1.0\_._ +runtime.native.system.security.cryptography.openssl\4.3.0\runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.native.system.security.cryptography.openssl\4.3.0\runtime.native.system.security.cryptography.openssl.nuspec +runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.native.system.security.cryptography\4.0.0\dotnet_library_license.txt +runtime.native.system.security.cryptography\4.0.0\lib\netstandard1.0\_._ +runtime.native.system.security.cryptography\4.0.0\runtime.native.system.security.cryptography.4.0.0.nupkg.sha512 +runtime.native.system.security.cryptography\4.0.0\runtime.native.system.security.cryptography.nuspec +runtime.native.system.security.cryptography\4.0.0\ThirdPartyNotices.txt +runtime.native.system\4.0.0\dotnet_library_license.txt +runtime.native.system\4.0.0\lib\netstandard1.0\_._ +runtime.native.system\4.0.0\runtime.native.system.4.0.0.nupkg.sha512 +runtime.native.system\4.0.0\runtime.native.system.nuspec +runtime.native.system\4.0.0\ThirdPartyNotices.txt +runtime.native.system\4.3.0\dotnet_library_license.txt +runtime.native.system\4.3.0\lib\netstandard1.0\_._ +runtime.native.system\4.3.0\runtime.native.system.4.3.0.nupkg.sha512 +runtime.native.system\4.3.0\runtime.native.system.nuspec +runtime.native.system\4.3.0\ThirdPartyNotices.txt +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\opensuse.13.2-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\opensuse.42.1-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\dotnet_library_license.txt +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.4.3.0.nupkg.sha512 +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.nuspec +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\runtimes\osx.10.10-x64\native\System.Security.Cryptography.Native.Apple.dylib +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\ThirdPartyNotices.txt +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\osx.10.10-x64\native\System.Security.Cryptography.Native.OpenSsl.dylib +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\rhel.7-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\ubuntu.14.04-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\ubuntu.16.04-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512 +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.nuspec +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\runtimes\ubuntu.16.10-x64\native\System.Security.Cryptography.Native.OpenSsl.so +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\dotnet_library_license.txt +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-arm64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512 +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-arm64.runtime.native.system.data.sqlclient.sni.nuspec +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\runtimes\win-arm64\native\sni.dll +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\ThirdPartyNotices.txt +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\useSharedDesignerContext.txt +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\version.txt +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\dotnet_library_license.txt +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512 +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x64.runtime.native.system.data.sqlclient.sni.nuspec +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\runtimes\win-x64\native\sni.dll +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\ThirdPartyNotices.txt +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\useSharedDesignerContext.txt +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\version.txt +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\dotnet_library_license.txt +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x86.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512 +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\runtime.win-x86.runtime.native.system.data.sqlclient.sni.nuspec +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\runtimes\win-x86\native\sni.dll +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\ThirdPartyNotices.txt +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\useSharedDesignerContext.txt +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\version.txt +sqlitepclraw.bundle_green\1.1.11\build\wp8\SQLitePCLRaw.bundle_green.targets +sqlitepclraw.bundle_green\1.1.11\build\wp80\arm\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\build\wp80\arm\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\build\wp80\x86\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\build\wp80\x86\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\MonoAndroid\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\MonoAndroid\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\net35\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\net35\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\net40\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\net40\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\net45\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\net45\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\netcoreapp\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\netcoreapp\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\netstandard1.1\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\netstandard1.1\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net40+sl5+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net40+sl5+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\uap10.0\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\uap10.0\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\win8\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\win8\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\win81\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\win81\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\wp8\_._ +sqlitepclraw.bundle_green\1.1.11\lib\wpa81\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\wpa81\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\Xamarin.iOS10\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\Xamarin.iOS10\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\lib\Xamarin.Mac20\SQLitePCLRaw.batteries_green.dll +sqlitepclraw.bundle_green\1.1.11\lib\Xamarin.Mac20\SQLitePCLRaw.batteries_v2.dll +sqlitepclraw.bundle_green\1.1.11\sqlitepclraw.bundle_green.1.1.11.nupkg.sha512 +sqlitepclraw.bundle_green\1.1.11\sqlitepclraw.bundle_green.nuspec +sqlitepclraw.core\1.1.11\lib\MonoAndroid\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\net35\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\net40\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\net45\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\netstandard1.0\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\netstandard1.1\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\portable-net40+sl5+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\uap10.0\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\win8\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\win81\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\wpa81\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\Xamarin.iOS10\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\lib\Xamarin.Mac20\SQLitePCLRaw.core.dll +sqlitepclraw.core\1.1.11\sqlitepclraw.core.1.1.11.nupkg.sha512 +sqlitepclraw.core\1.1.11\sqlitepclraw.core.nuspec +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\build\net35\SQLitePCLRaw.lib.e_sqlite3.linux.targets +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\lib\net35\_._ +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\lib\netstandard1.0\_._ +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\lib\netstandard2.0\_._ +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\alpine-x64\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-arm\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-arm64\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-armel\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-musl-x64\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-x64\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\runtimes\linux-x86\native\libe_sqlite3.so +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\sqlitepclraw.lib.e_sqlite3.linux.1.1.11.nupkg.sha512 +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\sqlitepclraw.lib.e_sqlite3.linux.nuspec +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\build\net35\SQLitePCLRaw.lib.e_sqlite3.osx.targets +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\build\Xamarin.Mac20\SQLitePCLRaw.lib.e_sqlite3.osx.targets +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\lib\net35\_._ +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\lib\netstandard1.0\_._ +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\lib\netstandard2.0\_._ +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\lib\Xamarin.Mac20\_._ +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\runtimes\osx-x64\native\libe_sqlite3.dylib +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\sqlitepclraw.lib.e_sqlite3.osx.1.1.11.nupkg.sha512 +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\sqlitepclraw.lib.e_sqlite3.osx.nuspec +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\build\net35\SQLitePCLRaw.lib.e_sqlite3.v110_xp.targets +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\lib\net35\_._ +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\lib\netstandard1.0\_._ +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\lib\netstandard2.0\_._ +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\runtimes\win-x64\native\e_sqlite3.dll +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\runtimes\win-x86\native\e_sqlite3.dll +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\runtimes\win8-arm\native\e_sqlite3.dll +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\sqlitepclraw.lib.e_sqlite3.v110_xp.1.1.11.nupkg.sha512 +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\sqlitepclraw.lib.e_sqlite3.v110_xp.nuspec +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\lib\netstandard1.1\SQLitePCLRaw.provider.e_sqlite3.dll +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\sqlitepclraw.provider.e_sqlite3.netstandard11.1.1.11.nupkg.sha512 +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\sqlitepclraw.provider.e_sqlite3.netstandard11.nuspec +stackexchange.redis.strongname\1.2.4\lib\net45\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.4\lib\net46\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.4\lib\netstandard1.5\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.4\stackexchange.redis.strongname.1.2.4.nupkg.sha512 +stackexchange.redis.strongname\1.2.4\stackexchange.redis.strongname.nuspec +system.appcontext\4.1.0\dotnet_library_license.txt +system.appcontext\4.1.0\lib\MonoAndroid10\_._ +system.appcontext\4.1.0\lib\MonoTouch10\_._ +system.appcontext\4.1.0\lib\net46\System.AppContext.dll +system.appcontext\4.1.0\lib\net463\System.AppContext.dll +system.appcontext\4.1.0\lib\netcore50\System.AppContext.dll +system.appcontext\4.1.0\lib\netstandard1.6\System.AppContext.dll +system.appcontext\4.1.0\lib\xamarinios10\_._ +system.appcontext\4.1.0\lib\xamarinmac20\_._ +system.appcontext\4.1.0\lib\xamarintvos10\_._ +system.appcontext\4.1.0\lib\xamarinwatchos10\_._ +system.appcontext\4.1.0\ref\MonoAndroid10\_._ +system.appcontext\4.1.0\ref\MonoTouch10\_._ +system.appcontext\4.1.0\ref\net46\System.AppContext.dll +system.appcontext\4.1.0\ref\net463\System.AppContext.dll +system.appcontext\4.1.0\ref\netstandard\_._ +system.appcontext\4.1.0\ref\netstandard1.3\System.AppContext.dll +system.appcontext\4.1.0\ref\netstandard1.6\System.AppContext.dll +system.appcontext\4.1.0\ref\xamarinios10\_._ +system.appcontext\4.1.0\ref\xamarinmac20\_._ +system.appcontext\4.1.0\ref\xamarintvos10\_._ +system.appcontext\4.1.0\ref\xamarinwatchos10\_._ +system.appcontext\4.1.0\runtimes\aot\lib\netcore50\System.AppContext.dll +system.appcontext\4.1.0\system.appcontext.4.1.0.nupkg.sha512 +system.appcontext\4.1.0\system.appcontext.nuspec +system.appcontext\4.1.0\ThirdPartyNotices.txt +system.appcontext\4.3.0\dotnet_library_license.txt +system.appcontext\4.3.0\lib\MonoAndroid10\_._ +system.appcontext\4.3.0\lib\MonoTouch10\_._ +system.appcontext\4.3.0\lib\net46\System.AppContext.dll +system.appcontext\4.3.0\lib\net463\System.AppContext.dll +system.appcontext\4.3.0\lib\netcore50\System.AppContext.dll +system.appcontext\4.3.0\lib\netstandard1.6\System.AppContext.dll +system.appcontext\4.3.0\lib\xamarinios10\_._ +system.appcontext\4.3.0\lib\xamarinmac20\_._ +system.appcontext\4.3.0\lib\xamarintvos10\_._ +system.appcontext\4.3.0\lib\xamarinwatchos10\_._ +system.appcontext\4.3.0\ref\MonoAndroid10\_._ +system.appcontext\4.3.0\ref\MonoTouch10\_._ +system.appcontext\4.3.0\ref\net46\System.AppContext.dll +system.appcontext\4.3.0\ref\net463\System.AppContext.dll +system.appcontext\4.3.0\ref\netstandard\_._ +system.appcontext\4.3.0\ref\netstandard1.3\System.AppContext.dll +system.appcontext\4.3.0\ref\netstandard1.6\System.AppContext.dll +system.appcontext\4.3.0\ref\xamarinios10\_._ +system.appcontext\4.3.0\ref\xamarinmac20\_._ +system.appcontext\4.3.0\ref\xamarintvos10\_._ +system.appcontext\4.3.0\ref\xamarinwatchos10\_._ +system.appcontext\4.3.0\runtimes\aot\lib\netcore50\System.AppContext.dll +system.appcontext\4.3.0\system.appcontext.4.3.0.nupkg.sha512 +system.appcontext\4.3.0\system.appcontext.nuspec +system.appcontext\4.3.0\ThirdPartyNotices.txt +system.buffers\4.0.0\dotnet_library_license.txt +system.buffers\4.0.0\lib\netstandard1.1\.xml +system.buffers\4.0.0\lib\netstandard1.1\System.Buffers.dll +system.buffers\4.0.0\system.buffers.4.0.0.nupkg.sha512 +system.buffers\4.0.0\system.buffers.nuspec +system.buffers\4.0.0\ThirdPartyNotices.txt +system.buffers\4.3.0\dotnet_library_license.txt +system.buffers\4.3.0\lib\netstandard1.1\.xml +system.buffers\4.3.0\lib\netstandard1.1\System.Buffers.dll +system.buffers\4.3.0\system.buffers.4.3.0.nupkg.sha512 +system.buffers\4.3.0\system.buffers.nuspec +system.buffers\4.3.0\ThirdPartyNotices.txt +system.buffers\4.5.0\.signature.p7s +system.buffers\4.5.0\lib\netcoreapp2.0\_._ +system.buffers\4.5.0\lib\netstandard1.1\System.Buffers.dll +system.buffers\4.5.0\lib\netstandard2.0\System.Buffers.dll +system.buffers\4.5.0\lib\uap10.0.16299\_._ +system.buffers\4.5.0\LICENSE.TXT +system.buffers\4.5.0\ref\net45\System.Buffers.dll +system.buffers\4.5.0\ref\netcoreapp2.0\_._ +system.buffers\4.5.0\ref\netstandard1.1\System.Buffers.dll +system.buffers\4.5.0\ref\netstandard2.0\System.Buffers.dll +system.buffers\4.5.0\ref\uap10.0.16299\_._ +system.buffers\4.5.0\system.buffers.4.5.0.nupkg.sha512 +system.buffers\4.5.0\system.buffers.nuspec +system.buffers\4.5.0\THIRD-PARTY-NOTICES.TXT +system.buffers\4.5.0\useSharedDesignerContext.txt +system.buffers\4.5.0\version.txt +system.collections.concurrent\4.0.12\dotnet_library_license.txt +system.collections.concurrent\4.0.12\lib\MonoAndroid10\_._ +system.collections.concurrent\4.0.12\lib\MonoTouch10\_._ +system.collections.concurrent\4.0.12\lib\net45\_._ +system.collections.concurrent\4.0.12\lib\netcore50\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\lib\netstandard1.3\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\lib\portable-net45+win8+wpa81\_._ +system.collections.concurrent\4.0.12\lib\win8\_._ +system.collections.concurrent\4.0.12\lib\wpa81\_._ +system.collections.concurrent\4.0.12\lib\xamarinios10\_._ +system.collections.concurrent\4.0.12\lib\xamarinmac20\_._ +system.collections.concurrent\4.0.12\lib\xamarintvos10\_._ +system.collections.concurrent\4.0.12\lib\xamarinwatchos10\_._ +system.collections.concurrent\4.0.12\ref\MonoAndroid10\_._ +system.collections.concurrent\4.0.12\ref\MonoTouch10\_._ +system.collections.concurrent\4.0.12\ref\net45\_._ +system.collections.concurrent\4.0.12\ref\netcore50\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\ref\netstandard1.1\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\ref\netstandard1.3\System.Collections.Concurrent.dll +system.collections.concurrent\4.0.12\ref\portable-net45+win8+wpa81\_._ +system.collections.concurrent\4.0.12\ref\win8\_._ +system.collections.concurrent\4.0.12\ref\wpa81\_._ +system.collections.concurrent\4.0.12\ref\xamarinios10\_._ +system.collections.concurrent\4.0.12\ref\xamarinmac20\_._ +system.collections.concurrent\4.0.12\ref\xamarintvos10\_._ +system.collections.concurrent\4.0.12\ref\xamarinwatchos10\_._ +system.collections.concurrent\4.0.12\system.collections.concurrent.4.0.12.nupkg.sha512 +system.collections.concurrent\4.0.12\system.collections.concurrent.nuspec +system.collections.concurrent\4.0.12\ThirdPartyNotices.txt +system.collections.concurrent\4.3.0\dotnet_library_license.txt +system.collections.concurrent\4.3.0\lib\MonoAndroid10\_._ +system.collections.concurrent\4.3.0\lib\MonoTouch10\_._ +system.collections.concurrent\4.3.0\lib\net45\_._ +system.collections.concurrent\4.3.0\lib\netcore50\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\lib\netstandard1.3\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.collections.concurrent\4.3.0\lib\win8\_._ +system.collections.concurrent\4.3.0\lib\wpa81\_._ +system.collections.concurrent\4.3.0\lib\xamarinios10\_._ +system.collections.concurrent\4.3.0\lib\xamarinmac20\_._ +system.collections.concurrent\4.3.0\lib\xamarintvos10\_._ +system.collections.concurrent\4.3.0\lib\xamarinwatchos10\_._ +system.collections.concurrent\4.3.0\ref\MonoAndroid10\_._ +system.collections.concurrent\4.3.0\ref\MonoTouch10\_._ +system.collections.concurrent\4.3.0\ref\net45\_._ +system.collections.concurrent\4.3.0\ref\netcore50\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\ref\netstandard1.1\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\ref\netstandard1.3\System.Collections.Concurrent.dll +system.collections.concurrent\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.collections.concurrent\4.3.0\ref\win8\_._ +system.collections.concurrent\4.3.0\ref\wpa81\_._ +system.collections.concurrent\4.3.0\ref\xamarinios10\_._ +system.collections.concurrent\4.3.0\ref\xamarinmac20\_._ +system.collections.concurrent\4.3.0\ref\xamarintvos10\_._ +system.collections.concurrent\4.3.0\ref\xamarinwatchos10\_._ +system.collections.concurrent\4.3.0\system.collections.concurrent.4.3.0.nupkg.sha512 +system.collections.concurrent\4.3.0\system.collections.concurrent.nuspec +system.collections.concurrent\4.3.0\ThirdPartyNotices.txt +system.collections.immutable\1.3.0\dotnet_library_license.txt +system.collections.immutable\1.3.0\lib\netstandard1.0\System.Collections.Immutable.dll +system.collections.immutable\1.3.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll +system.collections.immutable\1.3.0\system.collections.immutable.1.3.0.nupkg.sha512 +system.collections.immutable\1.3.0\system.collections.immutable.nuspec +system.collections.immutable\1.3.0\ThirdPartyNotices.txt +system.collections.immutable\1.3.1\dotnet_library_license.txt +system.collections.immutable\1.3.1\lib\netstandard1.0\System.Collections.Immutable.dll +system.collections.immutable\1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll +system.collections.immutable\1.3.1\system.collections.immutable.1.3.1.nupkg.sha512 +system.collections.immutable\1.3.1\system.collections.immutable.nuspec +system.collections.immutable\1.3.1\ThirdPartyNotices.txt +system.collections.immutable\1.5.0\.signature.p7s +system.collections.immutable\1.5.0\lib\netstandard1.0\System.Collections.Immutable.dll +system.collections.immutable\1.5.0\lib\netstandard1.3\System.Collections.Immutable.dll +system.collections.immutable\1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll +system.collections.immutable\1.5.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll +system.collections.immutable\1.5.0\LICENSE.TXT +system.collections.immutable\1.5.0\system.collections.immutable.1.5.0.nupkg.sha512 +system.collections.immutable\1.5.0\system.collections.immutable.nuspec +system.collections.immutable\1.5.0\THIRD-PARTY-NOTICES.TXT +system.collections.immutable\1.5.0\useSharedDesignerContext.txt +system.collections.immutable\1.5.0\version.txt +system.collections.nongeneric\4.3.0\dotnet_library_license.txt +system.collections.nongeneric\4.3.0\lib\MonoAndroid10\_._ +system.collections.nongeneric\4.3.0\lib\MonoTouch10\_._ +system.collections.nongeneric\4.3.0\lib\net46\System.Collections.NonGeneric.dll +system.collections.nongeneric\4.3.0\lib\netstandard1.3\System.Collections.NonGeneric.dll +system.collections.nongeneric\4.3.0\lib\xamarinios10\_._ +system.collections.nongeneric\4.3.0\lib\xamarinmac20\_._ +system.collections.nongeneric\4.3.0\lib\xamarintvos10\_._ +system.collections.nongeneric\4.3.0\lib\xamarinwatchos10\_._ +system.collections.nongeneric\4.3.0\ref\MonoAndroid10\_._ +system.collections.nongeneric\4.3.0\ref\MonoTouch10\_._ +system.collections.nongeneric\4.3.0\ref\net46\System.Collections.NonGeneric.dll +system.collections.nongeneric\4.3.0\ref\netstandard1.3\System.Collections.NonGeneric.dll +system.collections.nongeneric\4.3.0\ref\xamarinios10\_._ +system.collections.nongeneric\4.3.0\ref\xamarinmac20\_._ +system.collections.nongeneric\4.3.0\ref\xamarintvos10\_._ +system.collections.nongeneric\4.3.0\ref\xamarinwatchos10\_._ +system.collections.nongeneric\4.3.0\system.collections.nongeneric.4.3.0.nupkg.sha512 +system.collections.nongeneric\4.3.0\system.collections.nongeneric.nuspec +system.collections.nongeneric\4.3.0\ThirdPartyNotices.txt +system.collections.specialized\4.3.0\dotnet_library_license.txt +system.collections.specialized\4.3.0\lib\MonoAndroid10\_._ +system.collections.specialized\4.3.0\lib\MonoTouch10\_._ +system.collections.specialized\4.3.0\lib\net46\System.Collections.Specialized.dll +system.collections.specialized\4.3.0\lib\netstandard1.3\System.Collections.Specialized.dll +system.collections.specialized\4.3.0\lib\xamarinios10\_._ +system.collections.specialized\4.3.0\lib\xamarinmac20\_._ +system.collections.specialized\4.3.0\lib\xamarintvos10\_._ +system.collections.specialized\4.3.0\lib\xamarinwatchos10\_._ +system.collections.specialized\4.3.0\ref\MonoAndroid10\_._ +system.collections.specialized\4.3.0\ref\MonoTouch10\_._ +system.collections.specialized\4.3.0\ref\net46\System.Collections.Specialized.dll +system.collections.specialized\4.3.0\ref\netstandard1.3\System.Collections.Specialized.dll +system.collections.specialized\4.3.0\ref\xamarinios10\_._ +system.collections.specialized\4.3.0\ref\xamarinmac20\_._ +system.collections.specialized\4.3.0\ref\xamarintvos10\_._ +system.collections.specialized\4.3.0\ref\xamarinwatchos10\_._ +system.collections.specialized\4.3.0\system.collections.specialized.4.3.0.nupkg.sha512 +system.collections.specialized\4.3.0\system.collections.specialized.nuspec +system.collections.specialized\4.3.0\ThirdPartyNotices.txt +system.collections\4.0.11\dotnet_library_license.txt +system.collections\4.0.11\lib\MonoAndroid10\_._ +system.collections\4.0.11\lib\MonoTouch10\_._ +system.collections\4.0.11\lib\net45\_._ +system.collections\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.collections\4.0.11\lib\win8\_._ +system.collections\4.0.11\lib\wp80\_._ +system.collections\4.0.11\lib\wpa81\_._ +system.collections\4.0.11\lib\xamarinios10\_._ +system.collections\4.0.11\lib\xamarinmac20\_._ +system.collections\4.0.11\lib\xamarintvos10\_._ +system.collections\4.0.11\lib\xamarinwatchos10\_._ +system.collections\4.0.11\ref\MonoAndroid10\_._ +system.collections\4.0.11\ref\MonoTouch10\_._ +system.collections\4.0.11\ref\net45\_._ +system.collections\4.0.11\ref\netcore50\System.Collections.dll +system.collections\4.0.11\ref\netstandard1.0\System.Collections.dll +system.collections\4.0.11\ref\netstandard1.3\System.Collections.dll +system.collections\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.collections\4.0.11\ref\win8\_._ +system.collections\4.0.11\ref\wp80\_._ +system.collections\4.0.11\ref\wpa81\_._ +system.collections\4.0.11\ref\xamarinios10\_._ +system.collections\4.0.11\ref\xamarinmac20\_._ +system.collections\4.0.11\ref\xamarintvos10\_._ +system.collections\4.0.11\ref\xamarinwatchos10\_._ +system.collections\4.0.11\system.collections.4.0.11.nupkg.sha512 +system.collections\4.0.11\system.collections.nuspec +system.collections\4.0.11\ThirdPartyNotices.txt +system.collections\4.3.0\dotnet_library_license.txt +system.collections\4.3.0\lib\MonoAndroid10\_._ +system.collections\4.3.0\lib\MonoTouch10\_._ +system.collections\4.3.0\lib\net45\_._ +system.collections\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.collections\4.3.0\lib\win8\_._ +system.collections\4.3.0\lib\wp80\_._ +system.collections\4.3.0\lib\wpa81\_._ +system.collections\4.3.0\lib\xamarinios10\_._ +system.collections\4.3.0\lib\xamarinmac20\_._ +system.collections\4.3.0\lib\xamarintvos10\_._ +system.collections\4.3.0\lib\xamarinwatchos10\_._ +system.collections\4.3.0\ref\MonoAndroid10\_._ +system.collections\4.3.0\ref\MonoTouch10\_._ +system.collections\4.3.0\ref\net45\_._ +system.collections\4.3.0\ref\netcore50\System.Collections.dll +system.collections\4.3.0\ref\netstandard1.0\System.Collections.dll +system.collections\4.3.0\ref\netstandard1.3\System.Collections.dll +system.collections\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.collections\4.3.0\ref\win8\_._ +system.collections\4.3.0\ref\wp80\_._ +system.collections\4.3.0\ref\wpa81\_._ +system.collections\4.3.0\ref\xamarinios10\_._ +system.collections\4.3.0\ref\xamarinmac20\_._ +system.collections\4.3.0\ref\xamarintvos10\_._ +system.collections\4.3.0\ref\xamarinwatchos10\_._ +system.collections\4.3.0\system.collections.4.3.0.nupkg.sha512 +system.collections\4.3.0\system.collections.nuspec +system.collections\4.3.0\ThirdPartyNotices.txt +system.componentmodel.annotations\4.5.0\.signature.p7s +system.componentmodel.annotations\4.5.0\lib\MonoAndroid10\_._ +system.componentmodel.annotations\4.5.0\lib\MonoTouch10\_._ +system.componentmodel.annotations\4.5.0\lib\net45\_._ +system.componentmodel.annotations\4.5.0\lib\net461\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\lib\netcore50\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\lib\netcoreapp2.0\_._ +system.componentmodel.annotations\4.5.0\lib\netstandard1.4\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\lib\netstandard2.0\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\lib\portable-net45+win8\_._ +system.componentmodel.annotations\4.5.0\lib\uap10.0.16299\_._ +system.componentmodel.annotations\4.5.0\lib\win8\_._ +system.componentmodel.annotations\4.5.0\lib\xamarinios10\_._ +system.componentmodel.annotations\4.5.0\lib\xamarinmac20\_._ +system.componentmodel.annotations\4.5.0\lib\xamarintvos10\_._ +system.componentmodel.annotations\4.5.0\lib\xamarinwatchos10\_._ +system.componentmodel.annotations\4.5.0\LICENSE.TXT +system.componentmodel.annotations\4.5.0\ref\MonoAndroid10\_._ +system.componentmodel.annotations\4.5.0\ref\MonoTouch10\_._ +system.componentmodel.annotations\4.5.0\ref\net45\_._ +system.componentmodel.annotations\4.5.0\ref\net461\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netcore50\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netcoreapp2.0\_._ +system.componentmodel.annotations\4.5.0\ref\netstandard1.1\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netstandard1.3\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netstandard1.4\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\netstandard2.0\System.ComponentModel.Annotations.dll +system.componentmodel.annotations\4.5.0\ref\portable-net45+win8\_._ +system.componentmodel.annotations\4.5.0\ref\uap10.0.16299\_._ +system.componentmodel.annotations\4.5.0\ref\win8\_._ +system.componentmodel.annotations\4.5.0\ref\xamarinios10\_._ +system.componentmodel.annotations\4.5.0\ref\xamarinmac20\_._ +system.componentmodel.annotations\4.5.0\ref\xamarintvos10\_._ +system.componentmodel.annotations\4.5.0\ref\xamarinwatchos10\_._ +system.componentmodel.annotations\4.5.0\system.componentmodel.annotations.4.5.0.nupkg.sha512 +system.componentmodel.annotations\4.5.0\system.componentmodel.annotations.nuspec +system.componentmodel.annotations\4.5.0\THIRD-PARTY-NOTICES.TXT +system.componentmodel.annotations\4.5.0\useSharedDesignerContext.txt +system.componentmodel.annotations\4.5.0\version.txt +system.componentmodel.primitives\4.3.0\dotnet_library_license.txt +system.componentmodel.primitives\4.3.0\lib\MonoAndroid10\_._ +system.componentmodel.primitives\4.3.0\lib\MonoTouch10\_._ +system.componentmodel.primitives\4.3.0\lib\net45\System.ComponentModel.Primitives.dll +system.componentmodel.primitives\4.3.0\lib\netstandard1.0\System.ComponentModel.Primitives.dll +system.componentmodel.primitives\4.3.0\lib\xamarinios10\_._ +system.componentmodel.primitives\4.3.0\lib\xamarinmac20\_._ +system.componentmodel.primitives\4.3.0\lib\xamarintvos10\_._ +system.componentmodel.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.componentmodel.primitives\4.3.0\ref\MonoAndroid10\_._ +system.componentmodel.primitives\4.3.0\ref\MonoTouch10\_._ +system.componentmodel.primitives\4.3.0\ref\net45\System.ComponentModel.Primitives.dll +system.componentmodel.primitives\4.3.0\ref\netstandard1.0\System.ComponentModel.Primitives.dll +system.componentmodel.primitives\4.3.0\ref\xamarinios10\_._ +system.componentmodel.primitives\4.3.0\ref\xamarinmac20\_._ +system.componentmodel.primitives\4.3.0\ref\xamarintvos10\_._ +system.componentmodel.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.componentmodel.primitives\4.3.0\system.componentmodel.primitives.4.3.0.nupkg.sha512 +system.componentmodel.primitives\4.3.0\system.componentmodel.primitives.nuspec +system.componentmodel.primitives\4.3.0\ThirdPartyNotices.txt +system.componentmodel.typeconverter\4.3.0\dotnet_library_license.txt +system.componentmodel.typeconverter\4.3.0\lib\MonoAndroid10\_._ +system.componentmodel.typeconverter\4.3.0\lib\MonoTouch10\_._ +system.componentmodel.typeconverter\4.3.0\lib\net45\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\lib\net462\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\lib\netstandard1.0\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\lib\netstandard1.5\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\lib\xamarinios10\_._ +system.componentmodel.typeconverter\4.3.0\lib\xamarinmac20\_._ +system.componentmodel.typeconverter\4.3.0\lib\xamarintvos10\_._ +system.componentmodel.typeconverter\4.3.0\lib\xamarinwatchos10\_._ +system.componentmodel.typeconverter\4.3.0\ref\MonoAndroid10\_._ +system.componentmodel.typeconverter\4.3.0\ref\MonoTouch10\_._ +system.componentmodel.typeconverter\4.3.0\ref\net45\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\ref\net462\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\ref\netstandard1.0\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\ref\netstandard1.5\System.ComponentModel.TypeConverter.dll +system.componentmodel.typeconverter\4.3.0\ref\xamarinios10\_._ +system.componentmodel.typeconverter\4.3.0\ref\xamarinmac20\_._ +system.componentmodel.typeconverter\4.3.0\ref\xamarintvos10\_._ +system.componentmodel.typeconverter\4.3.0\ref\xamarinwatchos10\_._ +system.componentmodel.typeconverter\4.3.0\system.componentmodel.typeconverter.4.3.0.nupkg.sha512 +system.componentmodel.typeconverter\4.3.0\system.componentmodel.typeconverter.nuspec +system.componentmodel.typeconverter\4.3.0\ThirdPartyNotices.txt +system.componentmodel\4.3.0\dotnet_library_license.txt +system.componentmodel\4.3.0\lib\MonoAndroid10\_._ +system.componentmodel\4.3.0\lib\MonoTouch10\_._ +system.componentmodel\4.3.0\lib\net45\_._ +system.componentmodel\4.3.0\lib\netcore50\System.ComponentModel.dll +system.componentmodel\4.3.0\lib\netstandard1.3\System.ComponentModel.dll +system.componentmodel\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.componentmodel\4.3.0\lib\win8\_._ +system.componentmodel\4.3.0\lib\wp80\_._ +system.componentmodel\4.3.0\lib\wpa81\_._ +system.componentmodel\4.3.0\lib\xamarinios10\_._ +system.componentmodel\4.3.0\lib\xamarinmac20\_._ +system.componentmodel\4.3.0\lib\xamarintvos10\_._ +system.componentmodel\4.3.0\lib\xamarinwatchos10\_._ +system.componentmodel\4.3.0\ref\MonoAndroid10\_._ +system.componentmodel\4.3.0\ref\MonoTouch10\_._ +system.componentmodel\4.3.0\ref\net45\_._ +system.componentmodel\4.3.0\ref\netcore50\System.ComponentModel.dll +system.componentmodel\4.3.0\ref\netstandard1.0\System.ComponentModel.dll +system.componentmodel\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.componentmodel\4.3.0\ref\win8\_._ +system.componentmodel\4.3.0\ref\wp80\_._ +system.componentmodel\4.3.0\ref\wpa81\_._ +system.componentmodel\4.3.0\ref\xamarinios10\_._ +system.componentmodel\4.3.0\ref\xamarinmac20\_._ +system.componentmodel\4.3.0\ref\xamarintvos10\_._ +system.componentmodel\4.3.0\ref\xamarinwatchos10\_._ +system.componentmodel\4.3.0\system.componentmodel.4.3.0.nupkg.sha512 +system.componentmodel\4.3.0\system.componentmodel.nuspec +system.componentmodel\4.3.0\ThirdPartyNotices.txt +system.composition.attributedmodel\1.0.31\dotnet_library_license.txt +system.composition.attributedmodel\1.0.31\lib\netstandard1.0\System.Composition.AttributedModel.dll +system.composition.attributedmodel\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll +system.composition.attributedmodel\1.0.31\system.composition.attributedmodel.1.0.31.nupkg.sha512 +system.composition.attributedmodel\1.0.31\system.composition.attributedmodel.nuspec +system.composition.attributedmodel\1.0.31\ThirdPartyNotices.txt +system.composition.convention\1.0.31\dotnet_library_license.txt +system.composition.convention\1.0.31\lib\netstandard1.0\System.Composition.Convention.dll +system.composition.convention\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll +system.composition.convention\1.0.31\system.composition.convention.1.0.31.nupkg.sha512 +system.composition.convention\1.0.31\system.composition.convention.nuspec +system.composition.convention\1.0.31\ThirdPartyNotices.txt +system.composition.hosting\1.0.31\dotnet_library_license.txt +system.composition.hosting\1.0.31\lib\netstandard1.0\System.Composition.Hosting.dll +system.composition.hosting\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll +system.composition.hosting\1.0.31\system.composition.hosting.1.0.31.nupkg.sha512 +system.composition.hosting\1.0.31\system.composition.hosting.nuspec +system.composition.hosting\1.0.31\ThirdPartyNotices.txt +system.composition.runtime\1.0.31\dotnet_library_license.txt +system.composition.runtime\1.0.31\lib\netstandard1.0\System.Composition.Runtime.dll +system.composition.runtime\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll +system.composition.runtime\1.0.31\system.composition.runtime.1.0.31.nupkg.sha512 +system.composition.runtime\1.0.31\system.composition.runtime.nuspec +system.composition.runtime\1.0.31\ThirdPartyNotices.txt +system.composition.typedparts\1.0.31\dotnet_library_license.txt +system.composition.typedparts\1.0.31\lib\netstandard1.0\System.Composition.TypedParts.dll +system.composition.typedparts\1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll +system.composition.typedparts\1.0.31\system.composition.typedparts.1.0.31.nupkg.sha512 +system.composition.typedparts\1.0.31\system.composition.typedparts.nuspec +system.composition.typedparts\1.0.31\ThirdPartyNotices.txt +system.composition\1.0.31\dotnet_library_license.txt +system.composition\1.0.31\system.composition.1.0.31.nupkg.sha512 +system.composition\1.0.31\system.composition.nuspec +system.composition\1.0.31\ThirdPartyNotices.txt +system.console\4.0.0\dotnet_library_license.txt +system.console\4.0.0\lib\MonoAndroid10\_._ +system.console\4.0.0\lib\MonoTouch10\_._ +system.console\4.0.0\lib\net46\System.Console.dll +system.console\4.0.0\lib\xamarinios10\_._ +system.console\4.0.0\lib\xamarinmac20\_._ +system.console\4.0.0\lib\xamarintvos10\_._ +system.console\4.0.0\lib\xamarinwatchos10\_._ +system.console\4.0.0\ref\MonoAndroid10\_._ +system.console\4.0.0\ref\MonoTouch10\_._ +system.console\4.0.0\ref\net46\System.Console.dll +system.console\4.0.0\ref\netstandard1.3\System.Console.dll +system.console\4.0.0\ref\xamarinios10\_._ +system.console\4.0.0\ref\xamarinmac20\_._ +system.console\4.0.0\ref\xamarintvos10\_._ +system.console\4.0.0\ref\xamarinwatchos10\_._ +system.console\4.0.0\system.console.4.0.0.nupkg.sha512 +system.console\4.0.0\system.console.nuspec +system.console\4.0.0\ThirdPartyNotices.txt +system.console\4.3.0\dotnet_library_license.txt +system.console\4.3.0\lib\MonoAndroid10\_._ +system.console\4.3.0\lib\MonoTouch10\_._ +system.console\4.3.0\lib\net46\System.Console.dll +system.console\4.3.0\lib\xamarinios10\_._ +system.console\4.3.0\lib\xamarinmac20\_._ +system.console\4.3.0\lib\xamarintvos10\_._ +system.console\4.3.0\lib\xamarinwatchos10\_._ +system.console\4.3.0\ref\MonoAndroid10\_._ +system.console\4.3.0\ref\MonoTouch10\_._ +system.console\4.3.0\ref\net46\System.Console.dll +system.console\4.3.0\ref\netstandard1.3\System.Console.dll +system.console\4.3.0\ref\xamarinios10\_._ +system.console\4.3.0\ref\xamarinmac20\_._ +system.console\4.3.0\ref\xamarintvos10\_._ +system.console\4.3.0\ref\xamarinwatchos10\_._ +system.console\4.3.0\system.console.4.3.0.nupkg.sha512 +system.console\4.3.0\system.console.nuspec +system.console\4.3.0\ThirdPartyNotices.txt +system.data.sqlclient\4.5.1\.signature.p7s +system.data.sqlclient\4.5.1\lib\MonoAndroid10\_._ +system.data.sqlclient\4.5.1\lib\MonoTouch10\_._ +system.data.sqlclient\4.5.1\lib\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\netstandard1.2\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\lib\xamarinios10\_._ +system.data.sqlclient\4.5.1\lib\xamarinmac20\_._ +system.data.sqlclient\4.5.1\lib\xamarintvos10\_._ +system.data.sqlclient\4.5.1\lib\xamarinwatchos10\_._ +system.data.sqlclient\4.5.1\LICENSE.TXT +system.data.sqlclient\4.5.1\ref\MonoAndroid10\_._ +system.data.sqlclient\4.5.1\ref\MonoTouch10\_._ +system.data.sqlclient\4.5.1\ref\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\netstandard1.2\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\ref\xamarinios10\_._ +system.data.sqlclient\4.5.1\ref\xamarinmac20\_._ +system.data.sqlclient\4.5.1\ref\xamarintvos10\_._ +system.data.sqlclient\4.5.1\ref\xamarinwatchos10\_._ +system.data.sqlclient\4.5.1\runtimes\unix\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\unix\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\unix\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\runtimes\win\lib\uap10.0.16299\System.Data.SqlClient.dll +system.data.sqlclient\4.5.1\system.data.sqlclient.4.5.1.nupkg.sha512 +system.data.sqlclient\4.5.1\system.data.sqlclient.nuspec +system.data.sqlclient\4.5.1\THIRD-PARTY-NOTICES.TXT +system.data.sqlclient\4.5.1\useSharedDesignerContext.txt +system.data.sqlclient\4.5.1\version.txt +system.diagnostics.contracts\4.3.0\dotnet_library_license.txt +system.diagnostics.contracts\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.contracts\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.contracts\4.3.0\lib\net45\_._ +system.diagnostics.contracts\4.3.0\lib\netcore50\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\lib\netstandard1.0\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.contracts\4.3.0\lib\win8\_._ +system.diagnostics.contracts\4.3.0\lib\wp80\_._ +system.diagnostics.contracts\4.3.0\lib\wpa81\_._ +system.diagnostics.contracts\4.3.0\lib\xamarinios10\_._ +system.diagnostics.contracts\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.contracts\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.contracts\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.contracts\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.contracts\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.contracts\4.3.0\ref\net45\_._ +system.diagnostics.contracts\4.3.0\ref\netcore50\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\ref\netstandard1.0\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.contracts\4.3.0\ref\win8\_._ +system.diagnostics.contracts\4.3.0\ref\wp80\_._ +system.diagnostics.contracts\4.3.0\ref\wpa81\_._ +system.diagnostics.contracts\4.3.0\ref\xamarinios10\_._ +system.diagnostics.contracts\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.contracts\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.contracts\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.contracts\4.3.0\runtimes\aot\lib\netcore50\System.Diagnostics.Contracts.dll +system.diagnostics.contracts\4.3.0\system.diagnostics.contracts.4.3.0.nupkg.sha512 +system.diagnostics.contracts\4.3.0\system.diagnostics.contracts.nuspec +system.diagnostics.contracts\4.3.0\ThirdPartyNotices.txt +system.diagnostics.debug\4.0.11\dotnet_library_license.txt +system.diagnostics.debug\4.0.11\lib\MonoAndroid10\_._ +system.diagnostics.debug\4.0.11\lib\MonoTouch10\_._ +system.diagnostics.debug\4.0.11\lib\net45\_._ +system.diagnostics.debug\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.debug\4.0.11\lib\win8\_._ +system.diagnostics.debug\4.0.11\lib\wp80\_._ +system.diagnostics.debug\4.0.11\lib\wpa81\_._ +system.diagnostics.debug\4.0.11\lib\xamarinios10\_._ +system.diagnostics.debug\4.0.11\lib\xamarinmac20\_._ +system.diagnostics.debug\4.0.11\lib\xamarintvos10\_._ +system.diagnostics.debug\4.0.11\lib\xamarinwatchos10\_._ +system.diagnostics.debug\4.0.11\ref\MonoAndroid10\_._ +system.diagnostics.debug\4.0.11\ref\MonoTouch10\_._ +system.diagnostics.debug\4.0.11\ref\net45\_._ +system.diagnostics.debug\4.0.11\ref\netcore50\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.0.11\ref\netstandard1.0\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.0.11\ref\netstandard1.3\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.debug\4.0.11\ref\win8\_._ +system.diagnostics.debug\4.0.11\ref\wp80\_._ +system.diagnostics.debug\4.0.11\ref\wpa81\_._ +system.diagnostics.debug\4.0.11\ref\xamarinios10\_._ +system.diagnostics.debug\4.0.11\ref\xamarinmac20\_._ +system.diagnostics.debug\4.0.11\ref\xamarintvos10\_._ +system.diagnostics.debug\4.0.11\ref\xamarinwatchos10\_._ +system.diagnostics.debug\4.0.11\system.diagnostics.debug.4.0.11.nupkg.sha512 +system.diagnostics.debug\4.0.11\system.diagnostics.debug.nuspec +system.diagnostics.debug\4.0.11\ThirdPartyNotices.txt +system.diagnostics.debug\4.3.0\dotnet_library_license.txt +system.diagnostics.debug\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.debug\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.debug\4.3.0\lib\net45\_._ +system.diagnostics.debug\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.debug\4.3.0\lib\win8\_._ +system.diagnostics.debug\4.3.0\lib\wp80\_._ +system.diagnostics.debug\4.3.0\lib\wpa81\_._ +system.diagnostics.debug\4.3.0\lib\xamarinios10\_._ +system.diagnostics.debug\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.debug\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.debug\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.debug\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.debug\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.debug\4.3.0\ref\net45\_._ +system.diagnostics.debug\4.3.0\ref\netcore50\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.3.0\ref\netstandard1.0\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.3.0\ref\netstandard1.3\System.Diagnostics.Debug.dll +system.diagnostics.debug\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.debug\4.3.0\ref\win8\_._ +system.diagnostics.debug\4.3.0\ref\wp80\_._ +system.diagnostics.debug\4.3.0\ref\wpa81\_._ +system.diagnostics.debug\4.3.0\ref\xamarinios10\_._ +system.diagnostics.debug\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.debug\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.debug\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.debug\4.3.0\system.diagnostics.debug.4.3.0.nupkg.sha512 +system.diagnostics.debug\4.3.0\system.diagnostics.debug.nuspec +system.diagnostics.debug\4.3.0\ThirdPartyNotices.txt +system.diagnostics.diagnosticsource\4.0.0\dotnet_library_license.txt +system.diagnostics.diagnosticsource\4.0.0\lib\net46\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.0.0\lib\netstandard1.1\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.0.0\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.0.0\lib\portable-net45+win8+wpa81\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.0.0\system.diagnostics.diagnosticsource.4.0.0.nupkg.sha512 +system.diagnostics.diagnosticsource\4.0.0\system.diagnostics.diagnosticsource.nuspec +system.diagnostics.diagnosticsource\4.0.0\ThirdPartyNotices.txt +system.diagnostics.diagnosticsource\4.3.0\dotnet_library_license.txt +system.diagnostics.diagnosticsource\4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.3.0\lib\netstandard1.1\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.3.0\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.3.0\lib\portable-net45+win8+wpa81\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.3.0\system.diagnostics.diagnosticsource.4.3.0.nupkg.sha512 +system.diagnostics.diagnosticsource\4.3.0\system.diagnostics.diagnosticsource.nuspec +system.diagnostics.diagnosticsource\4.3.0\ThirdPartyNotices.txt +system.diagnostics.diagnosticsource\4.4.0\lib\net45\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\lib\net46\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\lib\netcoreapp2.0\_._ +system.diagnostics.diagnosticsource\4.4.0\lib\netstandard1.1\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\lib\portable-net45+win8+wpa81\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.4.0\LICENSE.TXT +system.diagnostics.diagnosticsource\4.4.0\ref\netcoreapp2.0\_._ +system.diagnostics.diagnosticsource\4.4.0\system.diagnostics.diagnosticsource.4.4.0.nupkg.sha512 +system.diagnostics.diagnosticsource\4.4.0\system.diagnostics.diagnosticsource.nuspec +system.diagnostics.diagnosticsource\4.4.0\THIRD-PARTY-NOTICES.TXT +system.diagnostics.diagnosticsource\4.4.0\useSharedDesignerContext.txt +system.diagnostics.diagnosticsource\4.4.0\version.txt +system.diagnostics.diagnosticsource\4.5.0\.signature.p7s +system.diagnostics.diagnosticsource\4.5.0\lib\net45\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\lib\net46\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\lib\netstandard1.1\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\lib\portable-net45+win8+wpa81\System.Diagnostics.DiagnosticSource.dll +system.diagnostics.diagnosticsource\4.5.0\LICENSE.TXT +system.diagnostics.diagnosticsource\4.5.0\system.diagnostics.diagnosticsource.4.5.0.nupkg.sha512 +system.diagnostics.diagnosticsource\4.5.0\system.diagnostics.diagnosticsource.nuspec +system.diagnostics.diagnosticsource\4.5.0\THIRD-PARTY-NOTICES.TXT +system.diagnostics.diagnosticsource\4.5.0\useSharedDesignerContext.txt +system.diagnostics.diagnosticsource\4.5.0\version.txt +system.diagnostics.fileversioninfo\4.3.0\dotnet_library_license.txt +system.diagnostics.fileversioninfo\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\lib\xamarinios10\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.fileversioninfo\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\net46\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\ref\netstandard1.3\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\ref\xamarinios10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.fileversioninfo\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.fileversioninfo\4.3.0\runtimes\unix\lib\netstandard1.3\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\runtimes\win\lib\net46\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\runtimes\win\lib\netcore50\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\runtimes\win\lib\netstandard1.3\System.Diagnostics.FileVersionInfo.dll +system.diagnostics.fileversioninfo\4.3.0\system.diagnostics.fileversioninfo.4.3.0.nupkg.sha512 +system.diagnostics.fileversioninfo\4.3.0\system.diagnostics.fileversioninfo.nuspec +system.diagnostics.fileversioninfo\4.3.0\ThirdPartyNotices.txt +system.diagnostics.process\4.3.0\dotnet_library_license.txt +system.diagnostics.process\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.process\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.process\4.3.0\lib\net46\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\lib\net461\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\lib\xamarinios10\_._ +system.diagnostics.process\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.process\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.process\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.process\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.process\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.process\4.3.0\ref\net46\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\ref\net461\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\ref\netstandard1.3\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\ref\netstandard1.4\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\ref\xamarinios10\_._ +system.diagnostics.process\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.process\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.process\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.process\4.3.0\runtimes\linux\lib\netstandard1.4\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\osx\lib\netstandard1.4\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\win\lib\net46\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\win\lib\net461\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\win\lib\netstandard1.4\System.Diagnostics.Process.dll +system.diagnostics.process\4.3.0\runtimes\win7\lib\netcore50\_._ +system.diagnostics.process\4.3.0\system.diagnostics.process.4.3.0.nupkg.sha512 +system.diagnostics.process\4.3.0\system.diagnostics.process.nuspec +system.diagnostics.process\4.3.0\ThirdPartyNotices.txt +system.diagnostics.stacktrace\4.3.0\dotnet_library_license.txt +system.diagnostics.stacktrace\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.stacktrace\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.stacktrace\4.3.0\lib\net46\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\lib\netstandard1.3\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\lib\xamarinios10\_._ +system.diagnostics.stacktrace\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.stacktrace\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.stacktrace\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.stacktrace\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.stacktrace\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.stacktrace\4.3.0\ref\net46\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\ref\netstandard1.3\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\ref\xamarinios10\_._ +system.diagnostics.stacktrace\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.stacktrace\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.stacktrace\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.stacktrace\4.3.0\runtimes\aot\lib\netcore50\System.Diagnostics.StackTrace.dll +system.diagnostics.stacktrace\4.3.0\system.diagnostics.stacktrace.4.3.0.nupkg.sha512 +system.diagnostics.stacktrace\4.3.0\system.diagnostics.stacktrace.nuspec +system.diagnostics.stacktrace\4.3.0\ThirdPartyNotices.txt +system.diagnostics.tools\4.0.1\dotnet_library_license.txt +system.diagnostics.tools\4.0.1\lib\MonoAndroid10\_._ +system.diagnostics.tools\4.0.1\lib\MonoTouch10\_._ +system.diagnostics.tools\4.0.1\lib\net45\_._ +system.diagnostics.tools\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.tools\4.0.1\lib\win8\_._ +system.diagnostics.tools\4.0.1\lib\wp80\_._ +system.diagnostics.tools\4.0.1\lib\wpa81\_._ +system.diagnostics.tools\4.0.1\lib\xamarinios10\_._ +system.diagnostics.tools\4.0.1\lib\xamarinmac20\_._ +system.diagnostics.tools\4.0.1\lib\xamarintvos10\_._ +system.diagnostics.tools\4.0.1\lib\xamarinwatchos10\_._ +system.diagnostics.tools\4.0.1\ref\MonoAndroid10\_._ +system.diagnostics.tools\4.0.1\ref\MonoTouch10\_._ +system.diagnostics.tools\4.0.1\ref\net45\_._ +system.diagnostics.tools\4.0.1\ref\netcore50\System.Diagnostics.Tools.dll +system.diagnostics.tools\4.0.1\ref\netstandard1.0\System.Diagnostics.Tools.dll +system.diagnostics.tools\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.tools\4.0.1\ref\win8\_._ +system.diagnostics.tools\4.0.1\ref\wp80\_._ +system.diagnostics.tools\4.0.1\ref\wpa81\_._ +system.diagnostics.tools\4.0.1\ref\xamarinios10\_._ +system.diagnostics.tools\4.0.1\ref\xamarinmac20\_._ +system.diagnostics.tools\4.0.1\ref\xamarintvos10\_._ +system.diagnostics.tools\4.0.1\ref\xamarinwatchos10\_._ +system.diagnostics.tools\4.0.1\system.diagnostics.tools.4.0.1.nupkg.sha512 +system.diagnostics.tools\4.0.1\system.diagnostics.tools.nuspec +system.diagnostics.tools\4.0.1\ThirdPartyNotices.txt +system.diagnostics.tools\4.3.0\dotnet_library_license.txt +system.diagnostics.tools\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.tools\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.tools\4.3.0\lib\net45\_._ +system.diagnostics.tools\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.tools\4.3.0\lib\win8\_._ +system.diagnostics.tools\4.3.0\lib\wp80\_._ +system.diagnostics.tools\4.3.0\lib\wpa81\_._ +system.diagnostics.tools\4.3.0\lib\xamarinios10\_._ +system.diagnostics.tools\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.tools\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.tools\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.tools\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.tools\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.tools\4.3.0\ref\net45\_._ +system.diagnostics.tools\4.3.0\ref\netcore50\System.Diagnostics.Tools.dll +system.diagnostics.tools\4.3.0\ref\netstandard1.0\System.Diagnostics.Tools.dll +system.diagnostics.tools\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.diagnostics.tools\4.3.0\ref\win8\_._ +system.diagnostics.tools\4.3.0\ref\wp80\_._ +system.diagnostics.tools\4.3.0\ref\wpa81\_._ +system.diagnostics.tools\4.3.0\ref\xamarinios10\_._ +system.diagnostics.tools\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.tools\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.tools\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.tools\4.3.0\system.diagnostics.tools.4.3.0.nupkg.sha512 +system.diagnostics.tools\4.3.0\system.diagnostics.tools.nuspec +system.diagnostics.tools\4.3.0\ThirdPartyNotices.txt +system.diagnostics.tracing\4.1.0\dotnet_library_license.txt +system.diagnostics.tracing\4.1.0\lib\MonoAndroid10\_._ +system.diagnostics.tracing\4.1.0\lib\MonoTouch10\_._ +system.diagnostics.tracing\4.1.0\lib\net45\_._ +system.diagnostics.tracing\4.1.0\lib\net462\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\lib\portable-net45+win8+wpa81\_._ +system.diagnostics.tracing\4.1.0\lib\win8\_._ +system.diagnostics.tracing\4.1.0\lib\wpa81\_._ +system.diagnostics.tracing\4.1.0\lib\xamarinios10\_._ +system.diagnostics.tracing\4.1.0\lib\xamarinmac20\_._ +system.diagnostics.tracing\4.1.0\lib\xamarintvos10\_._ +system.diagnostics.tracing\4.1.0\lib\xamarinwatchos10\_._ +system.diagnostics.tracing\4.1.0\ref\MonoAndroid10\_._ +system.diagnostics.tracing\4.1.0\ref\MonoTouch10\_._ +system.diagnostics.tracing\4.1.0\ref\net45\_._ +system.diagnostics.tracing\4.1.0\ref\net462\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netcore50\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netstandard1.1\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netstandard1.2\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netstandard1.3\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\netstandard1.5\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.1.0\ref\portable-net45+win8+wpa81\_._ +system.diagnostics.tracing\4.1.0\ref\win8\_._ +system.diagnostics.tracing\4.1.0\ref\wpa81\_._ +system.diagnostics.tracing\4.1.0\ref\xamarinios10\_._ +system.diagnostics.tracing\4.1.0\ref\xamarinmac20\_._ +system.diagnostics.tracing\4.1.0\ref\xamarintvos10\_._ +system.diagnostics.tracing\4.1.0\ref\xamarinwatchos10\_._ +system.diagnostics.tracing\4.1.0\system.diagnostics.tracing.4.1.0.nupkg.sha512 +system.diagnostics.tracing\4.1.0\system.diagnostics.tracing.nuspec +system.diagnostics.tracing\4.1.0\ThirdPartyNotices.txt +system.diagnostics.tracing\4.3.0\dotnet_library_license.txt +system.diagnostics.tracing\4.3.0\lib\MonoAndroid10\_._ +system.diagnostics.tracing\4.3.0\lib\MonoTouch10\_._ +system.diagnostics.tracing\4.3.0\lib\net45\_._ +system.diagnostics.tracing\4.3.0\lib\net462\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.diagnostics.tracing\4.3.0\lib\win8\_._ +system.diagnostics.tracing\4.3.0\lib\wpa81\_._ +system.diagnostics.tracing\4.3.0\lib\xamarinios10\_._ +system.diagnostics.tracing\4.3.0\lib\xamarinmac20\_._ +system.diagnostics.tracing\4.3.0\lib\xamarintvos10\_._ +system.diagnostics.tracing\4.3.0\lib\xamarinwatchos10\_._ +system.diagnostics.tracing\4.3.0\ref\MonoAndroid10\_._ +system.diagnostics.tracing\4.3.0\ref\MonoTouch10\_._ +system.diagnostics.tracing\4.3.0\ref\net45\_._ +system.diagnostics.tracing\4.3.0\ref\net462\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netcore50\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netstandard1.1\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netstandard1.2\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netstandard1.3\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\netstandard1.5\System.Diagnostics.Tracing.dll +system.diagnostics.tracing\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.diagnostics.tracing\4.3.0\ref\win8\_._ +system.diagnostics.tracing\4.3.0\ref\wpa81\_._ +system.diagnostics.tracing\4.3.0\ref\xamarinios10\_._ +system.diagnostics.tracing\4.3.0\ref\xamarinmac20\_._ +system.diagnostics.tracing\4.3.0\ref\xamarintvos10\_._ +system.diagnostics.tracing\4.3.0\ref\xamarinwatchos10\_._ +system.diagnostics.tracing\4.3.0\system.diagnostics.tracing.4.3.0.nupkg.sha512 +system.diagnostics.tracing\4.3.0\system.diagnostics.tracing.nuspec +system.diagnostics.tracing\4.3.0\ThirdPartyNotices.txt +system.dynamic.runtime\4.0.11\dotnet_library_license.txt +system.dynamic.runtime\4.0.11\lib\MonoAndroid10\_._ +system.dynamic.runtime\4.0.11\lib\MonoTouch10\_._ +system.dynamic.runtime\4.0.11\lib\net45\_._ +system.dynamic.runtime\4.0.11\lib\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\lib\netstandard1.3\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.dynamic.runtime\4.0.11\lib\win8\_._ +system.dynamic.runtime\4.0.11\lib\wp80\_._ +system.dynamic.runtime\4.0.11\lib\wpa81\_._ +system.dynamic.runtime\4.0.11\lib\xamarinios10\_._ +system.dynamic.runtime\4.0.11\lib\xamarinmac20\_._ +system.dynamic.runtime\4.0.11\lib\xamarintvos10\_._ +system.dynamic.runtime\4.0.11\lib\xamarinwatchos10\_._ +system.dynamic.runtime\4.0.11\ref\MonoAndroid10\_._ +system.dynamic.runtime\4.0.11\ref\MonoTouch10\_._ +system.dynamic.runtime\4.0.11\ref\net45\_._ +system.dynamic.runtime\4.0.11\ref\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\ref\netstandard1.0\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\ref\netstandard1.3\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.dynamic.runtime\4.0.11\ref\win8\_._ +system.dynamic.runtime\4.0.11\ref\wp80\_._ +system.dynamic.runtime\4.0.11\ref\wpa81\_._ +system.dynamic.runtime\4.0.11\ref\xamarinios10\_._ +system.dynamic.runtime\4.0.11\ref\xamarinmac20\_._ +system.dynamic.runtime\4.0.11\ref\xamarintvos10\_._ +system.dynamic.runtime\4.0.11\ref\xamarinwatchos10\_._ +system.dynamic.runtime\4.0.11\runtimes\aot\lib\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.0.11\system.dynamic.runtime.4.0.11.nupkg.sha512 +system.dynamic.runtime\4.0.11\system.dynamic.runtime.nuspec +system.dynamic.runtime\4.0.11\ThirdPartyNotices.txt +system.dynamic.runtime\4.3.0\dotnet_library_license.txt +system.dynamic.runtime\4.3.0\lib\MonoAndroid10\_._ +system.dynamic.runtime\4.3.0\lib\MonoTouch10\_._ +system.dynamic.runtime\4.3.0\lib\net45\_._ +system.dynamic.runtime\4.3.0\lib\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\lib\netstandard1.3\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.dynamic.runtime\4.3.0\lib\win8\_._ +system.dynamic.runtime\4.3.0\lib\wp80\_._ +system.dynamic.runtime\4.3.0\lib\wpa81\_._ +system.dynamic.runtime\4.3.0\lib\xamarinios10\_._ +system.dynamic.runtime\4.3.0\lib\xamarinmac20\_._ +system.dynamic.runtime\4.3.0\lib\xamarintvos10\_._ +system.dynamic.runtime\4.3.0\lib\xamarinwatchos10\_._ +system.dynamic.runtime\4.3.0\ref\MonoAndroid10\_._ +system.dynamic.runtime\4.3.0\ref\MonoTouch10\_._ +system.dynamic.runtime\4.3.0\ref\net45\_._ +system.dynamic.runtime\4.3.0\ref\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\ref\netstandard1.0\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\ref\netstandard1.3\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.dynamic.runtime\4.3.0\ref\win8\_._ +system.dynamic.runtime\4.3.0\ref\wp80\_._ +system.dynamic.runtime\4.3.0\ref\wpa81\_._ +system.dynamic.runtime\4.3.0\ref\xamarinios10\_._ +system.dynamic.runtime\4.3.0\ref\xamarinmac20\_._ +system.dynamic.runtime\4.3.0\ref\xamarintvos10\_._ +system.dynamic.runtime\4.3.0\ref\xamarinwatchos10\_._ +system.dynamic.runtime\4.3.0\runtimes\aot\lib\netcore50\System.Dynamic.Runtime.dll +system.dynamic.runtime\4.3.0\system.dynamic.runtime.4.3.0.nupkg.sha512 +system.dynamic.runtime\4.3.0\system.dynamic.runtime.nuspec +system.dynamic.runtime\4.3.0\ThirdPartyNotices.txt +system.globalization.calendars\4.0.1\dotnet_library_license.txt +system.globalization.calendars\4.0.1\lib\MonoAndroid10\_._ +system.globalization.calendars\4.0.1\lib\MonoTouch10\_._ +system.globalization.calendars\4.0.1\lib\net46\System.Globalization.Calendars.dll +system.globalization.calendars\4.0.1\lib\xamarinios10\_._ +system.globalization.calendars\4.0.1\lib\xamarinmac20\_._ +system.globalization.calendars\4.0.1\lib\xamarintvos10\_._ +system.globalization.calendars\4.0.1\lib\xamarinwatchos10\_._ +system.globalization.calendars\4.0.1\ref\MonoAndroid10\_._ +system.globalization.calendars\4.0.1\ref\MonoTouch10\_._ +system.globalization.calendars\4.0.1\ref\net46\System.Globalization.Calendars.dll +system.globalization.calendars\4.0.1\ref\netstandard1.3\System.Globalization.Calendars.dll +system.globalization.calendars\4.0.1\ref\xamarinios10\_._ +system.globalization.calendars\4.0.1\ref\xamarinmac20\_._ +system.globalization.calendars\4.0.1\ref\xamarintvos10\_._ +system.globalization.calendars\4.0.1\ref\xamarinwatchos10\_._ +system.globalization.calendars\4.0.1\system.globalization.calendars.4.0.1.nupkg.sha512 +system.globalization.calendars\4.0.1\system.globalization.calendars.nuspec +system.globalization.calendars\4.0.1\ThirdPartyNotices.txt +system.globalization.calendars\4.3.0\dotnet_library_license.txt +system.globalization.calendars\4.3.0\lib\MonoAndroid10\_._ +system.globalization.calendars\4.3.0\lib\MonoTouch10\_._ +system.globalization.calendars\4.3.0\lib\net46\System.Globalization.Calendars.dll +system.globalization.calendars\4.3.0\lib\xamarinios10\_._ +system.globalization.calendars\4.3.0\lib\xamarinmac20\_._ +system.globalization.calendars\4.3.0\lib\xamarintvos10\_._ +system.globalization.calendars\4.3.0\lib\xamarinwatchos10\_._ +system.globalization.calendars\4.3.0\ref\MonoAndroid10\_._ +system.globalization.calendars\4.3.0\ref\MonoTouch10\_._ +system.globalization.calendars\4.3.0\ref\net46\System.Globalization.Calendars.dll +system.globalization.calendars\4.3.0\ref\netstandard1.3\System.Globalization.Calendars.dll +system.globalization.calendars\4.3.0\ref\xamarinios10\_._ +system.globalization.calendars\4.3.0\ref\xamarinmac20\_._ +system.globalization.calendars\4.3.0\ref\xamarintvos10\_._ +system.globalization.calendars\4.3.0\ref\xamarinwatchos10\_._ +system.globalization.calendars\4.3.0\system.globalization.calendars.4.3.0.nupkg.sha512 +system.globalization.calendars\4.3.0\system.globalization.calendars.nuspec +system.globalization.calendars\4.3.0\ThirdPartyNotices.txt +system.globalization.extensions\4.0.1\dotnet_library_license.txt +system.globalization.extensions\4.0.1\lib\MonoAndroid10\_._ +system.globalization.extensions\4.0.1\lib\MonoTouch10\_._ +system.globalization.extensions\4.0.1\lib\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\lib\xamarinios10\_._ +system.globalization.extensions\4.0.1\lib\xamarinmac20\_._ +system.globalization.extensions\4.0.1\lib\xamarintvos10\_._ +system.globalization.extensions\4.0.1\lib\xamarinwatchos10\_._ +system.globalization.extensions\4.0.1\ref\MonoAndroid10\_._ +system.globalization.extensions\4.0.1\ref\MonoTouch10\_._ +system.globalization.extensions\4.0.1\ref\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\ref\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\ref\xamarinios10\_._ +system.globalization.extensions\4.0.1\ref\xamarinmac20\_._ +system.globalization.extensions\4.0.1\ref\xamarintvos10\_._ +system.globalization.extensions\4.0.1\ref\xamarinwatchos10\_._ +system.globalization.extensions\4.0.1\runtimes\unix\lib\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\runtimes\win\lib\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\runtimes\win\lib\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.0.1\system.globalization.extensions.4.0.1.nupkg.sha512 +system.globalization.extensions\4.0.1\system.globalization.extensions.nuspec +system.globalization.extensions\4.0.1\ThirdPartyNotices.txt +system.globalization.extensions\4.3.0\dotnet_library_license.txt +system.globalization.extensions\4.3.0\lib\MonoAndroid10\_._ +system.globalization.extensions\4.3.0\lib\MonoTouch10\_._ +system.globalization.extensions\4.3.0\lib\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\lib\xamarinios10\_._ +system.globalization.extensions\4.3.0\lib\xamarinmac20\_._ +system.globalization.extensions\4.3.0\lib\xamarintvos10\_._ +system.globalization.extensions\4.3.0\lib\xamarinwatchos10\_._ +system.globalization.extensions\4.3.0\ref\MonoAndroid10\_._ +system.globalization.extensions\4.3.0\ref\MonoTouch10\_._ +system.globalization.extensions\4.3.0\ref\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\ref\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\ref\xamarinios10\_._ +system.globalization.extensions\4.3.0\ref\xamarinmac20\_._ +system.globalization.extensions\4.3.0\ref\xamarintvos10\_._ +system.globalization.extensions\4.3.0\ref\xamarinwatchos10\_._ +system.globalization.extensions\4.3.0\runtimes\unix\lib\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\runtimes\win\lib\net46\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\runtimes\win\lib\netstandard1.3\System.Globalization.Extensions.dll +system.globalization.extensions\4.3.0\system.globalization.extensions.4.3.0.nupkg.sha512 +system.globalization.extensions\4.3.0\system.globalization.extensions.nuspec +system.globalization.extensions\4.3.0\ThirdPartyNotices.txt +system.globalization\4.0.11\dotnet_library_license.txt +system.globalization\4.0.11\lib\MonoAndroid10\_._ +system.globalization\4.0.11\lib\MonoTouch10\_._ +system.globalization\4.0.11\lib\net45\_._ +system.globalization\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.globalization\4.0.11\lib\win8\_._ +system.globalization\4.0.11\lib\wp80\_._ +system.globalization\4.0.11\lib\wpa81\_._ +system.globalization\4.0.11\lib\xamarinios10\_._ +system.globalization\4.0.11\lib\xamarinmac20\_._ +system.globalization\4.0.11\lib\xamarintvos10\_._ +system.globalization\4.0.11\lib\xamarinwatchos10\_._ +system.globalization\4.0.11\ref\MonoAndroid10\_._ +system.globalization\4.0.11\ref\MonoTouch10\_._ +system.globalization\4.0.11\ref\net45\_._ +system.globalization\4.0.11\ref\netcore50\System.Globalization.dll +system.globalization\4.0.11\ref\netstandard1.0\System.Globalization.dll +system.globalization\4.0.11\ref\netstandard1.3\System.Globalization.dll +system.globalization\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.globalization\4.0.11\ref\win8\_._ +system.globalization\4.0.11\ref\wp80\_._ +system.globalization\4.0.11\ref\wpa81\_._ +system.globalization\4.0.11\ref\xamarinios10\_._ +system.globalization\4.0.11\ref\xamarinmac20\_._ +system.globalization\4.0.11\ref\xamarintvos10\_._ +system.globalization\4.0.11\ref\xamarinwatchos10\_._ +system.globalization\4.0.11\system.globalization.4.0.11.nupkg.sha512 +system.globalization\4.0.11\system.globalization.nuspec +system.globalization\4.0.11\ThirdPartyNotices.txt +system.globalization\4.3.0\dotnet_library_license.txt +system.globalization\4.3.0\lib\MonoAndroid10\_._ +system.globalization\4.3.0\lib\MonoTouch10\_._ +system.globalization\4.3.0\lib\net45\_._ +system.globalization\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.globalization\4.3.0\lib\win8\_._ +system.globalization\4.3.0\lib\wp80\_._ +system.globalization\4.3.0\lib\wpa81\_._ +system.globalization\4.3.0\lib\xamarinios10\_._ +system.globalization\4.3.0\lib\xamarinmac20\_._ +system.globalization\4.3.0\lib\xamarintvos10\_._ +system.globalization\4.3.0\lib\xamarinwatchos10\_._ +system.globalization\4.3.0\ref\MonoAndroid10\_._ +system.globalization\4.3.0\ref\MonoTouch10\_._ +system.globalization\4.3.0\ref\net45\_._ +system.globalization\4.3.0\ref\netcore50\System.Globalization.dll +system.globalization\4.3.0\ref\netstandard1.0\System.Globalization.dll +system.globalization\4.3.0\ref\netstandard1.3\System.Globalization.dll +system.globalization\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.globalization\4.3.0\ref\win8\_._ +system.globalization\4.3.0\ref\wp80\_._ +system.globalization\4.3.0\ref\wpa81\_._ +system.globalization\4.3.0\ref\xamarinios10\_._ +system.globalization\4.3.0\ref\xamarinmac20\_._ +system.globalization\4.3.0\ref\xamarintvos10\_._ +system.globalization\4.3.0\ref\xamarinwatchos10\_._ +system.globalization\4.3.0\system.globalization.4.3.0.nupkg.sha512 +system.globalization\4.3.0\system.globalization.nuspec +system.globalization\4.3.0\ThirdPartyNotices.txt +system.identitymodel.tokens.jwt\5.2.0\lib\net45\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.2.0\lib\net451\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.2.0\lib\netstandard1.4\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.2.0\system.identitymodel.tokens.jwt.5.2.0.nupkg.sha512 +system.identitymodel.tokens.jwt\5.2.0\system.identitymodel.tokens.jwt.nuspec +system.interactive.async\3.1.1\lib\net45\System.Interactive.Async.dll +system.interactive.async\3.1.1\lib\net46\System.Interactive.Async.dll +system.interactive.async\3.1.1\lib\netstandard1.0\System.Interactive.Async.dll +system.interactive.async\3.1.1\lib\netstandard1.3\System.Interactive.Async.dll +system.interactive.async\3.1.1\system.interactive.async.3.1.1.nupkg.sha512 +system.interactive.async\3.1.1\system.interactive.async.nuspec +system.io.compression.zipfile\4.0.1\dotnet_library_license.txt +system.io.compression.zipfile\4.0.1\lib\MonoAndroid10\_._ +system.io.compression.zipfile\4.0.1\lib\MonoTouch10\_._ +system.io.compression.zipfile\4.0.1\lib\net46\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.0.1\lib\netstandard1.3\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.0.1\lib\xamarinios10\_._ +system.io.compression.zipfile\4.0.1\lib\xamarinmac20\_._ +system.io.compression.zipfile\4.0.1\lib\xamarintvos10\_._ +system.io.compression.zipfile\4.0.1\lib\xamarinwatchos10\_._ +system.io.compression.zipfile\4.0.1\ref\MonoAndroid10\_._ +system.io.compression.zipfile\4.0.1\ref\MonoTouch10\_._ +system.io.compression.zipfile\4.0.1\ref\net46\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.0.1\ref\netstandard1.3\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.0.1\ref\xamarinios10\_._ +system.io.compression.zipfile\4.0.1\ref\xamarinmac20\_._ +system.io.compression.zipfile\4.0.1\ref\xamarintvos10\_._ +system.io.compression.zipfile\4.0.1\ref\xamarinwatchos10\_._ +system.io.compression.zipfile\4.0.1\system.io.compression.zipfile.4.0.1.nupkg.sha512 +system.io.compression.zipfile\4.0.1\system.io.compression.zipfile.nuspec +system.io.compression.zipfile\4.0.1\ThirdPartyNotices.txt +system.io.compression.zipfile\4.3.0\dotnet_library_license.txt +system.io.compression.zipfile\4.3.0\lib\MonoAndroid10\_._ +system.io.compression.zipfile\4.3.0\lib\MonoTouch10\_._ +system.io.compression.zipfile\4.3.0\lib\net46\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.3.0\lib\netstandard1.3\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.3.0\lib\xamarinios10\_._ +system.io.compression.zipfile\4.3.0\lib\xamarinmac20\_._ +system.io.compression.zipfile\4.3.0\lib\xamarintvos10\_._ +system.io.compression.zipfile\4.3.0\lib\xamarinwatchos10\_._ +system.io.compression.zipfile\4.3.0\ref\MonoAndroid10\_._ +system.io.compression.zipfile\4.3.0\ref\MonoTouch10\_._ +system.io.compression.zipfile\4.3.0\ref\net46\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.3.0\ref\netstandard1.3\System.IO.Compression.ZipFile.dll +system.io.compression.zipfile\4.3.0\ref\xamarinios10\_._ +system.io.compression.zipfile\4.3.0\ref\xamarinmac20\_._ +system.io.compression.zipfile\4.3.0\ref\xamarintvos10\_._ +system.io.compression.zipfile\4.3.0\ref\xamarinwatchos10\_._ +system.io.compression.zipfile\4.3.0\system.io.compression.zipfile.4.3.0.nupkg.sha512 +system.io.compression.zipfile\4.3.0\system.io.compression.zipfile.nuspec +system.io.compression.zipfile\4.3.0\ThirdPartyNotices.txt +system.io.compression\4.1.0\dotnet_library_license.txt +system.io.compression\4.1.0\lib\MonoAndroid10\_._ +system.io.compression\4.1.0\lib\MonoTouch10\_._ +system.io.compression\4.1.0\lib\net45\_._ +system.io.compression\4.1.0\lib\net46\System.IO.Compression.dll +system.io.compression\4.1.0\lib\portable-net45+win8+wpa81\_._ +system.io.compression\4.1.0\lib\win8\_._ +system.io.compression\4.1.0\lib\wpa81\_._ +system.io.compression\4.1.0\lib\xamarinios10\_._ +system.io.compression\4.1.0\lib\xamarinmac20\_._ +system.io.compression\4.1.0\lib\xamarintvos10\_._ +system.io.compression\4.1.0\lib\xamarinwatchos10\_._ +system.io.compression\4.1.0\ref\MonoAndroid10\_._ +system.io.compression\4.1.0\ref\MonoTouch10\_._ +system.io.compression\4.1.0\ref\net45\_._ +system.io.compression\4.1.0\ref\net46\System.IO.Compression.dll +system.io.compression\4.1.0\ref\netcore50\System.IO.Compression.dll +system.io.compression\4.1.0\ref\netstandard1.1\System.IO.Compression.dll +system.io.compression\4.1.0\ref\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.1.0\ref\portable-net45+win8+wpa81\_._ +system.io.compression\4.1.0\ref\win8\_._ +system.io.compression\4.1.0\ref\wpa81\_._ +system.io.compression\4.1.0\ref\xamarinios10\_._ +system.io.compression\4.1.0\ref\xamarinmac20\_._ +system.io.compression\4.1.0\ref\xamarintvos10\_._ +system.io.compression\4.1.0\ref\xamarinwatchos10\_._ +system.io.compression\4.1.0\runtimes\unix\lib\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.1.0\runtimes\win\lib\net46\System.IO.Compression.dll +system.io.compression\4.1.0\runtimes\win\lib\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.1.0\system.io.compression.4.1.0.nupkg.sha512 +system.io.compression\4.1.0\system.io.compression.nuspec +system.io.compression\4.1.0\ThirdPartyNotices.txt +system.io.compression\4.3.0\dotnet_library_license.txt +system.io.compression\4.3.0\lib\MonoAndroid10\_._ +system.io.compression\4.3.0\lib\MonoTouch10\_._ +system.io.compression\4.3.0\lib\net45\_._ +system.io.compression\4.3.0\lib\net46\System.IO.Compression.dll +system.io.compression\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.io.compression\4.3.0\lib\win8\_._ +system.io.compression\4.3.0\lib\wpa81\_._ +system.io.compression\4.3.0\lib\xamarinios10\_._ +system.io.compression\4.3.0\lib\xamarinmac20\_._ +system.io.compression\4.3.0\lib\xamarintvos10\_._ +system.io.compression\4.3.0\lib\xamarinwatchos10\_._ +system.io.compression\4.3.0\ref\MonoAndroid10\_._ +system.io.compression\4.3.0\ref\MonoTouch10\_._ +system.io.compression\4.3.0\ref\net45\_._ +system.io.compression\4.3.0\ref\net46\System.IO.Compression.dll +system.io.compression\4.3.0\ref\netcore50\System.IO.Compression.dll +system.io.compression\4.3.0\ref\netstandard1.1\System.IO.Compression.dll +system.io.compression\4.3.0\ref\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.io.compression\4.3.0\ref\win8\_._ +system.io.compression\4.3.0\ref\wpa81\_._ +system.io.compression\4.3.0\ref\xamarinios10\_._ +system.io.compression\4.3.0\ref\xamarinmac20\_._ +system.io.compression\4.3.0\ref\xamarintvos10\_._ +system.io.compression\4.3.0\ref\xamarinwatchos10\_._ +system.io.compression\4.3.0\runtimes\unix\lib\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.3.0\runtimes\win\lib\net46\System.IO.Compression.dll +system.io.compression\4.3.0\runtimes\win\lib\netstandard1.3\System.IO.Compression.dll +system.io.compression\4.3.0\system.io.compression.4.3.0.nupkg.sha512 +system.io.compression\4.3.0\system.io.compression.nuspec +system.io.compression\4.3.0\ThirdPartyNotices.txt +system.io.filesystem.primitives\4.0.1\dotnet_library_license.txt +system.io.filesystem.primitives\4.0.1\lib\MonoAndroid10\_._ +system.io.filesystem.primitives\4.0.1\lib\MonoTouch10\_._ +system.io.filesystem.primitives\4.0.1\lib\net46\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.0.1\lib\netstandard1.3\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.0.1\lib\xamarinios10\_._ +system.io.filesystem.primitives\4.0.1\lib\xamarinmac20\_._ +system.io.filesystem.primitives\4.0.1\lib\xamarintvos10\_._ +system.io.filesystem.primitives\4.0.1\lib\xamarinwatchos10\_._ +system.io.filesystem.primitives\4.0.1\ref\MonoAndroid10\_._ +system.io.filesystem.primitives\4.0.1\ref\MonoTouch10\_._ +system.io.filesystem.primitives\4.0.1\ref\net46\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.0.1\ref\netstandard1.3\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.0.1\ref\xamarinios10\_._ +system.io.filesystem.primitives\4.0.1\ref\xamarinmac20\_._ +system.io.filesystem.primitives\4.0.1\ref\xamarintvos10\_._ +system.io.filesystem.primitives\4.0.1\ref\xamarinwatchos10\_._ +system.io.filesystem.primitives\4.0.1\system.io.filesystem.primitives.4.0.1.nupkg.sha512 +system.io.filesystem.primitives\4.0.1\system.io.filesystem.primitives.nuspec +system.io.filesystem.primitives\4.0.1\ThirdPartyNotices.txt +system.io.filesystem.primitives\4.3.0\dotnet_library_license.txt +system.io.filesystem.primitives\4.3.0\lib\MonoAndroid10\_._ +system.io.filesystem.primitives\4.3.0\lib\MonoTouch10\_._ +system.io.filesystem.primitives\4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.3.0\lib\netstandard1.3\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.3.0\lib\xamarinios10\_._ +system.io.filesystem.primitives\4.3.0\lib\xamarinmac20\_._ +system.io.filesystem.primitives\4.3.0\lib\xamarintvos10\_._ +system.io.filesystem.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.io.filesystem.primitives\4.3.0\ref\MonoAndroid10\_._ +system.io.filesystem.primitives\4.3.0\ref\MonoTouch10\_._ +system.io.filesystem.primitives\4.3.0\ref\net46\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.3.0\ref\netstandard1.3\System.IO.FileSystem.Primitives.dll +system.io.filesystem.primitives\4.3.0\ref\xamarinios10\_._ +system.io.filesystem.primitives\4.3.0\ref\xamarinmac20\_._ +system.io.filesystem.primitives\4.3.0\ref\xamarintvos10\_._ +system.io.filesystem.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.io.filesystem.primitives\4.3.0\system.io.filesystem.primitives.4.3.0.nupkg.sha512 +system.io.filesystem.primitives\4.3.0\system.io.filesystem.primitives.nuspec +system.io.filesystem.primitives\4.3.0\ThirdPartyNotices.txt +system.io.filesystem\4.0.1\dotnet_library_license.txt +system.io.filesystem\4.0.1\lib\MonoAndroid10\_._ +system.io.filesystem\4.0.1\lib\MonoTouch10\_._ +system.io.filesystem\4.0.1\lib\net46\System.IO.FileSystem.dll +system.io.filesystem\4.0.1\lib\xamarinios10\_._ +system.io.filesystem\4.0.1\lib\xamarinmac20\_._ +system.io.filesystem\4.0.1\lib\xamarintvos10\_._ +system.io.filesystem\4.0.1\lib\xamarinwatchos10\_._ +system.io.filesystem\4.0.1\ref\MonoAndroid10\_._ +system.io.filesystem\4.0.1\ref\MonoTouch10\_._ +system.io.filesystem\4.0.1\ref\net46\System.IO.FileSystem.dll +system.io.filesystem\4.0.1\ref\netstandard1.3\System.IO.FileSystem.dll +system.io.filesystem\4.0.1\ref\xamarinios10\_._ +system.io.filesystem\4.0.1\ref\xamarinmac20\_._ +system.io.filesystem\4.0.1\ref\xamarintvos10\_._ +system.io.filesystem\4.0.1\ref\xamarinwatchos10\_._ +system.io.filesystem\4.0.1\system.io.filesystem.4.0.1.nupkg.sha512 +system.io.filesystem\4.0.1\system.io.filesystem.nuspec +system.io.filesystem\4.0.1\ThirdPartyNotices.txt +system.io.filesystem\4.3.0\dotnet_library_license.txt +system.io.filesystem\4.3.0\lib\MonoAndroid10\_._ +system.io.filesystem\4.3.0\lib\MonoTouch10\_._ +system.io.filesystem\4.3.0\lib\net46\System.IO.FileSystem.dll +system.io.filesystem\4.3.0\lib\xamarinios10\_._ +system.io.filesystem\4.3.0\lib\xamarinmac20\_._ +system.io.filesystem\4.3.0\lib\xamarintvos10\_._ +system.io.filesystem\4.3.0\lib\xamarinwatchos10\_._ +system.io.filesystem\4.3.0\ref\MonoAndroid10\_._ +system.io.filesystem\4.3.0\ref\MonoTouch10\_._ +system.io.filesystem\4.3.0\ref\net46\System.IO.FileSystem.dll +system.io.filesystem\4.3.0\ref\netstandard1.3\System.IO.FileSystem.dll +system.io.filesystem\4.3.0\ref\xamarinios10\_._ +system.io.filesystem\4.3.0\ref\xamarinmac20\_._ +system.io.filesystem\4.3.0\ref\xamarintvos10\_._ +system.io.filesystem\4.3.0\ref\xamarinwatchos10\_._ +system.io.filesystem\4.3.0\system.io.filesystem.4.3.0.nupkg.sha512 +system.io.filesystem\4.3.0\system.io.filesystem.nuspec +system.io.filesystem\4.3.0\ThirdPartyNotices.txt +system.io.pipelines\4.5.0\.signature.p7s +system.io.pipelines\4.5.0\lib\netcoreapp2.1\System.IO.Pipelines.dll +system.io.pipelines\4.5.0\lib\netstandard1.3\System.IO.Pipelines.dll +system.io.pipelines\4.5.0\lib\netstandard2.0\System.IO.Pipelines.dll +system.io.pipelines\4.5.0\LICENSE.TXT +system.io.pipelines\4.5.0\ref\netstandard1.3\System.IO.Pipelines.dll +system.io.pipelines\4.5.0\system.io.pipelines.4.5.0.nupkg.sha512 +system.io.pipelines\4.5.0\system.io.pipelines.nuspec +system.io.pipelines\4.5.0\THIRD-PARTY-NOTICES.TXT +system.io.pipelines\4.5.0\useSharedDesignerContext.txt +system.io.pipelines\4.5.0\version.txt +system.io\4.1.0\dotnet_library_license.txt +system.io\4.1.0\lib\MonoAndroid10\_._ +system.io\4.1.0\lib\MonoTouch10\_._ +system.io\4.1.0\lib\net45\_._ +system.io\4.1.0\lib\net462\System.IO.dll +system.io\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.io\4.1.0\lib\win8\_._ +system.io\4.1.0\lib\wp80\_._ +system.io\4.1.0\lib\wpa81\_._ +system.io\4.1.0\lib\xamarinios10\_._ +system.io\4.1.0\lib\xamarinmac20\_._ +system.io\4.1.0\lib\xamarintvos10\_._ +system.io\4.1.0\lib\xamarinwatchos10\_._ +system.io\4.1.0\ref\MonoAndroid10\_._ +system.io\4.1.0\ref\MonoTouch10\_._ +system.io\4.1.0\ref\net45\_._ +system.io\4.1.0\ref\net462\System.IO.dll +system.io\4.1.0\ref\netcore50\System.IO.dll +system.io\4.1.0\ref\netstandard1.0\System.IO.dll +system.io\4.1.0\ref\netstandard1.3\System.IO.dll +system.io\4.1.0\ref\netstandard1.5\System.IO.dll +system.io\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.io\4.1.0\ref\win8\_._ +system.io\4.1.0\ref\wp80\_._ +system.io\4.1.0\ref\wpa81\_._ +system.io\4.1.0\ref\xamarinios10\_._ +system.io\4.1.0\ref\xamarinmac20\_._ +system.io\4.1.0\ref\xamarintvos10\_._ +system.io\4.1.0\ref\xamarinwatchos10\_._ +system.io\4.1.0\system.io.4.1.0.nupkg.sha512 +system.io\4.1.0\system.io.nuspec +system.io\4.1.0\ThirdPartyNotices.txt +system.io\4.3.0\dotnet_library_license.txt +system.io\4.3.0\lib\MonoAndroid10\_._ +system.io\4.3.0\lib\MonoTouch10\_._ +system.io\4.3.0\lib\net45\_._ +system.io\4.3.0\lib\net462\System.IO.dll +system.io\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.io\4.3.0\lib\win8\_._ +system.io\4.3.0\lib\wp80\_._ +system.io\4.3.0\lib\wpa81\_._ +system.io\4.3.0\lib\xamarinios10\_._ +system.io\4.3.0\lib\xamarinmac20\_._ +system.io\4.3.0\lib\xamarintvos10\_._ +system.io\4.3.0\lib\xamarinwatchos10\_._ +system.io\4.3.0\ref\MonoAndroid10\_._ +system.io\4.3.0\ref\MonoTouch10\_._ +system.io\4.3.0\ref\net45\_._ +system.io\4.3.0\ref\net462\System.IO.dll +system.io\4.3.0\ref\netcore50\System.IO.dll +system.io\4.3.0\ref\netstandard1.0\System.IO.dll +system.io\4.3.0\ref\netstandard1.3\System.IO.dll +system.io\4.3.0\ref\netstandard1.5\System.IO.dll +system.io\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.io\4.3.0\ref\win8\_._ +system.io\4.3.0\ref\wp80\_._ +system.io\4.3.0\ref\wpa81\_._ +system.io\4.3.0\ref\xamarinios10\_._ +system.io\4.3.0\ref\xamarinmac20\_._ +system.io\4.3.0\ref\xamarintvos10\_._ +system.io\4.3.0\ref\xamarinwatchos10\_._ +system.io\4.3.0\system.io.4.3.0.nupkg.sha512 +system.io\4.3.0\system.io.nuspec +system.io\4.3.0\ThirdPartyNotices.txt +system.linq.expressions\4.1.0\dotnet_library_license.txt +system.linq.expressions\4.1.0\lib\MonoAndroid10\_._ +system.linq.expressions\4.1.0\lib\MonoTouch10\_._ +system.linq.expressions\4.1.0\lib\net45\_._ +system.linq.expressions\4.1.0\lib\net463\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\lib\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\lib\netstandard1.6\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq.expressions\4.1.0\lib\win8\_._ +system.linq.expressions\4.1.0\lib\wp80\_._ +system.linq.expressions\4.1.0\lib\wpa81\_._ +system.linq.expressions\4.1.0\lib\xamarinios10\_._ +system.linq.expressions\4.1.0\lib\xamarinmac20\_._ +system.linq.expressions\4.1.0\lib\xamarintvos10\_._ +system.linq.expressions\4.1.0\lib\xamarinwatchos10\_._ +system.linq.expressions\4.1.0\ref\MonoAndroid10\_._ +system.linq.expressions\4.1.0\ref\MonoTouch10\_._ +system.linq.expressions\4.1.0\ref\net45\_._ +system.linq.expressions\4.1.0\ref\net463\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\netstandard1.0\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\netstandard1.3\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\netstandard1.6\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq.expressions\4.1.0\ref\win8\_._ +system.linq.expressions\4.1.0\ref\wp80\_._ +system.linq.expressions\4.1.0\ref\wpa81\_._ +system.linq.expressions\4.1.0\ref\xamarinios10\_._ +system.linq.expressions\4.1.0\ref\xamarinmac20\_._ +system.linq.expressions\4.1.0\ref\xamarintvos10\_._ +system.linq.expressions\4.1.0\ref\xamarinwatchos10\_._ +system.linq.expressions\4.1.0\runtimes\aot\lib\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.1.0\system.linq.expressions.4.1.0.nupkg.sha512 +system.linq.expressions\4.1.0\system.linq.expressions.nuspec +system.linq.expressions\4.1.0\ThirdPartyNotices.txt +system.linq.expressions\4.3.0\dotnet_library_license.txt +system.linq.expressions\4.3.0\lib\MonoAndroid10\_._ +system.linq.expressions\4.3.0\lib\MonoTouch10\_._ +system.linq.expressions\4.3.0\lib\net45\_._ +system.linq.expressions\4.3.0\lib\net463\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\lib\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\lib\netstandard1.6\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq.expressions\4.3.0\lib\win8\_._ +system.linq.expressions\4.3.0\lib\wp80\_._ +system.linq.expressions\4.3.0\lib\wpa81\_._ +system.linq.expressions\4.3.0\lib\xamarinios10\_._ +system.linq.expressions\4.3.0\lib\xamarinmac20\_._ +system.linq.expressions\4.3.0\lib\xamarintvos10\_._ +system.linq.expressions\4.3.0\lib\xamarinwatchos10\_._ +system.linq.expressions\4.3.0\ref\MonoAndroid10\_._ +system.linq.expressions\4.3.0\ref\MonoTouch10\_._ +system.linq.expressions\4.3.0\ref\net45\_._ +system.linq.expressions\4.3.0\ref\net463\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\netstandard1.0\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\netstandard1.3\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\netstandard1.6\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq.expressions\4.3.0\ref\win8\_._ +system.linq.expressions\4.3.0\ref\wp80\_._ +system.linq.expressions\4.3.0\ref\wpa81\_._ +system.linq.expressions\4.3.0\ref\xamarinios10\_._ +system.linq.expressions\4.3.0\ref\xamarinmac20\_._ +system.linq.expressions\4.3.0\ref\xamarintvos10\_._ +system.linq.expressions\4.3.0\ref\xamarinwatchos10\_._ +system.linq.expressions\4.3.0\runtimes\aot\lib\netcore50\System.Linq.Expressions.dll +system.linq.expressions\4.3.0\system.linq.expressions.4.3.0.nupkg.sha512 +system.linq.expressions\4.3.0\system.linq.expressions.nuspec +system.linq.expressions\4.3.0\ThirdPartyNotices.txt +system.linq.parallel\4.3.0\dotnet_library_license.txt +system.linq.parallel\4.3.0\lib\MonoAndroid10\_._ +system.linq.parallel\4.3.0\lib\MonoTouch10\_._ +system.linq.parallel\4.3.0\lib\net45\_._ +system.linq.parallel\4.3.0\lib\netcore50\System.Linq.Parallel.dll +system.linq.parallel\4.3.0\lib\netstandard1.3\System.Linq.Parallel.dll +system.linq.parallel\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.linq.parallel\4.3.0\lib\win8\_._ +system.linq.parallel\4.3.0\lib\wpa81\_._ +system.linq.parallel\4.3.0\lib\xamarinios10\_._ +system.linq.parallel\4.3.0\lib\xamarinmac20\_._ +system.linq.parallel\4.3.0\lib\xamarintvos10\_._ +system.linq.parallel\4.3.0\lib\xamarinwatchos10\_._ +system.linq.parallel\4.3.0\ref\MonoAndroid10\_._ +system.linq.parallel\4.3.0\ref\MonoTouch10\_._ +system.linq.parallel\4.3.0\ref\net45\_._ +system.linq.parallel\4.3.0\ref\netcore50\System.Linq.Parallel.dll +system.linq.parallel\4.3.0\ref\netstandard1.1\System.Linq.Parallel.dll +system.linq.parallel\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.linq.parallel\4.3.0\ref\win8\_._ +system.linq.parallel\4.3.0\ref\wpa81\_._ +system.linq.parallel\4.3.0\ref\xamarinios10\_._ +system.linq.parallel\4.3.0\ref\xamarinmac20\_._ +system.linq.parallel\4.3.0\ref\xamarintvos10\_._ +system.linq.parallel\4.3.0\ref\xamarinwatchos10\_._ +system.linq.parallel\4.3.0\system.linq.parallel.4.3.0.nupkg.sha512 +system.linq.parallel\4.3.0\system.linq.parallel.nuspec +system.linq.parallel\4.3.0\ThirdPartyNotices.txt +system.linq.queryable\4.0.1\dotnet_library_license.txt +system.linq.queryable\4.0.1\lib\monoandroid10\_._ +system.linq.queryable\4.0.1\lib\monotouch10\_._ +system.linq.queryable\4.0.1\lib\net45\_._ +system.linq.queryable\4.0.1\lib\netcore50\System.Linq.Queryable.dll +system.linq.queryable\4.0.1\lib\netstandard1.3\System.Linq.Queryable.dll +system.linq.queryable\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq.queryable\4.0.1\lib\win8\_._ +system.linq.queryable\4.0.1\lib\wp80\_._ +system.linq.queryable\4.0.1\lib\wpa81\_._ +system.linq.queryable\4.0.1\lib\xamarinios10\_._ +system.linq.queryable\4.0.1\lib\xamarinmac20\_._ +system.linq.queryable\4.0.1\lib\xamarintvos10\_._ +system.linq.queryable\4.0.1\lib\xamarinwatchos10\_._ +system.linq.queryable\4.0.1\ref\monoandroid10\_._ +system.linq.queryable\4.0.1\ref\monotouch10\_._ +system.linq.queryable\4.0.1\ref\net45\_._ +system.linq.queryable\4.0.1\ref\netcore50\System.Linq.Queryable.dll +system.linq.queryable\4.0.1\ref\netstandard1.0\System.Linq.Queryable.dll +system.linq.queryable\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq.queryable\4.0.1\ref\win8\_._ +system.linq.queryable\4.0.1\ref\wp80\_._ +system.linq.queryable\4.0.1\ref\wpa81\_._ +system.linq.queryable\4.0.1\ref\xamarinios10\_._ +system.linq.queryable\4.0.1\ref\xamarinmac20\_._ +system.linq.queryable\4.0.1\ref\xamarintvos10\_._ +system.linq.queryable\4.0.1\ref\xamarinwatchos10\_._ +system.linq.queryable\4.0.1\system.linq.queryable.4.0.1.nupkg.sha512 +system.linq.queryable\4.0.1\system.linq.queryable.nuspec +system.linq.queryable\4.0.1\ThirdPartyNotices.txt +system.linq\4.1.0\dotnet_library_license.txt +system.linq\4.1.0\lib\MonoAndroid10\_._ +system.linq\4.1.0\lib\MonoTouch10\_._ +system.linq\4.1.0\lib\net45\_._ +system.linq\4.1.0\lib\net463\System.Linq.dll +system.linq\4.1.0\lib\netcore50\System.Linq.dll +system.linq\4.1.0\lib\netstandard1.6\System.Linq.dll +system.linq\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq\4.1.0\lib\win8\_._ +system.linq\4.1.0\lib\wp80\_._ +system.linq\4.1.0\lib\wpa81\_._ +system.linq\4.1.0\lib\xamarinios10\_._ +system.linq\4.1.0\lib\xamarinmac20\_._ +system.linq\4.1.0\lib\xamarintvos10\_._ +system.linq\4.1.0\lib\xamarinwatchos10\_._ +system.linq\4.1.0\ref\MonoAndroid10\_._ +system.linq\4.1.0\ref\MonoTouch10\_._ +system.linq\4.1.0\ref\net45\_._ +system.linq\4.1.0\ref\net463\System.Linq.dll +system.linq\4.1.0\ref\netcore50\System.Linq.dll +system.linq\4.1.0\ref\netstandard1.0\System.Linq.dll +system.linq\4.1.0\ref\netstandard1.6\System.Linq.dll +system.linq\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq\4.1.0\ref\win8\_._ +system.linq\4.1.0\ref\wp80\_._ +system.linq\4.1.0\ref\wpa81\_._ +system.linq\4.1.0\ref\xamarinios10\_._ +system.linq\4.1.0\ref\xamarinmac20\_._ +system.linq\4.1.0\ref\xamarintvos10\_._ +system.linq\4.1.0\ref\xamarinwatchos10\_._ +system.linq\4.1.0\system.linq.4.1.0.nupkg.sha512 +system.linq\4.1.0\system.linq.nuspec +system.linq\4.1.0\ThirdPartyNotices.txt +system.linq\4.3.0\dotnet_library_license.txt +system.linq\4.3.0\lib\MonoAndroid10\_._ +system.linq\4.3.0\lib\MonoTouch10\_._ +system.linq\4.3.0\lib\net45\_._ +system.linq\4.3.0\lib\net463\System.Linq.dll +system.linq\4.3.0\lib\netcore50\System.Linq.dll +system.linq\4.3.0\lib\netstandard1.6\System.Linq.dll +system.linq\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.linq\4.3.0\lib\win8\_._ +system.linq\4.3.0\lib\wp80\_._ +system.linq\4.3.0\lib\wpa81\_._ +system.linq\4.3.0\lib\xamarinios10\_._ +system.linq\4.3.0\lib\xamarinmac20\_._ +system.linq\4.3.0\lib\xamarintvos10\_._ +system.linq\4.3.0\lib\xamarinwatchos10\_._ +system.linq\4.3.0\ref\MonoAndroid10\_._ +system.linq\4.3.0\ref\MonoTouch10\_._ +system.linq\4.3.0\ref\net45\_._ +system.linq\4.3.0\ref\net463\System.Linq.dll +system.linq\4.3.0\ref\netcore50\System.Linq.dll +system.linq\4.3.0\ref\netstandard1.0\System.Linq.dll +system.linq\4.3.0\ref\netstandard1.6\System.Linq.dll +system.linq\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.linq\4.3.0\ref\win8\_._ +system.linq\4.3.0\ref\wp80\_._ +system.linq\4.3.0\ref\wpa81\_._ +system.linq\4.3.0\ref\xamarinios10\_._ +system.linq\4.3.0\ref\xamarinmac20\_._ +system.linq\4.3.0\ref\xamarintvos10\_._ +system.linq\4.3.0\ref\xamarinwatchos10\_._ +system.linq\4.3.0\system.linq.4.3.0.nupkg.sha512 +system.linq\4.3.0\system.linq.nuspec +system.linq\4.3.0\ThirdPartyNotices.txt +system.memory\4.5.1\.signature.p7s +system.memory\4.5.1\lib\netcoreapp2.1\_._ +system.memory\4.5.1\lib\netstandard1.1\System.Memory.dll +system.memory\4.5.1\lib\netstandard2.0\System.Memory.dll +system.memory\4.5.1\LICENSE.TXT +system.memory\4.5.1\ref\netcoreapp2.1\_._ +system.memory\4.5.1\ref\netstandard1.1\System.Memory.dll +system.memory\4.5.1\ref\netstandard2.0\System.Memory.dll +system.memory\4.5.1\system.memory.4.5.1.nupkg.sha512 +system.memory\4.5.1\system.memory.nuspec +system.memory\4.5.1\THIRD-PARTY-NOTICES.TXT +system.memory\4.5.1\useSharedDesignerContext.txt +system.memory\4.5.1\version.txt +system.net.http\4.1.0\dotnet_library_license.txt +system.net.http\4.1.0\lib\monoandroid10\_._ +system.net.http\4.1.0\lib\monotouch10\_._ +system.net.http\4.1.0\lib\net45\_._ +system.net.http\4.1.0\lib\net46\System.Net.Http.dll +system.net.http\4.1.0\lib\portable-net45+win8+wpa81\_._ +system.net.http\4.1.0\lib\win8\_._ +system.net.http\4.1.0\lib\wpa81\_._ +system.net.http\4.1.0\lib\xamarinios10\_._ +system.net.http\4.1.0\lib\Xamarinmac20\_._ +system.net.http\4.1.0\lib\xamarintvos10\_._ +system.net.http\4.1.0\lib\xamarinwatchos10\_._ +system.net.http\4.1.0\ref\monoandroid10\_._ +system.net.http\4.1.0\ref\monotouch10\_._ +system.net.http\4.1.0\ref\net45\_._ +system.net.http\4.1.0\ref\net46\System.Net.Http.dll +system.net.http\4.1.0\ref\netcore50\System.Net.Http.dll +system.net.http\4.1.0\ref\netstandard1.1\System.Net.Http.dll +system.net.http\4.1.0\ref\netstandard1.3\System.Net.Http.dll +system.net.http\4.1.0\ref\portable-net45+win8+wpa81\_._ +system.net.http\4.1.0\ref\win8\_._ +system.net.http\4.1.0\ref\wpa81\_._ +system.net.http\4.1.0\ref\xamarinios10\_._ +system.net.http\4.1.0\ref\Xamarinmac20\_._ +system.net.http\4.1.0\ref\xamarintvos10\_._ +system.net.http\4.1.0\ref\xamarinwatchos10\_._ +system.net.http\4.1.0\runtimes\unix\lib\netstandard1.6\System.Net.Http.dll +system.net.http\4.1.0\runtimes\win\lib\net46\System.Net.Http.dll +system.net.http\4.1.0\runtimes\win\lib\netcore50\System.Net.Http.dll +system.net.http\4.1.0\runtimes\win\lib\netstandard1.3\System.Net.Http.dll +system.net.http\4.1.0\system.net.http.4.1.0.nupkg.sha512 +system.net.http\4.1.0\system.net.http.nuspec +system.net.http\4.1.0\ThirdPartyNotices.txt +system.net.http\4.3.0\dotnet_library_license.txt +system.net.http\4.3.0\lib\monoandroid10\_._ +system.net.http\4.3.0\lib\monotouch10\_._ +system.net.http\4.3.0\lib\net45\_._ +system.net.http\4.3.0\lib\net46\System.Net.Http.dll +system.net.http\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.net.http\4.3.0\lib\win8\_._ +system.net.http\4.3.0\lib\wpa81\_._ +system.net.http\4.3.0\lib\xamarinios10\_._ +system.net.http\4.3.0\lib\Xamarinmac20\_._ +system.net.http\4.3.0\lib\xamarintvos10\_._ +system.net.http\4.3.0\lib\xamarinwatchos10\_._ +system.net.http\4.3.0\ref\monoandroid10\_._ +system.net.http\4.3.0\ref\monotouch10\_._ +system.net.http\4.3.0\ref\net45\_._ +system.net.http\4.3.0\ref\net46\System.Net.Http.dll +system.net.http\4.3.0\ref\netcore50\System.Net.Http.dll +system.net.http\4.3.0\ref\netstandard1.1\System.Net.Http.dll +system.net.http\4.3.0\ref\netstandard1.3\System.Net.Http.dll +system.net.http\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.net.http\4.3.0\ref\win8\_._ +system.net.http\4.3.0\ref\wpa81\_._ +system.net.http\4.3.0\ref\xamarinios10\_._ +system.net.http\4.3.0\ref\Xamarinmac20\_._ +system.net.http\4.3.0\ref\xamarintvos10\_._ +system.net.http\4.3.0\ref\xamarinwatchos10\_._ +system.net.http\4.3.0\runtimes\unix\lib\netstandard1.6\System.Net.Http.dll +system.net.http\4.3.0\runtimes\win\lib\net46\System.Net.Http.dll +system.net.http\4.3.0\runtimes\win\lib\netcore50\System.Net.Http.dll +system.net.http\4.3.0\runtimes\win\lib\netstandard1.3\System.Net.Http.dll +system.net.http\4.3.0\system.net.http.4.3.0.nupkg.sha512 +system.net.http\4.3.0\system.net.http.nuspec +system.net.http\4.3.0\ThirdPartyNotices.txt +system.net.nameresolution\4.3.0\dotnet_library_license.txt +system.net.nameresolution\4.3.0\lib\MonoAndroid10\_._ +system.net.nameresolution\4.3.0\lib\MonoTouch10\_._ +system.net.nameresolution\4.3.0\lib\net46\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\lib\xamarinios10\_._ +system.net.nameresolution\4.3.0\lib\xamarinmac20\_._ +system.net.nameresolution\4.3.0\lib\xamarintvos10\_._ +system.net.nameresolution\4.3.0\lib\xamarinwatchos10\_._ +system.net.nameresolution\4.3.0\ref\MonoAndroid10\_._ +system.net.nameresolution\4.3.0\ref\MonoTouch10\_._ +system.net.nameresolution\4.3.0\ref\net46\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\ref\netstandard1.3\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\ref\xamarinios10\_._ +system.net.nameresolution\4.3.0\ref\xamarinmac20\_._ +system.net.nameresolution\4.3.0\ref\xamarintvos10\_._ +system.net.nameresolution\4.3.0\ref\xamarinwatchos10\_._ +system.net.nameresolution\4.3.0\runtimes\unix\lib\netstandard1.3\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\runtimes\win\lib\net46\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\runtimes\win\lib\netcore50\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\runtimes\win\lib\netstandard1.3\System.Net.NameResolution.dll +system.net.nameresolution\4.3.0\system.net.nameresolution.4.3.0.nupkg.sha512 +system.net.nameresolution\4.3.0\system.net.nameresolution.nuspec +system.net.nameresolution\4.3.0\ThirdPartyNotices.txt +system.net.primitives\4.0.11\dotnet_library_license.txt +system.net.primitives\4.0.11\lib\MonoAndroid10\_._ +system.net.primitives\4.0.11\lib\MonoTouch10\_._ +system.net.primitives\4.0.11\lib\net45\_._ +system.net.primitives\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.net.primitives\4.0.11\lib\win8\_._ +system.net.primitives\4.0.11\lib\wp80\_._ +system.net.primitives\4.0.11\lib\wpa81\_._ +system.net.primitives\4.0.11\lib\xamarinios10\_._ +system.net.primitives\4.0.11\lib\xamarinmac20\_._ +system.net.primitives\4.0.11\lib\xamarintvos10\_._ +system.net.primitives\4.0.11\lib\xamarinwatchos10\_._ +system.net.primitives\4.0.11\ref\MonoAndroid10\_._ +system.net.primitives\4.0.11\ref\MonoTouch10\_._ +system.net.primitives\4.0.11\ref\net45\_._ +system.net.primitives\4.0.11\ref\netcore50\System.Net.Primitives.dll +system.net.primitives\4.0.11\ref\netstandard1.0\System.Net.Primitives.dll +system.net.primitives\4.0.11\ref\netstandard1.1\System.Net.Primitives.dll +system.net.primitives\4.0.11\ref\netstandard1.3\System.Net.Primitives.dll +system.net.primitives\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.net.primitives\4.0.11\ref\win8\_._ +system.net.primitives\4.0.11\ref\wp80\_._ +system.net.primitives\4.0.11\ref\wpa81\_._ +system.net.primitives\4.0.11\ref\xamarinios10\_._ +system.net.primitives\4.0.11\ref\xamarinmac20\_._ +system.net.primitives\4.0.11\ref\xamarintvos10\_._ +system.net.primitives\4.0.11\ref\xamarinwatchos10\_._ +system.net.primitives\4.0.11\system.net.primitives.4.0.11.nupkg.sha512 +system.net.primitives\4.0.11\system.net.primitives.nuspec +system.net.primitives\4.0.11\ThirdPartyNotices.txt +system.net.primitives\4.3.0\dotnet_library_license.txt +system.net.primitives\4.3.0\lib\MonoAndroid10\_._ +system.net.primitives\4.3.0\lib\MonoTouch10\_._ +system.net.primitives\4.3.0\lib\net45\_._ +system.net.primitives\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.net.primitives\4.3.0\lib\win8\_._ +system.net.primitives\4.3.0\lib\wp80\_._ +system.net.primitives\4.3.0\lib\wpa81\_._ +system.net.primitives\4.3.0\lib\xamarinios10\_._ +system.net.primitives\4.3.0\lib\xamarinmac20\_._ +system.net.primitives\4.3.0\lib\xamarintvos10\_._ +system.net.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.net.primitives\4.3.0\ref\MonoAndroid10\_._ +system.net.primitives\4.3.0\ref\MonoTouch10\_._ +system.net.primitives\4.3.0\ref\net45\_._ +system.net.primitives\4.3.0\ref\netcore50\System.Net.Primitives.dll +system.net.primitives\4.3.0\ref\netstandard1.0\System.Net.Primitives.dll +system.net.primitives\4.3.0\ref\netstandard1.1\System.Net.Primitives.dll +system.net.primitives\4.3.0\ref\netstandard1.3\System.Net.Primitives.dll +system.net.primitives\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.net.primitives\4.3.0\ref\win8\_._ +system.net.primitives\4.3.0\ref\wp80\_._ +system.net.primitives\4.3.0\ref\wpa81\_._ +system.net.primitives\4.3.0\ref\xamarinios10\_._ +system.net.primitives\4.3.0\ref\xamarinmac20\_._ +system.net.primitives\4.3.0\ref\xamarintvos10\_._ +system.net.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.net.primitives\4.3.0\system.net.primitives.4.3.0.nupkg.sha512 +system.net.primitives\4.3.0\system.net.primitives.nuspec +system.net.primitives\4.3.0\ThirdPartyNotices.txt +system.net.security\4.3.0\dotnet_library_license.txt +system.net.security\4.3.0\lib\MonoAndroid10\_._ +system.net.security\4.3.0\lib\MonoTouch10\_._ +system.net.security\4.3.0\lib\net46\System.Net.Security.dll +system.net.security\4.3.0\lib\xamarinios10\_._ +system.net.security\4.3.0\lib\xamarinmac20\_._ +system.net.security\4.3.0\lib\xamarintvos10\_._ +system.net.security\4.3.0\lib\xamarinwatchos10\_._ +system.net.security\4.3.0\ref\MonoAndroid10\_._ +system.net.security\4.3.0\ref\MonoTouch10\_._ +system.net.security\4.3.0\ref\net46\System.Net.Security.dll +system.net.security\4.3.0\ref\netstandard1.3\System.Net.Security.dll +system.net.security\4.3.0\ref\xamarinios10\_._ +system.net.security\4.3.0\ref\xamarinmac20\_._ +system.net.security\4.3.0\ref\xamarintvos10\_._ +system.net.security\4.3.0\ref\xamarinwatchos10\_._ +system.net.security\4.3.0\runtimes\unix\lib\netstandard1.6\System.Net.Security.dll +system.net.security\4.3.0\runtimes\win\lib\net46\System.Net.Security.dll +system.net.security\4.3.0\runtimes\win\lib\netstandard1.3\System.Net.Security.dll +system.net.security\4.3.0\runtimes\win7\lib\netcore50\_._ +system.net.security\4.3.0\system.net.security.4.3.0.nupkg.sha512 +system.net.security\4.3.0\system.net.security.nuspec +system.net.security\4.3.0\ThirdPartyNotices.txt +system.net.sockets\4.1.0\dotnet_library_license.txt +system.net.sockets\4.1.0\lib\MonoAndroid10\_._ +system.net.sockets\4.1.0\lib\MonoTouch10\_._ +system.net.sockets\4.1.0\lib\net46\System.Net.Sockets.dll +system.net.sockets\4.1.0\lib\xamarinios10\_._ +system.net.sockets\4.1.0\lib\xamarinmac20\_._ +system.net.sockets\4.1.0\lib\xamarintvos10\_._ +system.net.sockets\4.1.0\lib\xamarinwatchos10\_._ +system.net.sockets\4.1.0\ref\MonoAndroid10\_._ +system.net.sockets\4.1.0\ref\MonoTouch10\_._ +system.net.sockets\4.1.0\ref\net46\System.Net.Sockets.dll +system.net.sockets\4.1.0\ref\netstandard1.3\System.Net.Sockets.dll +system.net.sockets\4.1.0\ref\xamarinios10\_._ +system.net.sockets\4.1.0\ref\xamarinmac20\_._ +system.net.sockets\4.1.0\ref\xamarintvos10\_._ +system.net.sockets\4.1.0\ref\xamarinwatchos10\_._ +system.net.sockets\4.1.0\system.net.sockets.4.1.0.nupkg.sha512 +system.net.sockets\4.1.0\system.net.sockets.nuspec +system.net.sockets\4.1.0\ThirdPartyNotices.txt +system.net.sockets\4.3.0\dotnet_library_license.txt +system.net.sockets\4.3.0\lib\MonoAndroid10\_._ +system.net.sockets\4.3.0\lib\MonoTouch10\_._ +system.net.sockets\4.3.0\lib\net46\System.Net.Sockets.dll +system.net.sockets\4.3.0\lib\xamarinios10\_._ +system.net.sockets\4.3.0\lib\xamarinmac20\_._ +system.net.sockets\4.3.0\lib\xamarintvos10\_._ +system.net.sockets\4.3.0\lib\xamarinwatchos10\_._ +system.net.sockets\4.3.0\ref\MonoAndroid10\_._ +system.net.sockets\4.3.0\ref\MonoTouch10\_._ +system.net.sockets\4.3.0\ref\net46\System.Net.Sockets.dll +system.net.sockets\4.3.0\ref\netstandard1.3\System.Net.Sockets.dll +system.net.sockets\4.3.0\ref\xamarinios10\_._ +system.net.sockets\4.3.0\ref\xamarinmac20\_._ +system.net.sockets\4.3.0\ref\xamarintvos10\_._ +system.net.sockets\4.3.0\ref\xamarinwatchos10\_._ +system.net.sockets\4.3.0\system.net.sockets.4.3.0.nupkg.sha512 +system.net.sockets\4.3.0\system.net.sockets.nuspec +system.net.sockets\4.3.0\ThirdPartyNotices.txt +system.net.websockets.websocketprotocol\4.5.1\.signature.p7s +system.net.websockets.websocketprotocol\4.5.1\lib\netcoreapp2.1\System.Net.WebSockets.WebSocketProtocol.dll +system.net.websockets.websocketprotocol\4.5.1\lib\netstandard2.0\System.Net.WebSockets.WebSocketProtocol.dll +system.net.websockets.websocketprotocol\4.5.1\LICENSE.TXT +system.net.websockets.websocketprotocol\4.5.1\ref\netstandard2.0\System.Net.WebSockets.WebSocketProtocol.dll +system.net.websockets.websocketprotocol\4.5.1\system.net.websockets.websocketprotocol.4.5.1.nupkg.sha512 +system.net.websockets.websocketprotocol\4.5.1\system.net.websockets.websocketprotocol.nuspec +system.net.websockets.websocketprotocol\4.5.1\THIRD-PARTY-NOTICES.TXT +system.net.websockets.websocketprotocol\4.5.1\useSharedDesignerContext.txt +system.net.websockets.websocketprotocol\4.5.1\version.txt +system.numerics.vectors\4.5.0\.signature.p7s +system.numerics.vectors\4.5.0\lib\MonoAndroid10\_._ +system.numerics.vectors\4.5.0\lib\MonoTouch10\_._ +system.numerics.vectors\4.5.0\lib\net46\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\lib\netcoreapp2.0\_._ +system.numerics.vectors\4.5.0\lib\netstandard1.0\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\lib\netstandard2.0\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\lib\portable-net45+win8+wp8+wpa81\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\lib\uap10.0.16299\_._ +system.numerics.vectors\4.5.0\lib\xamarinios10\_._ +system.numerics.vectors\4.5.0\lib\xamarinmac20\_._ +system.numerics.vectors\4.5.0\lib\xamarintvos10\_._ +system.numerics.vectors\4.5.0\lib\xamarinwatchos10\_._ +system.numerics.vectors\4.5.0\LICENSE.TXT +system.numerics.vectors\4.5.0\ref\MonoAndroid10\_._ +system.numerics.vectors\4.5.0\ref\MonoTouch10\_._ +system.numerics.vectors\4.5.0\ref\net45\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\ref\net46\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\ref\netcoreapp2.0\_._ +system.numerics.vectors\4.5.0\ref\netstandard1.0\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\ref\netstandard2.0\System.Numerics.Vectors.dll +system.numerics.vectors\4.5.0\ref\uap10.0.16299\_._ +system.numerics.vectors\4.5.0\ref\xamarinios10\_._ +system.numerics.vectors\4.5.0\ref\xamarinmac20\_._ +system.numerics.vectors\4.5.0\ref\xamarintvos10\_._ +system.numerics.vectors\4.5.0\ref\xamarinwatchos10\_._ +system.numerics.vectors\4.5.0\system.numerics.vectors.4.5.0.nupkg.sha512 +system.numerics.vectors\4.5.0\system.numerics.vectors.nuspec +system.numerics.vectors\4.5.0\THIRD-PARTY-NOTICES.TXT +system.numerics.vectors\4.5.0\useSharedDesignerContext.txt +system.numerics.vectors\4.5.0\version.txt +system.objectmodel\4.0.12\dotnet_library_license.txt +system.objectmodel\4.0.12\lib\MonoAndroid10\_._ +system.objectmodel\4.0.12\lib\MonoTouch10\_._ +system.objectmodel\4.0.12\lib\net45\_._ +system.objectmodel\4.0.12\lib\netcore50\System.ObjectModel.dll +system.objectmodel\4.0.12\lib\netstandard1.3\System.ObjectModel.dll +system.objectmodel\4.0.12\lib\portable-net45+win8+wp8+wpa81\_._ +system.objectmodel\4.0.12\lib\win8\_._ +system.objectmodel\4.0.12\lib\wp80\_._ +system.objectmodel\4.0.12\lib\wpa81\_._ +system.objectmodel\4.0.12\lib\xamarinios10\_._ +system.objectmodel\4.0.12\lib\xamarinmac20\_._ +system.objectmodel\4.0.12\lib\xamarintvos10\_._ +system.objectmodel\4.0.12\lib\xamarinwatchos10\_._ +system.objectmodel\4.0.12\ref\MonoAndroid10\_._ +system.objectmodel\4.0.12\ref\MonoTouch10\_._ +system.objectmodel\4.0.12\ref\net45\_._ +system.objectmodel\4.0.12\ref\netcore50\System.ObjectModel.dll +system.objectmodel\4.0.12\ref\netstandard1.0\System.ObjectModel.dll +system.objectmodel\4.0.12\ref\netstandard1.3\System.ObjectModel.dll +system.objectmodel\4.0.12\ref\portable-net45+win8+wp8+wpa81\_._ +system.objectmodel\4.0.12\ref\win8\_._ +system.objectmodel\4.0.12\ref\wp80\_._ +system.objectmodel\4.0.12\ref\wpa81\_._ +system.objectmodel\4.0.12\ref\xamarinios10\_._ +system.objectmodel\4.0.12\ref\xamarinmac20\_._ +system.objectmodel\4.0.12\ref\xamarintvos10\_._ +system.objectmodel\4.0.12\ref\xamarinwatchos10\_._ +system.objectmodel\4.0.12\system.objectmodel.4.0.12.nupkg.sha512 +system.objectmodel\4.0.12\system.objectmodel.nuspec +system.objectmodel\4.0.12\ThirdPartyNotices.txt +system.objectmodel\4.3.0\dotnet_library_license.txt +system.objectmodel\4.3.0\lib\MonoAndroid10\_._ +system.objectmodel\4.3.0\lib\MonoTouch10\_._ +system.objectmodel\4.3.0\lib\net45\_._ +system.objectmodel\4.3.0\lib\netcore50\System.ObjectModel.dll +system.objectmodel\4.3.0\lib\netstandard1.3\System.ObjectModel.dll +system.objectmodel\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.objectmodel\4.3.0\lib\win8\_._ +system.objectmodel\4.3.0\lib\wp80\_._ +system.objectmodel\4.3.0\lib\wpa81\_._ +system.objectmodel\4.3.0\lib\xamarinios10\_._ +system.objectmodel\4.3.0\lib\xamarinmac20\_._ +system.objectmodel\4.3.0\lib\xamarintvos10\_._ +system.objectmodel\4.3.0\lib\xamarinwatchos10\_._ +system.objectmodel\4.3.0\ref\MonoAndroid10\_._ +system.objectmodel\4.3.0\ref\MonoTouch10\_._ +system.objectmodel\4.3.0\ref\net45\_._ +system.objectmodel\4.3.0\ref\netcore50\System.ObjectModel.dll +system.objectmodel\4.3.0\ref\netstandard1.0\System.ObjectModel.dll +system.objectmodel\4.3.0\ref\netstandard1.3\System.ObjectModel.dll +system.objectmodel\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.objectmodel\4.3.0\ref\win8\_._ +system.objectmodel\4.3.0\ref\wp80\_._ +system.objectmodel\4.3.0\ref\wpa81\_._ +system.objectmodel\4.3.0\ref\xamarinios10\_._ +system.objectmodel\4.3.0\ref\xamarinmac20\_._ +system.objectmodel\4.3.0\ref\xamarintvos10\_._ +system.objectmodel\4.3.0\ref\xamarinwatchos10\_._ +system.objectmodel\4.3.0\system.objectmodel.4.3.0.nupkg.sha512 +system.objectmodel\4.3.0\system.objectmodel.nuspec +system.objectmodel\4.3.0\ThirdPartyNotices.txt +system.private.datacontractserialization\4.1.1\dotnet_library_license.txt +system.private.datacontractserialization\4.1.1\lib\netstandard1.3\System.Private.DataContractSerialization.dll +system.private.datacontractserialization\4.1.1\ref\netstandard\_._ +system.private.datacontractserialization\4.1.1\runtimes\aot\lib\netcore50\System.Private.DataContractSerialization.dll +system.private.datacontractserialization\4.1.1\system.private.datacontractserialization.4.1.1.nupkg.sha512 +system.private.datacontractserialization\4.1.1\system.private.datacontractserialization.nuspec +system.private.datacontractserialization\4.1.1\ThirdPartyNotices.txt +system.private.datacontractserialization\4.3.0\dotnet_library_license.txt +system.private.datacontractserialization\4.3.0\lib\netstandard1.3\System.Private.DataContractSerialization.dll +system.private.datacontractserialization\4.3.0\ref\netstandard\_._ +system.private.datacontractserialization\4.3.0\runtimes\aot\lib\netcore50\System.Private.DataContractSerialization.dll +system.private.datacontractserialization\4.3.0\system.private.datacontractserialization.4.3.0.nupkg.sha512 +system.private.datacontractserialization\4.3.0\system.private.datacontractserialization.nuspec +system.private.datacontractserialization\4.3.0\ThirdPartyNotices.txt +system.reflection.emit.ilgeneration\4.0.1\dotnet_library_license.txt +system.reflection.emit.ilgeneration\4.0.1\lib\net45\_._ +system.reflection.emit.ilgeneration\4.0.1\lib\netcore50\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.0.1\lib\netstandard1.3\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.0.1\lib\portable-net45+wp8\_._ +system.reflection.emit.ilgeneration\4.0.1\lib\wp80\_._ +system.reflection.emit.ilgeneration\4.0.1\ref\net45\_._ +system.reflection.emit.ilgeneration\4.0.1\ref\netstandard1.0\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.0.1\ref\portable-net45+wp8\_._ +system.reflection.emit.ilgeneration\4.0.1\ref\wp80\_._ +system.reflection.emit.ilgeneration\4.0.1\runtimes\aot\lib\netcore50\_._ +system.reflection.emit.ilgeneration\4.0.1\system.reflection.emit.ilgeneration.4.0.1.nupkg.sha512 +system.reflection.emit.ilgeneration\4.0.1\system.reflection.emit.ilgeneration.nuspec +system.reflection.emit.ilgeneration\4.0.1\ThirdPartyNotices.txt +system.reflection.emit.ilgeneration\4.3.0\dotnet_library_license.txt +system.reflection.emit.ilgeneration\4.3.0\lib\MonoAndroid10\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\MonoTouch10\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\net45\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\netcore50\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.3.0\lib\netstandard1.3\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.3.0\lib\portable-net45+wp8\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\wp80\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\xamarinios10\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\xamarinmac20\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\xamarintvos10\_._ +system.reflection.emit.ilgeneration\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\MonoAndroid10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\MonoTouch10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\net45\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\netstandard1.0\System.Reflection.Emit.ILGeneration.dll +system.reflection.emit.ilgeneration\4.3.0\ref\portable-net45+wp8\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\wp80\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\xamarinios10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\xamarinmac20\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\xamarintvos10\_._ +system.reflection.emit.ilgeneration\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.emit.ilgeneration\4.3.0\runtimes\aot\lib\netcore50\_._ +system.reflection.emit.ilgeneration\4.3.0\system.reflection.emit.ilgeneration.4.3.0.nupkg.sha512 +system.reflection.emit.ilgeneration\4.3.0\system.reflection.emit.ilgeneration.nuspec +system.reflection.emit.ilgeneration\4.3.0\ThirdPartyNotices.txt +system.reflection.emit.lightweight\4.0.1\dotnet_library_license.txt +system.reflection.emit.lightweight\4.0.1\lib\net45\_._ +system.reflection.emit.lightweight\4.0.1\lib\netcore50\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.0.1\lib\netstandard1.3\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.0.1\lib\portable-net45+wp8\_._ +system.reflection.emit.lightweight\4.0.1\lib\wp80\_._ +system.reflection.emit.lightweight\4.0.1\ref\net45\_._ +system.reflection.emit.lightweight\4.0.1\ref\netstandard1.0\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.0.1\ref\portable-net45+wp8\_._ +system.reflection.emit.lightweight\4.0.1\ref\wp80\_._ +system.reflection.emit.lightweight\4.0.1\runtimes\aot\lib\netcore50\_._ +system.reflection.emit.lightweight\4.0.1\system.reflection.emit.lightweight.4.0.1.nupkg.sha512 +system.reflection.emit.lightweight\4.0.1\system.reflection.emit.lightweight.nuspec +system.reflection.emit.lightweight\4.0.1\ThirdPartyNotices.txt +system.reflection.emit.lightweight\4.3.0\dotnet_library_license.txt +system.reflection.emit.lightweight\4.3.0\lib\MonoAndroid10\_._ +system.reflection.emit.lightweight\4.3.0\lib\MonoTouch10\_._ +system.reflection.emit.lightweight\4.3.0\lib\net45\_._ +system.reflection.emit.lightweight\4.3.0\lib\netcore50\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.3.0\lib\netstandard1.3\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.3.0\lib\portable-net45+wp8\_._ +system.reflection.emit.lightweight\4.3.0\lib\wp80\_._ +system.reflection.emit.lightweight\4.3.0\lib\xamarinios10\_._ +system.reflection.emit.lightweight\4.3.0\lib\xamarinmac20\_._ +system.reflection.emit.lightweight\4.3.0\lib\xamarintvos10\_._ +system.reflection.emit.lightweight\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.emit.lightweight\4.3.0\ref\MonoAndroid10\_._ +system.reflection.emit.lightweight\4.3.0\ref\MonoTouch10\_._ +system.reflection.emit.lightweight\4.3.0\ref\net45\_._ +system.reflection.emit.lightweight\4.3.0\ref\netstandard1.0\System.Reflection.Emit.Lightweight.dll +system.reflection.emit.lightweight\4.3.0\ref\portable-net45+wp8\_._ +system.reflection.emit.lightweight\4.3.0\ref\wp80\_._ +system.reflection.emit.lightweight\4.3.0\ref\xamarinios10\_._ +system.reflection.emit.lightweight\4.3.0\ref\xamarinmac20\_._ +system.reflection.emit.lightweight\4.3.0\ref\xamarintvos10\_._ +system.reflection.emit.lightweight\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.emit.lightweight\4.3.0\runtimes\aot\lib\netcore50\_._ +system.reflection.emit.lightweight\4.3.0\system.reflection.emit.lightweight.4.3.0.nupkg.sha512 +system.reflection.emit.lightweight\4.3.0\system.reflection.emit.lightweight.nuspec +system.reflection.emit.lightweight\4.3.0\ThirdPartyNotices.txt +system.reflection.emit\4.0.1\dotnet_library_license.txt +system.reflection.emit\4.0.1\lib\MonoAndroid10\_._ +system.reflection.emit\4.0.1\lib\net45\_._ +system.reflection.emit\4.0.1\lib\netcore50\System.Reflection.Emit.dll +system.reflection.emit\4.0.1\lib\netstandard1.3\System.Reflection.Emit.dll +system.reflection.emit\4.0.1\lib\xamarinmac20\_._ +system.reflection.emit\4.0.1\ref\MonoAndroid10\_._ +system.reflection.emit\4.0.1\ref\net45\_._ +system.reflection.emit\4.0.1\ref\netstandard1.1\System.Reflection.Emit.dll +system.reflection.emit\4.0.1\ref\xamarinmac20\_._ +system.reflection.emit\4.0.1\system.reflection.emit.4.0.1.nupkg.sha512 +system.reflection.emit\4.0.1\system.reflection.emit.nuspec +system.reflection.emit\4.0.1\ThirdPartyNotices.txt +system.reflection.emit\4.3.0\dotnet_library_license.txt +system.reflection.emit\4.3.0\lib\MonoAndroid10\_._ +system.reflection.emit\4.3.0\lib\monotouch10\_._ +system.reflection.emit\4.3.0\lib\net45\_._ +system.reflection.emit\4.3.0\lib\netcore50\System.Reflection.Emit.dll +system.reflection.emit\4.3.0\lib\netstandard1.3\System.Reflection.Emit.dll +system.reflection.emit\4.3.0\lib\xamarinios10\_._ +system.reflection.emit\4.3.0\lib\xamarinmac20\_._ +system.reflection.emit\4.3.0\lib\xamarintvos10\_._ +system.reflection.emit\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.emit\4.3.0\ref\MonoAndroid10\_._ +system.reflection.emit\4.3.0\ref\net45\_._ +system.reflection.emit\4.3.0\ref\netstandard1.1\System.Reflection.Emit.dll +system.reflection.emit\4.3.0\ref\xamarinmac20\_._ +system.reflection.emit\4.3.0\system.reflection.emit.4.3.0.nupkg.sha512 +system.reflection.emit\4.3.0\system.reflection.emit.nuspec +system.reflection.emit\4.3.0\ThirdPartyNotices.txt +system.reflection.extensions\4.0.1\dotnet_library_license.txt +system.reflection.extensions\4.0.1\lib\MonoAndroid10\_._ +system.reflection.extensions\4.0.1\lib\MonoTouch10\_._ +system.reflection.extensions\4.0.1\lib\net45\_._ +system.reflection.extensions\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection.extensions\4.0.1\lib\win8\_._ +system.reflection.extensions\4.0.1\lib\wp80\_._ +system.reflection.extensions\4.0.1\lib\wpa81\_._ +system.reflection.extensions\4.0.1\lib\xamarinios10\_._ +system.reflection.extensions\4.0.1\lib\xamarinmac20\_._ +system.reflection.extensions\4.0.1\lib\xamarintvos10\_._ +system.reflection.extensions\4.0.1\lib\xamarinwatchos10\_._ +system.reflection.extensions\4.0.1\ref\MonoAndroid10\_._ +system.reflection.extensions\4.0.1\ref\MonoTouch10\_._ +system.reflection.extensions\4.0.1\ref\net45\_._ +system.reflection.extensions\4.0.1\ref\netcore50\System.Reflection.Extensions.dll +system.reflection.extensions\4.0.1\ref\netstandard1.0\System.Reflection.Extensions.dll +system.reflection.extensions\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection.extensions\4.0.1\ref\win8\_._ +system.reflection.extensions\4.0.1\ref\wp80\_._ +system.reflection.extensions\4.0.1\ref\wpa81\_._ +system.reflection.extensions\4.0.1\ref\xamarinios10\_._ +system.reflection.extensions\4.0.1\ref\xamarinmac20\_._ +system.reflection.extensions\4.0.1\ref\xamarintvos10\_._ +system.reflection.extensions\4.0.1\ref\xamarinwatchos10\_._ +system.reflection.extensions\4.0.1\system.reflection.extensions.4.0.1.nupkg.sha512 +system.reflection.extensions\4.0.1\system.reflection.extensions.nuspec +system.reflection.extensions\4.0.1\ThirdPartyNotices.txt +system.reflection.extensions\4.3.0\dotnet_library_license.txt +system.reflection.extensions\4.3.0\lib\MonoAndroid10\_._ +system.reflection.extensions\4.3.0\lib\MonoTouch10\_._ +system.reflection.extensions\4.3.0\lib\net45\_._ +system.reflection.extensions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection.extensions\4.3.0\lib\win8\_._ +system.reflection.extensions\4.3.0\lib\wp80\_._ +system.reflection.extensions\4.3.0\lib\wpa81\_._ +system.reflection.extensions\4.3.0\lib\xamarinios10\_._ +system.reflection.extensions\4.3.0\lib\xamarinmac20\_._ +system.reflection.extensions\4.3.0\lib\xamarintvos10\_._ +system.reflection.extensions\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.extensions\4.3.0\ref\MonoAndroid10\_._ +system.reflection.extensions\4.3.0\ref\MonoTouch10\_._ +system.reflection.extensions\4.3.0\ref\net45\_._ +system.reflection.extensions\4.3.0\ref\netcore50\System.Reflection.Extensions.dll +system.reflection.extensions\4.3.0\ref\netstandard1.0\System.Reflection.Extensions.dll +system.reflection.extensions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection.extensions\4.3.0\ref\win8\_._ +system.reflection.extensions\4.3.0\ref\wp80\_._ +system.reflection.extensions\4.3.0\ref\wpa81\_._ +system.reflection.extensions\4.3.0\ref\xamarinios10\_._ +system.reflection.extensions\4.3.0\ref\xamarinmac20\_._ +system.reflection.extensions\4.3.0\ref\xamarintvos10\_._ +system.reflection.extensions\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.extensions\4.3.0\system.reflection.extensions.4.3.0.nupkg.sha512 +system.reflection.extensions\4.3.0\system.reflection.extensions.nuspec +system.reflection.extensions\4.3.0\ThirdPartyNotices.txt +system.reflection.metadata\1.4.1\dotnet_library_license.txt +system.reflection.metadata\1.4.1\lib\netstandard1.1\System.Reflection.Metadata.dll +system.reflection.metadata\1.4.1\lib\portable-net45+win8\System.Reflection.Metadata.dll +system.reflection.metadata\1.4.1\system.reflection.metadata.1.4.1.nupkg.sha512 +system.reflection.metadata\1.4.1\system.reflection.metadata.nuspec +system.reflection.metadata\1.4.1\ThirdPartyNotices.txt +system.reflection.metadata\1.4.2\dotnet_library_license.txt +system.reflection.metadata\1.4.2\lib\netstandard1.1\System.Reflection.Metadata.dll +system.reflection.metadata\1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll +system.reflection.metadata\1.4.2\system.reflection.metadata.1.4.2.nupkg.sha512 +system.reflection.metadata\1.4.2\system.reflection.metadata.nuspec +system.reflection.metadata\1.4.2\ThirdPartyNotices.txt +system.reflection.metadata\1.6.0\.signature.p7s +system.reflection.metadata\1.6.0\lib\netstandard1.1\System.Reflection.Metadata.dll +system.reflection.metadata\1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll +system.reflection.metadata\1.6.0\lib\portable-net45+win8\System.Reflection.Metadata.dll +system.reflection.metadata\1.6.0\LICENSE.TXT +system.reflection.metadata\1.6.0\system.reflection.metadata.1.6.0.nupkg.sha512 +system.reflection.metadata\1.6.0\system.reflection.metadata.nuspec +system.reflection.metadata\1.6.0\THIRD-PARTY-NOTICES.TXT +system.reflection.metadata\1.6.0\useSharedDesignerContext.txt +system.reflection.metadata\1.6.0\version.txt +system.reflection.primitives\4.0.1\dotnet_library_license.txt +system.reflection.primitives\4.0.1\lib\MonoAndroid10\_._ +system.reflection.primitives\4.0.1\lib\MonoTouch10\_._ +system.reflection.primitives\4.0.1\lib\net45\_._ +system.reflection.primitives\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection.primitives\4.0.1\lib\win8\_._ +system.reflection.primitives\4.0.1\lib\wp80\_._ +system.reflection.primitives\4.0.1\lib\wpa81\_._ +system.reflection.primitives\4.0.1\lib\xamarinios10\_._ +system.reflection.primitives\4.0.1\lib\xamarinmac20\_._ +system.reflection.primitives\4.0.1\lib\xamarintvos10\_._ +system.reflection.primitives\4.0.1\lib\xamarinwatchos10\_._ +system.reflection.primitives\4.0.1\ref\MonoAndroid10\_._ +system.reflection.primitives\4.0.1\ref\MonoTouch10\_._ +system.reflection.primitives\4.0.1\ref\net45\_._ +system.reflection.primitives\4.0.1\ref\netcore50\System.Reflection.Primitives.dll +system.reflection.primitives\4.0.1\ref\netstandard1.0\System.Reflection.Primitives.dll +system.reflection.primitives\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection.primitives\4.0.1\ref\win8\_._ +system.reflection.primitives\4.0.1\ref\wp80\_._ +system.reflection.primitives\4.0.1\ref\wpa81\_._ +system.reflection.primitives\4.0.1\ref\xamarinios10\_._ +system.reflection.primitives\4.0.1\ref\xamarinmac20\_._ +system.reflection.primitives\4.0.1\ref\xamarintvos10\_._ +system.reflection.primitives\4.0.1\ref\xamarinwatchos10\_._ +system.reflection.primitives\4.0.1\system.reflection.primitives.4.0.1.nupkg.sha512 +system.reflection.primitives\4.0.1\system.reflection.primitives.nuspec +system.reflection.primitives\4.0.1\ThirdPartyNotices.txt +system.reflection.primitives\4.3.0\dotnet_library_license.txt +system.reflection.primitives\4.3.0\lib\MonoAndroid10\_._ +system.reflection.primitives\4.3.0\lib\MonoTouch10\_._ +system.reflection.primitives\4.3.0\lib\net45\_._ +system.reflection.primitives\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection.primitives\4.3.0\lib\win8\_._ +system.reflection.primitives\4.3.0\lib\wp80\_._ +system.reflection.primitives\4.3.0\lib\wpa81\_._ +system.reflection.primitives\4.3.0\lib\xamarinios10\_._ +system.reflection.primitives\4.3.0\lib\xamarinmac20\_._ +system.reflection.primitives\4.3.0\lib\xamarintvos10\_._ +system.reflection.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.primitives\4.3.0\ref\MonoAndroid10\_._ +system.reflection.primitives\4.3.0\ref\MonoTouch10\_._ +system.reflection.primitives\4.3.0\ref\net45\_._ +system.reflection.primitives\4.3.0\ref\netcore50\System.Reflection.Primitives.dll +system.reflection.primitives\4.3.0\ref\netstandard1.0\System.Reflection.Primitives.dll +system.reflection.primitives\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection.primitives\4.3.0\ref\win8\_._ +system.reflection.primitives\4.3.0\ref\wp80\_._ +system.reflection.primitives\4.3.0\ref\wpa81\_._ +system.reflection.primitives\4.3.0\ref\xamarinios10\_._ +system.reflection.primitives\4.3.0\ref\xamarinmac20\_._ +system.reflection.primitives\4.3.0\ref\xamarintvos10\_._ +system.reflection.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.primitives\4.3.0\system.reflection.primitives.4.3.0.nupkg.sha512 +system.reflection.primitives\4.3.0\system.reflection.primitives.nuspec +system.reflection.primitives\4.3.0\ThirdPartyNotices.txt +system.reflection.typeextensions\4.1.0\dotnet_library_license.txt +system.reflection.typeextensions\4.1.0\lib\MonoAndroid10\_._ +system.reflection.typeextensions\4.1.0\lib\MonoTouch10\_._ +system.reflection.typeextensions\4.1.0\lib\net46\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\lib\net462\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\lib\netcore50\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\lib\netstandard1.5\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\lib\xamarinios10\_._ +system.reflection.typeextensions\4.1.0\lib\xamarinmac20\_._ +system.reflection.typeextensions\4.1.0\lib\xamarintvos10\_._ +system.reflection.typeextensions\4.1.0\lib\xamarinwatchos10\_._ +system.reflection.typeextensions\4.1.0\ref\MonoAndroid10\_._ +system.reflection.typeextensions\4.1.0\ref\MonoTouch10\_._ +system.reflection.typeextensions\4.1.0\ref\net46\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\ref\net462\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\ref\netstandard1.3\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\ref\netstandard1.5\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\ref\xamarinios10\_._ +system.reflection.typeextensions\4.1.0\ref\xamarinmac20\_._ +system.reflection.typeextensions\4.1.0\ref\xamarintvos10\_._ +system.reflection.typeextensions\4.1.0\ref\xamarinwatchos10\_._ +system.reflection.typeextensions\4.1.0\runtimes\aot\lib\netcore50\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.1.0\system.reflection.typeextensions.4.1.0.nupkg.sha512 +system.reflection.typeextensions\4.1.0\system.reflection.typeextensions.nuspec +system.reflection.typeextensions\4.1.0\ThirdPartyNotices.txt +system.reflection.typeextensions\4.3.0\dotnet_library_license.txt +system.reflection.typeextensions\4.3.0\lib\MonoAndroid10\_._ +system.reflection.typeextensions\4.3.0\lib\MonoTouch10\_._ +system.reflection.typeextensions\4.3.0\lib\net46\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\lib\net462\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\lib\netcore50\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\lib\netstandard1.5\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\lib\xamarinios10\_._ +system.reflection.typeextensions\4.3.0\lib\xamarinmac20\_._ +system.reflection.typeextensions\4.3.0\lib\xamarintvos10\_._ +system.reflection.typeextensions\4.3.0\lib\xamarinwatchos10\_._ +system.reflection.typeextensions\4.3.0\ref\MonoAndroid10\_._ +system.reflection.typeextensions\4.3.0\ref\MonoTouch10\_._ +system.reflection.typeextensions\4.3.0\ref\net46\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\ref\net462\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\ref\netstandard1.3\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\ref\netstandard1.5\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\ref\xamarinios10\_._ +system.reflection.typeextensions\4.3.0\ref\xamarinmac20\_._ +system.reflection.typeextensions\4.3.0\ref\xamarintvos10\_._ +system.reflection.typeextensions\4.3.0\ref\xamarinwatchos10\_._ +system.reflection.typeextensions\4.3.0\runtimes\aot\lib\netcore50\System.Reflection.TypeExtensions.dll +system.reflection.typeextensions\4.3.0\system.reflection.typeextensions.4.3.0.nupkg.sha512 +system.reflection.typeextensions\4.3.0\system.reflection.typeextensions.nuspec +system.reflection.typeextensions\4.3.0\ThirdPartyNotices.txt +system.reflection\4.1.0\dotnet_library_license.txt +system.reflection\4.1.0\lib\MonoAndroid10\_._ +system.reflection\4.1.0\lib\MonoTouch10\_._ +system.reflection\4.1.0\lib\net45\_._ +system.reflection\4.1.0\lib\net462\System.Reflection.dll +system.reflection\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection\4.1.0\lib\win8\_._ +system.reflection\4.1.0\lib\wp80\_._ +system.reflection\4.1.0\lib\wpa81\_._ +system.reflection\4.1.0\lib\xamarinios10\_._ +system.reflection\4.1.0\lib\xamarinmac20\_._ +system.reflection\4.1.0\lib\xamarintvos10\_._ +system.reflection\4.1.0\lib\xamarinwatchos10\_._ +system.reflection\4.1.0\ref\MonoAndroid10\_._ +system.reflection\4.1.0\ref\MonoTouch10\_._ +system.reflection\4.1.0\ref\net45\_._ +system.reflection\4.1.0\ref\net462\System.Reflection.dll +system.reflection\4.1.0\ref\netcore50\System.Reflection.dll +system.reflection\4.1.0\ref\netstandard1.0\System.Reflection.dll +system.reflection\4.1.0\ref\netstandard1.3\System.Reflection.dll +system.reflection\4.1.0\ref\netstandard1.5\System.Reflection.dll +system.reflection\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection\4.1.0\ref\win8\_._ +system.reflection\4.1.0\ref\wp80\_._ +system.reflection\4.1.0\ref\wpa81\_._ +system.reflection\4.1.0\ref\xamarinios10\_._ +system.reflection\4.1.0\ref\xamarinmac20\_._ +system.reflection\4.1.0\ref\xamarintvos10\_._ +system.reflection\4.1.0\ref\xamarinwatchos10\_._ +system.reflection\4.1.0\system.reflection.4.1.0.nupkg.sha512 +system.reflection\4.1.0\system.reflection.nuspec +system.reflection\4.1.0\ThirdPartyNotices.txt +system.reflection\4.3.0\dotnet_library_license.txt +system.reflection\4.3.0\lib\MonoAndroid10\_._ +system.reflection\4.3.0\lib\MonoTouch10\_._ +system.reflection\4.3.0\lib\net45\_._ +system.reflection\4.3.0\lib\net462\System.Reflection.dll +system.reflection\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.reflection\4.3.0\lib\win8\_._ +system.reflection\4.3.0\lib\wp80\_._ +system.reflection\4.3.0\lib\wpa81\_._ +system.reflection\4.3.0\lib\xamarinios10\_._ +system.reflection\4.3.0\lib\xamarinmac20\_._ +system.reflection\4.3.0\lib\xamarintvos10\_._ +system.reflection\4.3.0\lib\xamarinwatchos10\_._ +system.reflection\4.3.0\ref\MonoAndroid10\_._ +system.reflection\4.3.0\ref\MonoTouch10\_._ +system.reflection\4.3.0\ref\net45\_._ +system.reflection\4.3.0\ref\net462\System.Reflection.dll +system.reflection\4.3.0\ref\netcore50\System.Reflection.dll +system.reflection\4.3.0\ref\netstandard1.0\System.Reflection.dll +system.reflection\4.3.0\ref\netstandard1.3\System.Reflection.dll +system.reflection\4.3.0\ref\netstandard1.5\System.Reflection.dll +system.reflection\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.reflection\4.3.0\ref\win8\_._ +system.reflection\4.3.0\ref\wp80\_._ +system.reflection\4.3.0\ref\wpa81\_._ +system.reflection\4.3.0\ref\xamarinios10\_._ +system.reflection\4.3.0\ref\xamarinmac20\_._ +system.reflection\4.3.0\ref\xamarintvos10\_._ +system.reflection\4.3.0\ref\xamarinwatchos10\_._ +system.reflection\4.3.0\system.reflection.4.3.0.nupkg.sha512 +system.reflection\4.3.0\system.reflection.nuspec +system.reflection\4.3.0\ThirdPartyNotices.txt +system.resources.resourcemanager\4.0.1\dotnet_library_license.txt +system.resources.resourcemanager\4.0.1\lib\MonoAndroid10\_._ +system.resources.resourcemanager\4.0.1\lib\MonoTouch10\_._ +system.resources.resourcemanager\4.0.1\lib\net45\_._ +system.resources.resourcemanager\4.0.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.resources.resourcemanager\4.0.1\lib\win8\_._ +system.resources.resourcemanager\4.0.1\lib\wp80\_._ +system.resources.resourcemanager\4.0.1\lib\wpa81\_._ +system.resources.resourcemanager\4.0.1\lib\xamarinios10\_._ +system.resources.resourcemanager\4.0.1\lib\xamarinmac20\_._ +system.resources.resourcemanager\4.0.1\lib\xamarintvos10\_._ +system.resources.resourcemanager\4.0.1\lib\xamarinwatchos10\_._ +system.resources.resourcemanager\4.0.1\ref\MonoAndroid10\_._ +system.resources.resourcemanager\4.0.1\ref\MonoTouch10\_._ +system.resources.resourcemanager\4.0.1\ref\net45\_._ +system.resources.resourcemanager\4.0.1\ref\netcore50\System.Resources.ResourceManager.dll +system.resources.resourcemanager\4.0.1\ref\netstandard1.0\System.Resources.ResourceManager.dll +system.resources.resourcemanager\4.0.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.resources.resourcemanager\4.0.1\ref\win8\_._ +system.resources.resourcemanager\4.0.1\ref\wp80\_._ +system.resources.resourcemanager\4.0.1\ref\wpa81\_._ +system.resources.resourcemanager\4.0.1\ref\xamarinios10\_._ +system.resources.resourcemanager\4.0.1\ref\xamarinmac20\_._ +system.resources.resourcemanager\4.0.1\ref\xamarintvos10\_._ +system.resources.resourcemanager\4.0.1\ref\xamarinwatchos10\_._ +system.resources.resourcemanager\4.0.1\system.resources.resourcemanager.4.0.1.nupkg.sha512 +system.resources.resourcemanager\4.0.1\system.resources.resourcemanager.nuspec +system.resources.resourcemanager\4.0.1\ThirdPartyNotices.txt +system.resources.resourcemanager\4.3.0\dotnet_library_license.txt +system.resources.resourcemanager\4.3.0\lib\MonoAndroid10\_._ +system.resources.resourcemanager\4.3.0\lib\MonoTouch10\_._ +system.resources.resourcemanager\4.3.0\lib\net45\_._ +system.resources.resourcemanager\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.resources.resourcemanager\4.3.0\lib\win8\_._ +system.resources.resourcemanager\4.3.0\lib\wp80\_._ +system.resources.resourcemanager\4.3.0\lib\wpa81\_._ +system.resources.resourcemanager\4.3.0\lib\xamarinios10\_._ +system.resources.resourcemanager\4.3.0\lib\xamarinmac20\_._ +system.resources.resourcemanager\4.3.0\lib\xamarintvos10\_._ +system.resources.resourcemanager\4.3.0\lib\xamarinwatchos10\_._ +system.resources.resourcemanager\4.3.0\ref\MonoAndroid10\_._ +system.resources.resourcemanager\4.3.0\ref\MonoTouch10\_._ +system.resources.resourcemanager\4.3.0\ref\net45\_._ +system.resources.resourcemanager\4.3.0\ref\netcore50\System.Resources.ResourceManager.dll +system.resources.resourcemanager\4.3.0\ref\netstandard1.0\System.Resources.ResourceManager.dll +system.resources.resourcemanager\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.resources.resourcemanager\4.3.0\ref\win8\_._ +system.resources.resourcemanager\4.3.0\ref\wp80\_._ +system.resources.resourcemanager\4.3.0\ref\wpa81\_._ +system.resources.resourcemanager\4.3.0\ref\xamarinios10\_._ +system.resources.resourcemanager\4.3.0\ref\xamarinmac20\_._ +system.resources.resourcemanager\4.3.0\ref\xamarintvos10\_._ +system.resources.resourcemanager\4.3.0\ref\xamarinwatchos10\_._ +system.resources.resourcemanager\4.3.0\system.resources.resourcemanager.4.3.0.nupkg.sha512 +system.resources.resourcemanager\4.3.0\system.resources.resourcemanager.nuspec +system.resources.resourcemanager\4.3.0\ThirdPartyNotices.txt +system.runtime.compilerservices.unsafe\4.5.0\.signature.p7s +system.runtime.compilerservices.unsafe\4.5.0\lib\netcoreapp2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\lib\uap10.0.16300\_._ +system.runtime.compilerservices.unsafe\4.5.0\LICENSE.TXT +system.runtime.compilerservices.unsafe\4.5.0\ref\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\ref\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.0\ref\uap10.0.16300\_._ +system.runtime.compilerservices.unsafe\4.5.0\system.runtime.compilerservices.unsafe.4.5.0.nupkg.sha512 +system.runtime.compilerservices.unsafe\4.5.0\system.runtime.compilerservices.unsafe.nuspec +system.runtime.compilerservices.unsafe\4.5.0\THIRD-PARTY-NOTICES.TXT +system.runtime.compilerservices.unsafe\4.5.0\useSharedDesignerContext.txt +system.runtime.compilerservices.unsafe\4.5.0\version.txt +system.runtime.compilerservices.unsafe\4.5.1\.signature.p7s +system.runtime.compilerservices.unsafe\4.5.1\lib\netcoreapp2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\LICENSE.TXT +system.runtime.compilerservices.unsafe\4.5.1\ref\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\ref\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll +system.runtime.compilerservices.unsafe\4.5.1\system.runtime.compilerservices.unsafe.4.5.1.nupkg.sha512 +system.runtime.compilerservices.unsafe\4.5.1\system.runtime.compilerservices.unsafe.nuspec +system.runtime.compilerservices.unsafe\4.5.1\THIRD-PARTY-NOTICES.TXT +system.runtime.compilerservices.unsafe\4.5.1\useSharedDesignerContext.txt +system.runtime.compilerservices.unsafe\4.5.1\version.txt +system.runtime.extensions\4.1.0\dotnet_library_license.txt +system.runtime.extensions\4.1.0\lib\MonoAndroid10\_._ +system.runtime.extensions\4.1.0\lib\MonoTouch10\_._ +system.runtime.extensions\4.1.0\lib\net45\_._ +system.runtime.extensions\4.1.0\lib\net462\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.extensions\4.1.0\lib\win8\_._ +system.runtime.extensions\4.1.0\lib\wp80\_._ +system.runtime.extensions\4.1.0\lib\wpa81\_._ +system.runtime.extensions\4.1.0\lib\xamarinios10\_._ +system.runtime.extensions\4.1.0\lib\xamarinmac20\_._ +system.runtime.extensions\4.1.0\lib\xamarintvos10\_._ +system.runtime.extensions\4.1.0\lib\xamarinwatchos10\_._ +system.runtime.extensions\4.1.0\ref\MonoAndroid10\_._ +system.runtime.extensions\4.1.0\ref\MonoTouch10\_._ +system.runtime.extensions\4.1.0\ref\net45\_._ +system.runtime.extensions\4.1.0\ref\net462\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\netcore50\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\netstandard1.0\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\netstandard1.3\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\netstandard1.5\System.Runtime.Extensions.dll +system.runtime.extensions\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.extensions\4.1.0\ref\win8\_._ +system.runtime.extensions\4.1.0\ref\wp80\_._ +system.runtime.extensions\4.1.0\ref\wpa81\_._ +system.runtime.extensions\4.1.0\ref\xamarinios10\_._ +system.runtime.extensions\4.1.0\ref\xamarinmac20\_._ +system.runtime.extensions\4.1.0\ref\xamarintvos10\_._ +system.runtime.extensions\4.1.0\ref\xamarinwatchos10\_._ +system.runtime.extensions\4.1.0\system.runtime.extensions.4.1.0.nupkg.sha512 +system.runtime.extensions\4.1.0\system.runtime.extensions.nuspec +system.runtime.extensions\4.1.0\ThirdPartyNotices.txt +system.runtime.extensions\4.3.0\dotnet_library_license.txt +system.runtime.extensions\4.3.0\lib\MonoAndroid10\_._ +system.runtime.extensions\4.3.0\lib\MonoTouch10\_._ +system.runtime.extensions\4.3.0\lib\net45\_._ +system.runtime.extensions\4.3.0\lib\net462\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.extensions\4.3.0\lib\win8\_._ +system.runtime.extensions\4.3.0\lib\wp80\_._ +system.runtime.extensions\4.3.0\lib\wpa81\_._ +system.runtime.extensions\4.3.0\lib\xamarinios10\_._ +system.runtime.extensions\4.3.0\lib\xamarinmac20\_._ +system.runtime.extensions\4.3.0\lib\xamarintvos10\_._ +system.runtime.extensions\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.extensions\4.3.0\ref\MonoAndroid10\_._ +system.runtime.extensions\4.3.0\ref\MonoTouch10\_._ +system.runtime.extensions\4.3.0\ref\net45\_._ +system.runtime.extensions\4.3.0\ref\net462\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\netcore50\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\netstandard1.0\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\netstandard1.3\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\netstandard1.5\System.Runtime.Extensions.dll +system.runtime.extensions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.extensions\4.3.0\ref\win8\_._ +system.runtime.extensions\4.3.0\ref\wp80\_._ +system.runtime.extensions\4.3.0\ref\wpa81\_._ +system.runtime.extensions\4.3.0\ref\xamarinios10\_._ +system.runtime.extensions\4.3.0\ref\xamarinmac20\_._ +system.runtime.extensions\4.3.0\ref\xamarintvos10\_._ +system.runtime.extensions\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.extensions\4.3.0\system.runtime.extensions.4.3.0.nupkg.sha512 +system.runtime.extensions\4.3.0\system.runtime.extensions.nuspec +system.runtime.extensions\4.3.0\ThirdPartyNotices.txt +system.runtime.handles\4.0.1\dotnet_library_license.txt +system.runtime.handles\4.0.1\lib\MonoAndroid10\_._ +system.runtime.handles\4.0.1\lib\MonoTouch10\_._ +system.runtime.handles\4.0.1\lib\net46\_._ +system.runtime.handles\4.0.1\lib\xamarinios10\_._ +system.runtime.handles\4.0.1\lib\xamarinmac20\_._ +system.runtime.handles\4.0.1\lib\xamarintvos10\_._ +system.runtime.handles\4.0.1\lib\xamarinwatchos10\_._ +system.runtime.handles\4.0.1\ref\MonoAndroid10\_._ +system.runtime.handles\4.0.1\ref\MonoTouch10\_._ +system.runtime.handles\4.0.1\ref\net46\_._ +system.runtime.handles\4.0.1\ref\netstandard1.3\System.Runtime.Handles.dll +system.runtime.handles\4.0.1\ref\xamarinios10\_._ +system.runtime.handles\4.0.1\ref\xamarinmac20\_._ +system.runtime.handles\4.0.1\ref\xamarintvos10\_._ +system.runtime.handles\4.0.1\ref\xamarinwatchos10\_._ +system.runtime.handles\4.0.1\system.runtime.handles.4.0.1.nupkg.sha512 +system.runtime.handles\4.0.1\system.runtime.handles.nuspec +system.runtime.handles\4.0.1\ThirdPartyNotices.txt +system.runtime.handles\4.3.0\dotnet_library_license.txt +system.runtime.handles\4.3.0\lib\MonoAndroid10\_._ +system.runtime.handles\4.3.0\lib\MonoTouch10\_._ +system.runtime.handles\4.3.0\lib\net46\_._ +system.runtime.handles\4.3.0\lib\xamarinios10\_._ +system.runtime.handles\4.3.0\lib\xamarinmac20\_._ +system.runtime.handles\4.3.0\lib\xamarintvos10\_._ +system.runtime.handles\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.handles\4.3.0\ref\MonoAndroid10\_._ +system.runtime.handles\4.3.0\ref\MonoTouch10\_._ +system.runtime.handles\4.3.0\ref\net46\_._ +system.runtime.handles\4.3.0\ref\netstandard1.3\System.Runtime.Handles.dll +system.runtime.handles\4.3.0\ref\xamarinios10\_._ +system.runtime.handles\4.3.0\ref\xamarinmac20\_._ +system.runtime.handles\4.3.0\ref\xamarintvos10\_._ +system.runtime.handles\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.handles\4.3.0\system.runtime.handles.4.3.0.nupkg.sha512 +system.runtime.handles\4.3.0\system.runtime.handles.nuspec +system.runtime.handles\4.3.0\ThirdPartyNotices.txt +system.runtime.interopservices.runtimeinformation\4.0.0\dotnet_library_license.txt +system.runtime.interopservices.runtimeinformation\4.0.0\lib\MonoAndroid10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\MonoTouch10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\lib\win8\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\lib\wpa81\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\lib\xamarinios10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\xamarinmac20\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\xamarintvos10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\lib\xamarinwatchos10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\MonoAndroid10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\MonoTouch10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\ref\xamarinios10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\xamarinmac20\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\xamarintvos10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\ref\xamarinwatchos10\_._ +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\aot\lib\netcore50\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\unix\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\win\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\win\lib\netcore50\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\runtimes\win\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.0.0\system.runtime.interopservices.runtimeinformation.4.0.0.nupkg.sha512 +system.runtime.interopservices.runtimeinformation\4.0.0\system.runtime.interopservices.runtimeinformation.nuspec +system.runtime.interopservices.runtimeinformation\4.0.0\ThirdPartyNotices.txt +system.runtime.interopservices.runtimeinformation\4.3.0\dotnet_library_license.txt +system.runtime.interopservices.runtimeinformation\4.3.0\lib\MonoAndroid10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\MonoTouch10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\lib\win8\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\lib\wpa81\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\lib\xamarinios10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\xamarinmac20\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\xamarintvos10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\MonoAndroid10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\MonoTouch10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\ref\xamarinios10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\xamarinmac20\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\xamarintvos10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\aot\lib\netcore50\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\unix\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\win\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\win\lib\netcore50\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\runtimes\win\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll +system.runtime.interopservices.runtimeinformation\4.3.0\system.runtime.interopservices.runtimeinformation.4.3.0.nupkg.sha512 +system.runtime.interopservices.runtimeinformation\4.3.0\system.runtime.interopservices.runtimeinformation.nuspec +system.runtime.interopservices.runtimeinformation\4.3.0\ThirdPartyNotices.txt +system.runtime.interopservices\4.1.0\dotnet_library_license.txt +system.runtime.interopservices\4.1.0\lib\MonoAndroid10\_._ +system.runtime.interopservices\4.1.0\lib\MonoTouch10\_._ +system.runtime.interopservices\4.1.0\lib\net45\_._ +system.runtime.interopservices\4.1.0\lib\net462\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\lib\portable-net45+win8+wpa81\_._ +system.runtime.interopservices\4.1.0\lib\win8\_._ +system.runtime.interopservices\4.1.0\lib\wpa81\_._ +system.runtime.interopservices\4.1.0\lib\xamarinios10\_._ +system.runtime.interopservices\4.1.0\lib\xamarinmac20\_._ +system.runtime.interopservices\4.1.0\lib\xamarintvos10\_._ +system.runtime.interopservices\4.1.0\lib\xamarinwatchos10\_._ +system.runtime.interopservices\4.1.0\ref\MonoAndroid10\_._ +system.runtime.interopservices\4.1.0\ref\MonoTouch10\_._ +system.runtime.interopservices\4.1.0\ref\net45\_._ +system.runtime.interopservices\4.1.0\ref\net462\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netcore50\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netstandard1.1\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netstandard1.2\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netstandard1.3\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\netstandard1.5\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.1.0\ref\portable-net45+win8+wpa81\_._ +system.runtime.interopservices\4.1.0\ref\win8\_._ +system.runtime.interopservices\4.1.0\ref\wpa81\_._ +system.runtime.interopservices\4.1.0\ref\xamarinios10\_._ +system.runtime.interopservices\4.1.0\ref\xamarinmac20\_._ +system.runtime.interopservices\4.1.0\ref\xamarintvos10\_._ +system.runtime.interopservices\4.1.0\ref\xamarinwatchos10\_._ +system.runtime.interopservices\4.1.0\system.runtime.interopservices.4.1.0.nupkg.sha512 +system.runtime.interopservices\4.1.0\system.runtime.interopservices.nuspec +system.runtime.interopservices\4.1.0\ThirdPartyNotices.txt +system.runtime.interopservices\4.3.0\dotnet_library_license.txt +system.runtime.interopservices\4.3.0\lib\MonoAndroid10\_._ +system.runtime.interopservices\4.3.0\lib\MonoTouch10\_._ +system.runtime.interopservices\4.3.0\lib\net45\_._ +system.runtime.interopservices\4.3.0\lib\net462\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\lib\net463\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.runtime.interopservices\4.3.0\lib\win8\_._ +system.runtime.interopservices\4.3.0\lib\wpa81\_._ +system.runtime.interopservices\4.3.0\lib\xamarinios10\_._ +system.runtime.interopservices\4.3.0\lib\xamarinmac20\_._ +system.runtime.interopservices\4.3.0\lib\xamarintvos10\_._ +system.runtime.interopservices\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.interopservices\4.3.0\ref\MonoAndroid10\_._ +system.runtime.interopservices\4.3.0\ref\MonoTouch10\_._ +system.runtime.interopservices\4.3.0\ref\net45\_._ +system.runtime.interopservices\4.3.0\ref\net462\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\net463\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netcore50\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netcoreapp1.1\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netstandard1.1\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netstandard1.2\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netstandard1.3\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\netstandard1.5\System.Runtime.InteropServices.dll +system.runtime.interopservices\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.runtime.interopservices\4.3.0\ref\win8\_._ +system.runtime.interopservices\4.3.0\ref\wpa81\_._ +system.runtime.interopservices\4.3.0\ref\xamarinios10\_._ +system.runtime.interopservices\4.3.0\ref\xamarinmac20\_._ +system.runtime.interopservices\4.3.0\ref\xamarintvos10\_._ +system.runtime.interopservices\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.interopservices\4.3.0\system.runtime.interopservices.4.3.0.nupkg.sha512 +system.runtime.interopservices\4.3.0\system.runtime.interopservices.nuspec +system.runtime.interopservices\4.3.0\ThirdPartyNotices.txt +system.runtime.numerics\4.0.1\dotnet_library_license.txt +system.runtime.numerics\4.0.1\lib\MonoAndroid10\_._ +system.runtime.numerics\4.0.1\lib\MonoTouch10\_._ +system.runtime.numerics\4.0.1\lib\net45\_._ +system.runtime.numerics\4.0.1\lib\netcore50\System.Runtime.Numerics.dll +system.runtime.numerics\4.0.1\lib\netstandard1.3\System.Runtime.Numerics.dll +system.runtime.numerics\4.0.1\lib\portable-net45+win8+wpa81\_._ +system.runtime.numerics\4.0.1\lib\win8\_._ +system.runtime.numerics\4.0.1\lib\wpa81\_._ +system.runtime.numerics\4.0.1\lib\xamarinios10\_._ +system.runtime.numerics\4.0.1\lib\xamarinmac20\_._ +system.runtime.numerics\4.0.1\lib\xamarintvos10\_._ +system.runtime.numerics\4.0.1\lib\xamarinwatchos10\_._ +system.runtime.numerics\4.0.1\ref\MonoAndroid10\_._ +system.runtime.numerics\4.0.1\ref\MonoTouch10\_._ +system.runtime.numerics\4.0.1\ref\net45\_._ +system.runtime.numerics\4.0.1\ref\netcore50\System.Runtime.Numerics.dll +system.runtime.numerics\4.0.1\ref\netstandard1.1\System.Runtime.Numerics.dll +system.runtime.numerics\4.0.1\ref\portable-net45+win8+wpa81\_._ +system.runtime.numerics\4.0.1\ref\win8\_._ +system.runtime.numerics\4.0.1\ref\wpa81\_._ +system.runtime.numerics\4.0.1\ref\xamarinios10\_._ +system.runtime.numerics\4.0.1\ref\xamarinmac20\_._ +system.runtime.numerics\4.0.1\ref\xamarintvos10\_._ +system.runtime.numerics\4.0.1\ref\xamarinwatchos10\_._ +system.runtime.numerics\4.0.1\system.runtime.numerics.4.0.1.nupkg.sha512 +system.runtime.numerics\4.0.1\system.runtime.numerics.nuspec +system.runtime.numerics\4.0.1\ThirdPartyNotices.txt +system.runtime.numerics\4.3.0\dotnet_library_license.txt +system.runtime.numerics\4.3.0\lib\MonoAndroid10\_._ +system.runtime.numerics\4.3.0\lib\MonoTouch10\_._ +system.runtime.numerics\4.3.0\lib\net45\_._ +system.runtime.numerics\4.3.0\lib\netcore50\System.Runtime.Numerics.dll +system.runtime.numerics\4.3.0\lib\netstandard1.3\System.Runtime.Numerics.dll +system.runtime.numerics\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.runtime.numerics\4.3.0\lib\win8\_._ +system.runtime.numerics\4.3.0\lib\wpa81\_._ +system.runtime.numerics\4.3.0\lib\xamarinios10\_._ +system.runtime.numerics\4.3.0\lib\xamarinmac20\_._ +system.runtime.numerics\4.3.0\lib\xamarintvos10\_._ +system.runtime.numerics\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.numerics\4.3.0\ref\MonoAndroid10\_._ +system.runtime.numerics\4.3.0\ref\MonoTouch10\_._ +system.runtime.numerics\4.3.0\ref\net45\_._ +system.runtime.numerics\4.3.0\ref\netcore50\System.Runtime.Numerics.dll +system.runtime.numerics\4.3.0\ref\netstandard1.1\System.Runtime.Numerics.dll +system.runtime.numerics\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.runtime.numerics\4.3.0\ref\win8\_._ +system.runtime.numerics\4.3.0\ref\wpa81\_._ +system.runtime.numerics\4.3.0\ref\xamarinios10\_._ +system.runtime.numerics\4.3.0\ref\xamarinmac20\_._ +system.runtime.numerics\4.3.0\ref\xamarintvos10\_._ +system.runtime.numerics\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.numerics\4.3.0\system.runtime.numerics.4.3.0.nupkg.sha512 +system.runtime.numerics\4.3.0\system.runtime.numerics.nuspec +system.runtime.numerics\4.3.0\ThirdPartyNotices.txt +system.runtime.serialization.formatters\4.3.0\dotnet_library_license.txt +system.runtime.serialization.formatters\4.3.0\lib\MonoAndroid10\_._ +system.runtime.serialization.formatters\4.3.0\lib\MonoTouch10\_._ +system.runtime.serialization.formatters\4.3.0\lib\net46\System.Runtime.Serialization.Formatters.dll +system.runtime.serialization.formatters\4.3.0\lib\netstandard1.4\System.Runtime.Serialization.Formatters.dll +system.runtime.serialization.formatters\4.3.0\lib\xamarinios10\_._ +system.runtime.serialization.formatters\4.3.0\lib\xamarinmac20\_._ +system.runtime.serialization.formatters\4.3.0\lib\xamarintvos10\_._ +system.runtime.serialization.formatters\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.serialization.formatters\4.3.0\ref\MonoAndroid10\_._ +system.runtime.serialization.formatters\4.3.0\ref\MonoTouch10\_._ +system.runtime.serialization.formatters\4.3.0\ref\net46\System.Runtime.Serialization.Formatters.dll +system.runtime.serialization.formatters\4.3.0\ref\netstandard1.3\System.Runtime.Serialization.Formatters.dll +system.runtime.serialization.formatters\4.3.0\ref\xamarinios10\_._ +system.runtime.serialization.formatters\4.3.0\ref\xamarinmac20\_._ +system.runtime.serialization.formatters\4.3.0\ref\xamarintvos10\_._ +system.runtime.serialization.formatters\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.serialization.formatters\4.3.0\system.runtime.serialization.formatters.4.3.0.nupkg.sha512 +system.runtime.serialization.formatters\4.3.0\system.runtime.serialization.formatters.nuspec +system.runtime.serialization.formatters\4.3.0\ThirdPartyNotices.txt +system.runtime.serialization.json\4.0.2\dotnet_library_license.txt +system.runtime.serialization.json\4.0.2\lib\MonoAndroid10\_._ +system.runtime.serialization.json\4.0.2\lib\MonoTouch10\_._ +system.runtime.serialization.json\4.0.2\lib\net45\_._ +system.runtime.serialization.json\4.0.2\lib\netcore50\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.0.2\lib\netstandard1.3\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.0.2\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.json\4.0.2\lib\win8\_._ +system.runtime.serialization.json\4.0.2\lib\wp80\_._ +system.runtime.serialization.json\4.0.2\lib\wpa81\_._ +system.runtime.serialization.json\4.0.2\lib\xamarinios10\_._ +system.runtime.serialization.json\4.0.2\lib\xamarinmac20\_._ +system.runtime.serialization.json\4.0.2\lib\xamarintvos10\_._ +system.runtime.serialization.json\4.0.2\lib\xamarinwatchos10\_._ +system.runtime.serialization.json\4.0.2\ref\MonoAndroid10\_._ +system.runtime.serialization.json\4.0.2\ref\MonoTouch10\_._ +system.runtime.serialization.json\4.0.2\ref\net45\_._ +system.runtime.serialization.json\4.0.2\ref\netcore50\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.0.2\ref\netstandard1.0\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.0.2\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.json\4.0.2\ref\win8\_._ +system.runtime.serialization.json\4.0.2\ref\wp80\_._ +system.runtime.serialization.json\4.0.2\ref\wpa81\_._ +system.runtime.serialization.json\4.0.2\ref\xamarinios10\_._ +system.runtime.serialization.json\4.0.2\ref\xamarinmac20\_._ +system.runtime.serialization.json\4.0.2\ref\xamarintvos10\_._ +system.runtime.serialization.json\4.0.2\ref\xamarinwatchos10\_._ +system.runtime.serialization.json\4.0.2\system.runtime.serialization.json.4.0.2.nupkg.sha512 +system.runtime.serialization.json\4.0.2\system.runtime.serialization.json.nuspec +system.runtime.serialization.json\4.0.2\ThirdPartyNotices.txt +system.runtime.serialization.primitives\4.1.1\dotnet_library_license.txt +system.runtime.serialization.primitives\4.1.1\lib\MonoAndroid10\_._ +system.runtime.serialization.primitives\4.1.1\lib\MonoTouch10\_._ +system.runtime.serialization.primitives\4.1.1\lib\net45\_._ +system.runtime.serialization.primitives\4.1.1\lib\net46\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\lib\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\lib\netstandard1.3\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.primitives\4.1.1\lib\win8\_._ +system.runtime.serialization.primitives\4.1.1\lib\wp80\_._ +system.runtime.serialization.primitives\4.1.1\lib\wpa81\_._ +system.runtime.serialization.primitives\4.1.1\lib\xamarinios10\_._ +system.runtime.serialization.primitives\4.1.1\lib\xamarinmac20\_._ +system.runtime.serialization.primitives\4.1.1\lib\xamarintvos10\_._ +system.runtime.serialization.primitives\4.1.1\lib\xamarinwatchos10\_._ +system.runtime.serialization.primitives\4.1.1\ref\MonoAndroid10\_._ +system.runtime.serialization.primitives\4.1.1\ref\MonoTouch10\_._ +system.runtime.serialization.primitives\4.1.1\ref\net45\_._ +system.runtime.serialization.primitives\4.1.1\ref\net46\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\ref\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\ref\netstandard1.0\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\ref\netstandard1.3\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.primitives\4.1.1\ref\win8\_._ +system.runtime.serialization.primitives\4.1.1\ref\wp80\_._ +system.runtime.serialization.primitives\4.1.1\ref\wpa81\_._ +system.runtime.serialization.primitives\4.1.1\ref\xamarinios10\_._ +system.runtime.serialization.primitives\4.1.1\ref\xamarinmac20\_._ +system.runtime.serialization.primitives\4.1.1\ref\xamarintvos10\_._ +system.runtime.serialization.primitives\4.1.1\ref\xamarinwatchos10\_._ +system.runtime.serialization.primitives\4.1.1\runtimes\aot\lib\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.1.1\system.runtime.serialization.primitives.4.1.1.nupkg.sha512 +system.runtime.serialization.primitives\4.1.1\system.runtime.serialization.primitives.nuspec +system.runtime.serialization.primitives\4.1.1\ThirdPartyNotices.txt +system.runtime.serialization.primitives\4.3.0\dotnet_library_license.txt +system.runtime.serialization.primitives\4.3.0\lib\MonoAndroid10\_._ +system.runtime.serialization.primitives\4.3.0\lib\MonoTouch10\_._ +system.runtime.serialization.primitives\4.3.0\lib\net45\_._ +system.runtime.serialization.primitives\4.3.0\lib\net46\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\lib\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\lib\netstandard1.3\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.primitives\4.3.0\lib\win8\_._ +system.runtime.serialization.primitives\4.3.0\lib\wp80\_._ +system.runtime.serialization.primitives\4.3.0\lib\wpa81\_._ +system.runtime.serialization.primitives\4.3.0\lib\xamarinios10\_._ +system.runtime.serialization.primitives\4.3.0\lib\xamarinmac20\_._ +system.runtime.serialization.primitives\4.3.0\lib\xamarintvos10\_._ +system.runtime.serialization.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.serialization.primitives\4.3.0\ref\MonoAndroid10\_._ +system.runtime.serialization.primitives\4.3.0\ref\MonoTouch10\_._ +system.runtime.serialization.primitives\4.3.0\ref\net45\_._ +system.runtime.serialization.primitives\4.3.0\ref\net46\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\ref\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\ref\netstandard1.0\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\ref\netstandard1.3\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.primitives\4.3.0\ref\win8\_._ +system.runtime.serialization.primitives\4.3.0\ref\wp80\_._ +system.runtime.serialization.primitives\4.3.0\ref\wpa81\_._ +system.runtime.serialization.primitives\4.3.0\ref\xamarinios10\_._ +system.runtime.serialization.primitives\4.3.0\ref\xamarinmac20\_._ +system.runtime.serialization.primitives\4.3.0\ref\xamarintvos10\_._ +system.runtime.serialization.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.serialization.primitives\4.3.0\runtimes\aot\lib\netcore50\System.Runtime.Serialization.Primitives.dll +system.runtime.serialization.primitives\4.3.0\system.runtime.serialization.primitives.4.3.0.nupkg.sha512 +system.runtime.serialization.primitives\4.3.0\system.runtime.serialization.primitives.nuspec +system.runtime.serialization.primitives\4.3.0\ThirdPartyNotices.txt +system.runtime.serialization.xml\4.3.0\dotnet_library_license.txt +system.runtime.serialization.xml\4.3.0\lib\MonoAndroid10\_._ +system.runtime.serialization.xml\4.3.0\lib\MonoTouch10\_._ +system.runtime.serialization.xml\4.3.0\lib\net45\_._ +system.runtime.serialization.xml\4.3.0\lib\net46\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\lib\netcore50\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\lib\netstandard1.3\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.xml\4.3.0\lib\win8\_._ +system.runtime.serialization.xml\4.3.0\lib\wp80\_._ +system.runtime.serialization.xml\4.3.0\lib\wpa81\_._ +system.runtime.serialization.xml\4.3.0\lib\xamarinios10\_._ +system.runtime.serialization.xml\4.3.0\lib\xamarinmac20\_._ +system.runtime.serialization.xml\4.3.0\lib\xamarintvos10\_._ +system.runtime.serialization.xml\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.serialization.xml\4.3.0\ref\MonoAndroid10\_._ +system.runtime.serialization.xml\4.3.0\ref\MonoTouch10\_._ +system.runtime.serialization.xml\4.3.0\ref\net45\_._ +system.runtime.serialization.xml\4.3.0\ref\net46\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\ref\netcore50\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\ref\netstandard1.0\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\ref\netstandard1.3\System.Runtime.Serialization.Xml.dll +system.runtime.serialization.xml\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.xml\4.3.0\ref\win8\_._ +system.runtime.serialization.xml\4.3.0\ref\wp80\_._ +system.runtime.serialization.xml\4.3.0\ref\wpa81\_._ +system.runtime.serialization.xml\4.3.0\ref\xamarinios10\_._ +system.runtime.serialization.xml\4.3.0\ref\xamarinmac20\_._ +system.runtime.serialization.xml\4.3.0\ref\xamarintvos10\_._ +system.runtime.serialization.xml\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.serialization.xml\4.3.0\system.runtime.serialization.xml.4.3.0.nupkg.sha512 +system.runtime.serialization.xml\4.3.0\system.runtime.serialization.xml.nuspec +system.runtime.serialization.xml\4.3.0\ThirdPartyNotices.txt +system.runtime\4.1.0\dotnet_library_license.txt +system.runtime\4.1.0\lib\MonoAndroid10\_._ +system.runtime\4.1.0\lib\MonoTouch10\_._ +system.runtime\4.1.0\lib\net45\_._ +system.runtime\4.1.0\lib\net462\System.Runtime.dll +system.runtime\4.1.0\lib\portable-net45+win8+wp80+wpa81\_._ +system.runtime\4.1.0\lib\win8\_._ +system.runtime\4.1.0\lib\wp80\_._ +system.runtime\4.1.0\lib\wpa81\_._ +system.runtime\4.1.0\lib\xamarinios10\_._ +system.runtime\4.1.0\lib\xamarinmac20\_._ +system.runtime\4.1.0\lib\xamarintvos10\_._ +system.runtime\4.1.0\lib\xamarinwatchos10\_._ +system.runtime\4.1.0\ref\MonoAndroid10\_._ +system.runtime\4.1.0\ref\MonoTouch10\_._ +system.runtime\4.1.0\ref\net45\_._ +system.runtime\4.1.0\ref\net462\System.Runtime.dll +system.runtime\4.1.0\ref\netcore50\System.Runtime.dll +system.runtime\4.1.0\ref\netstandard1.0\System.Runtime.dll +system.runtime\4.1.0\ref\netstandard1.2\System.Runtime.dll +system.runtime\4.1.0\ref\netstandard1.3\System.Runtime.dll +system.runtime\4.1.0\ref\netstandard1.5\System.Runtime.dll +system.runtime\4.1.0\ref\portable-net45+win8+wp80+wpa81\_._ +system.runtime\4.1.0\ref\win8\_._ +system.runtime\4.1.0\ref\wp80\_._ +system.runtime\4.1.0\ref\wpa81\_._ +system.runtime\4.1.0\ref\xamarinios10\_._ +system.runtime\4.1.0\ref\xamarinmac20\_._ +system.runtime\4.1.0\ref\xamarintvos10\_._ +system.runtime\4.1.0\ref\xamarinwatchos10\_._ +system.runtime\4.1.0\system.runtime.4.1.0.nupkg.sha512 +system.runtime\4.1.0\system.runtime.nuspec +system.runtime\4.1.0\ThirdPartyNotices.txt +system.runtime\4.3.0\dotnet_library_license.txt +system.runtime\4.3.0\lib\MonoAndroid10\_._ +system.runtime\4.3.0\lib\MonoTouch10\_._ +system.runtime\4.3.0\lib\net45\_._ +system.runtime\4.3.0\lib\net462\System.Runtime.dll +system.runtime\4.3.0\lib\portable-net45+win8+wp80+wpa81\_._ +system.runtime\4.3.0\lib\win8\_._ +system.runtime\4.3.0\lib\wp80\_._ +system.runtime\4.3.0\lib\wpa81\_._ +system.runtime\4.3.0\lib\xamarinios10\_._ +system.runtime\4.3.0\lib\xamarinmac20\_._ +system.runtime\4.3.0\lib\xamarintvos10\_._ +system.runtime\4.3.0\lib\xamarinwatchos10\_._ +system.runtime\4.3.0\ref\MonoAndroid10\_._ +system.runtime\4.3.0\ref\MonoTouch10\_._ +system.runtime\4.3.0\ref\net45\_._ +system.runtime\4.3.0\ref\net462\System.Runtime.dll +system.runtime\4.3.0\ref\netcore50\System.Runtime.dll +system.runtime\4.3.0\ref\netstandard1.0\System.Runtime.dll +system.runtime\4.3.0\ref\netstandard1.2\System.Runtime.dll +system.runtime\4.3.0\ref\netstandard1.3\System.Runtime.dll +system.runtime\4.3.0\ref\netstandard1.5\System.Runtime.dll +system.runtime\4.3.0\ref\portable-net45+win8+wp80+wpa81\_._ +system.runtime\4.3.0\ref\win8\_._ +system.runtime\4.3.0\ref\wp80\_._ +system.runtime\4.3.0\ref\wpa81\_._ +system.runtime\4.3.0\ref\xamarinios10\_._ +system.runtime\4.3.0\ref\xamarinmac20\_._ +system.runtime\4.3.0\ref\xamarintvos10\_._ +system.runtime\4.3.0\ref\xamarinwatchos10\_._ +system.runtime\4.3.0\system.runtime.4.3.0.nupkg.sha512 +system.runtime\4.3.0\system.runtime.nuspec +system.runtime\4.3.0\ThirdPartyNotices.txt +system.security.accesscontrol\4.5.0\.signature.p7s +system.security.accesscontrol\4.5.0\lib\net46\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\lib\net461\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\lib\netstandard1.3\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\lib\netstandard2.0\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\lib\uap10.0.16299\_._ +system.security.accesscontrol\4.5.0\LICENSE.TXT +system.security.accesscontrol\4.5.0\ref\net46\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\ref\net461\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\ref\netstandard1.3\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\ref\netstandard2.0\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\ref\uap10.0.16299\_._ +system.security.accesscontrol\4.5.0\runtimes\win\lib\net46\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\runtimes\win\lib\net461\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\runtimes\win\lib\netstandard1.3\System.Security.AccessControl.dll +system.security.accesscontrol\4.5.0\runtimes\win\lib\uap10.0.16299\_._ +system.security.accesscontrol\4.5.0\system.security.accesscontrol.4.5.0.nupkg.sha512 +system.security.accesscontrol\4.5.0\system.security.accesscontrol.nuspec +system.security.accesscontrol\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.accesscontrol\4.5.0\useSharedDesignerContext.txt +system.security.accesscontrol\4.5.0\version.txt +system.security.claims\4.3.0\dotnet_library_license.txt +system.security.claims\4.3.0\lib\MonoAndroid10\_._ +system.security.claims\4.3.0\lib\MonoTouch10\_._ +system.security.claims\4.3.0\lib\net46\System.Security.Claims.dll +system.security.claims\4.3.0\lib\netstandard1.3\System.Security.Claims.dll +system.security.claims\4.3.0\lib\xamarinios10\_._ +system.security.claims\4.3.0\lib\xamarinmac20\_._ +system.security.claims\4.3.0\lib\xamarintvos10\_._ +system.security.claims\4.3.0\lib\xamarinwatchos10\_._ +system.security.claims\4.3.0\ref\MonoAndroid10\_._ +system.security.claims\4.3.0\ref\MonoTouch10\_._ +system.security.claims\4.3.0\ref\net46\System.Security.Claims.dll +system.security.claims\4.3.0\ref\netstandard1.3\System.Security.Claims.dll +system.security.claims\4.3.0\ref\xamarinios10\_._ +system.security.claims\4.3.0\ref\xamarinmac20\_._ +system.security.claims\4.3.0\ref\xamarintvos10\_._ +system.security.claims\4.3.0\ref\xamarinwatchos10\_._ +system.security.claims\4.3.0\system.security.claims.4.3.0.nupkg.sha512 +system.security.claims\4.3.0\system.security.claims.nuspec +system.security.claims\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.algorithms\4.2.0\dotnet_library_license.txt +system.security.cryptography.algorithms\4.2.0\lib\MonoAndroid10\_._ +system.security.cryptography.algorithms\4.2.0\lib\MonoTouch10\_._ +system.security.cryptography.algorithms\4.2.0\lib\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\lib\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\lib\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\lib\xamarinios10\_._ +system.security.cryptography.algorithms\4.2.0\lib\xamarinmac20\_._ +system.security.cryptography.algorithms\4.2.0\lib\xamarintvos10\_._ +system.security.cryptography.algorithms\4.2.0\lib\xamarinwatchos10\_._ +system.security.cryptography.algorithms\4.2.0\ref\MonoAndroid10\_._ +system.security.cryptography.algorithms\4.2.0\ref\MonoTouch10\_._ +system.security.cryptography.algorithms\4.2.0\ref\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\netstandard1.3\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\netstandard1.4\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\ref\xamarinios10\_._ +system.security.cryptography.algorithms\4.2.0\ref\xamarinmac20\_._ +system.security.cryptography.algorithms\4.2.0\ref\xamarintvos10\_._ +system.security.cryptography.algorithms\4.2.0\ref\xamarinwatchos10\_._ +system.security.cryptography.algorithms\4.2.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\netcore50\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.2.0\system.security.cryptography.algorithms.4.2.0.nupkg.sha512 +system.security.cryptography.algorithms\4.2.0\system.security.cryptography.algorithms.nuspec +system.security.cryptography.algorithms\4.2.0\ThirdPartyNotices.txt +system.security.cryptography.algorithms\4.3.0\dotnet_library_license.txt +system.security.cryptography.algorithms\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.algorithms\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.algorithms\4.3.0\lib\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.algorithms\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.algorithms\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.algorithms\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.algorithms\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.algorithms\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.algorithms\4.3.0\ref\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\netstandard1.4\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.algorithms\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.algorithms\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.algorithms\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.algorithms\4.3.0\runtimes\osx\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\net461\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\net463\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\netcore50\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Algorithms.dll +system.security.cryptography.algorithms\4.3.0\system.security.cryptography.algorithms.4.3.0.nupkg.sha512 +system.security.cryptography.algorithms\4.3.0\system.security.cryptography.algorithms.nuspec +system.security.cryptography.algorithms\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.cng\4.2.0\dotnet_library_license.txt +system.security.cryptography.cng\4.2.0\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\lib\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\netstandard1.3\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\ref\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.2.0\system.security.cryptography.cng.4.2.0.nupkg.sha512 +system.security.cryptography.cng\4.2.0\system.security.cryptography.cng.nuspec +system.security.cryptography.cng\4.2.0\ThirdPartyNotices.txt +system.security.cryptography.cng\4.3.0\dotnet_library_license.txt +system.security.cryptography.cng\4.3.0\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\lib\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\ref\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\net463\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.3.0\system.security.cryptography.cng.4.3.0.nupkg.sha512 +system.security.cryptography.cng\4.3.0\system.security.cryptography.cng.nuspec +system.security.cryptography.cng\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.cng\4.5.0\.signature.p7s +system.security.cryptography.cng\4.5.0\lib\MonoAndroid10\_._ +system.security.cryptography.cng\4.5.0\lib\MonoTouch10\_._ +system.security.cryptography.cng\4.5.0\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\net462\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\net47\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netcoreapp2.1\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netstandard1.3\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\netstandard2.0\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\lib\uap10.0.16299\_._ +system.security.cryptography.cng\4.5.0\lib\xamarinios10\_._ +system.security.cryptography.cng\4.5.0\lib\xamarinmac20\_._ +system.security.cryptography.cng\4.5.0\lib\xamarintvos10\_._ +system.security.cryptography.cng\4.5.0\lib\xamarinwatchos10\_._ +system.security.cryptography.cng\4.5.0\LICENSE.TXT +system.security.cryptography.cng\4.5.0\ref\MonoAndroid10\_._ +system.security.cryptography.cng\4.5.0\ref\MonoTouch10\_._ +system.security.cryptography.cng\4.5.0\ref\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\net462\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\net47\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netcoreapp2.0\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netcoreapp2.1\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netstandard1.3\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\netstandard2.0\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\ref\uap10.0.16299\_._ +system.security.cryptography.cng\4.5.0\ref\xamarinios10\_._ +system.security.cryptography.cng\4.5.0\ref\xamarinmac20\_._ +system.security.cryptography.cng\4.5.0\ref\xamarintvos10\_._ +system.security.cryptography.cng\4.5.0\ref\xamarinwatchos10\_._ +system.security.cryptography.cng\4.5.0\runtimes\win\lib\net46\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\net461\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\net462\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\net47\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\netcoreapp2.1\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\netstandard1.4\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.Cng.dll +system.security.cryptography.cng\4.5.0\runtimes\win\lib\uap10.0.16299\_._ +system.security.cryptography.cng\4.5.0\system.security.cryptography.cng.4.5.0.nupkg.sha512 +system.security.cryptography.cng\4.5.0\system.security.cryptography.cng.nuspec +system.security.cryptography.cng\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.cryptography.cng\4.5.0\useSharedDesignerContext.txt +system.security.cryptography.cng\4.5.0\version.txt +system.security.cryptography.csp\4.0.0\dotnet_library_license.txt +system.security.cryptography.csp\4.0.0\lib\MonoAndroid10\_._ +system.security.cryptography.csp\4.0.0\lib\MonoTouch10\_._ +system.security.cryptography.csp\4.0.0\lib\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\lib\xamarinios10\_._ +system.security.cryptography.csp\4.0.0\lib\xamarinmac20\_._ +system.security.cryptography.csp\4.0.0\lib\xamarintvos10\_._ +system.security.cryptography.csp\4.0.0\lib\xamarinwatchos10\_._ +system.security.cryptography.csp\4.0.0\ref\MonoAndroid10\_._ +system.security.cryptography.csp\4.0.0\ref\MonoTouch10\_._ +system.security.cryptography.csp\4.0.0\ref\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\ref\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\ref\xamarinios10\_._ +system.security.cryptography.csp\4.0.0\ref\xamarinmac20\_._ +system.security.cryptography.csp\4.0.0\ref\xamarintvos10\_._ +system.security.cryptography.csp\4.0.0\ref\xamarinwatchos10\_._ +system.security.cryptography.csp\4.0.0\runtimes\unix\lib\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\runtimes\win\lib\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\runtimes\win\lib\netcore50\_._ +system.security.cryptography.csp\4.0.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.0.0\system.security.cryptography.csp.4.0.0.nupkg.sha512 +system.security.cryptography.csp\4.0.0\system.security.cryptography.csp.nuspec +system.security.cryptography.csp\4.0.0\ThirdPartyNotices.txt +system.security.cryptography.csp\4.3.0\dotnet_library_license.txt +system.security.cryptography.csp\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.csp\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.csp\4.3.0\lib\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.csp\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.csp\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.csp\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.csp\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.csp\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.csp\4.3.0\ref\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.csp\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.csp\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.csp\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.csp\4.3.0\runtimes\unix\lib\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\runtimes\win\lib\netcore50\_._ +system.security.cryptography.csp\4.3.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Csp.dll +system.security.cryptography.csp\4.3.0\system.security.cryptography.csp.4.3.0.nupkg.sha512 +system.security.cryptography.csp\4.3.0\system.security.cryptography.csp.nuspec +system.security.cryptography.csp\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.encoding\4.0.0\dotnet_library_license.txt +system.security.cryptography.encoding\4.0.0\lib\MonoAndroid10\_._ +system.security.cryptography.encoding\4.0.0\lib\MonoTouch10\_._ +system.security.cryptography.encoding\4.0.0\lib\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\lib\xamarinios10\_._ +system.security.cryptography.encoding\4.0.0\lib\xamarinmac20\_._ +system.security.cryptography.encoding\4.0.0\lib\xamarintvos10\_._ +system.security.cryptography.encoding\4.0.0\lib\xamarinwatchos10\_._ +system.security.cryptography.encoding\4.0.0\ref\MonoAndroid10\_._ +system.security.cryptography.encoding\4.0.0\ref\MonoTouch10\_._ +system.security.cryptography.encoding\4.0.0\ref\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\ref\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\ref\xamarinios10\_._ +system.security.cryptography.encoding\4.0.0\ref\xamarinmac20\_._ +system.security.cryptography.encoding\4.0.0\ref\xamarintvos10\_._ +system.security.cryptography.encoding\4.0.0\ref\xamarinwatchos10\_._ +system.security.cryptography.encoding\4.0.0\runtimes\unix\lib\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\runtimes\win\lib\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.0.0\system.security.cryptography.encoding.4.0.0.nupkg.sha512 +system.security.cryptography.encoding\4.0.0\system.security.cryptography.encoding.nuspec +system.security.cryptography.encoding\4.0.0\ThirdPartyNotices.txt +system.security.cryptography.encoding\4.3.0\dotnet_library_license.txt +system.security.cryptography.encoding\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.encoding\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.encoding\4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.encoding\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.encoding\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.encoding\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.encoding\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.encoding\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.encoding\4.3.0\ref\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.encoding\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.encoding\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.encoding\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.encoding\4.3.0\runtimes\unix\lib\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Encoding.dll +system.security.cryptography.encoding\4.3.0\system.security.cryptography.encoding.4.3.0.nupkg.sha512 +system.security.cryptography.encoding\4.3.0\system.security.cryptography.encoding.nuspec +system.security.cryptography.encoding\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.openssl\4.0.0\dotnet_library_license.txt +system.security.cryptography.openssl\4.0.0\lib\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.0.0\ref\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.0.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.0.0\system.security.cryptography.openssl.4.0.0.nupkg.sha512 +system.security.cryptography.openssl\4.0.0\system.security.cryptography.openssl.nuspec +system.security.cryptography.openssl\4.0.0\ThirdPartyNotices.txt +system.security.cryptography.openssl\4.3.0\dotnet_library_license.txt +system.security.cryptography.openssl\4.3.0\lib\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.3.0\ref\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.3.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.OpenSsl.dll +system.security.cryptography.openssl\4.3.0\system.security.cryptography.openssl.4.3.0.nupkg.sha512 +system.security.cryptography.openssl\4.3.0\system.security.cryptography.openssl.nuspec +system.security.cryptography.openssl\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.pkcs\4.5.0\.signature.p7s +system.security.cryptography.pkcs\4.5.0\lib\net46\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\lib\net461\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\lib\netcoreapp2.1\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\lib\netstandard1.3\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\lib\netstandard2.0\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\LICENSE.TXT +system.security.cryptography.pkcs\4.5.0\ref\net46\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\ref\net461\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\ref\netcoreapp2.1\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\ref\netstandard1.3\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\ref\netstandard2.0\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\net46\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\net461\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\netcoreapp2.1\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\netstandard1.3\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\runtimes\win\lib\netstandard2.0\System.Security.Cryptography.Pkcs.dll +system.security.cryptography.pkcs\4.5.0\system.security.cryptography.pkcs.4.5.0.nupkg.sha512 +system.security.cryptography.pkcs\4.5.0\system.security.cryptography.pkcs.nuspec +system.security.cryptography.pkcs\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.cryptography.pkcs\4.5.0\useSharedDesignerContext.txt +system.security.cryptography.pkcs\4.5.0\version.txt +system.security.cryptography.primitives\4.0.0\dotnet_library_license.txt +system.security.cryptography.primitives\4.0.0\lib\MonoAndroid10\_._ +system.security.cryptography.primitives\4.0.0\lib\MonoTouch10\_._ +system.security.cryptography.primitives\4.0.0\lib\net46\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.0.0\lib\netstandard1.3\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.0.0\lib\xamarinios10\_._ +system.security.cryptography.primitives\4.0.0\lib\xamarinmac20\_._ +system.security.cryptography.primitives\4.0.0\lib\xamarintvos10\_._ +system.security.cryptography.primitives\4.0.0\lib\xamarinwatchos10\_._ +system.security.cryptography.primitives\4.0.0\ref\MonoAndroid10\_._ +system.security.cryptography.primitives\4.0.0\ref\MonoTouch10\_._ +system.security.cryptography.primitives\4.0.0\ref\net46\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.0.0\ref\netstandard1.3\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.0.0\ref\xamarinios10\_._ +system.security.cryptography.primitives\4.0.0\ref\xamarinmac20\_._ +system.security.cryptography.primitives\4.0.0\ref\xamarintvos10\_._ +system.security.cryptography.primitives\4.0.0\ref\xamarinwatchos10\_._ +system.security.cryptography.primitives\4.0.0\system.security.cryptography.primitives.4.0.0.nupkg.sha512 +system.security.cryptography.primitives\4.0.0\system.security.cryptography.primitives.nuspec +system.security.cryptography.primitives\4.0.0\ThirdPartyNotices.txt +system.security.cryptography.primitives\4.3.0\dotnet_library_license.txt +system.security.cryptography.primitives\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.primitives\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.primitives\4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.3.0\lib\netstandard1.3\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.primitives\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.primitives\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.primitives\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.primitives\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.primitives\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.primitives\4.3.0\ref\net46\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Primitives.dll +system.security.cryptography.primitives\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.primitives\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.primitives\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.primitives\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.primitives\4.3.0\system.security.cryptography.primitives.4.3.0.nupkg.sha512 +system.security.cryptography.primitives\4.3.0\system.security.cryptography.primitives.nuspec +system.security.cryptography.primitives\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.x509certificates\4.1.0\dotnet_library_license.txt +system.security.cryptography.x509certificates\4.1.0\lib\MonoAndroid10\_._ +system.security.cryptography.x509certificates\4.1.0\lib\MonoTouch10\_._ +system.security.cryptography.x509certificates\4.1.0\lib\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\lib\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\lib\xamarinios10\_._ +system.security.cryptography.x509certificates\4.1.0\lib\xamarinmac20\_._ +system.security.cryptography.x509certificates\4.1.0\lib\xamarintvos10\_._ +system.security.cryptography.x509certificates\4.1.0\lib\xamarinwatchos10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\MonoAndroid10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\MonoTouch10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\ref\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\ref\netstandard1.3\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\ref\netstandard1.4\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\ref\xamarinios10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\xamarinmac20\_._ +system.security.cryptography.x509certificates\4.1.0\ref\xamarintvos10\_._ +system.security.cryptography.x509certificates\4.1.0\ref\xamarinwatchos10\_._ +system.security.cryptography.x509certificates\4.1.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\runtimes\win\lib\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\runtimes\win\lib\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\runtimes\win\lib\netcore50\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.1.0\system.security.cryptography.x509certificates.4.1.0.nupkg.sha512 +system.security.cryptography.x509certificates\4.1.0\system.security.cryptography.x509certificates.nuspec +system.security.cryptography.x509certificates\4.1.0\ThirdPartyNotices.txt +system.security.cryptography.x509certificates\4.3.0\dotnet_library_license.txt +system.security.cryptography.x509certificates\4.3.0\lib\MonoAndroid10\_._ +system.security.cryptography.x509certificates\4.3.0\lib\MonoTouch10\_._ +system.security.cryptography.x509certificates\4.3.0\lib\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\lib\xamarinios10\_._ +system.security.cryptography.x509certificates\4.3.0\lib\xamarinmac20\_._ +system.security.cryptography.x509certificates\4.3.0\lib\xamarintvos10\_._ +system.security.cryptography.x509certificates\4.3.0\lib\xamarinwatchos10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\MonoAndroid10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\MonoTouch10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\ref\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\ref\netstandard1.3\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\ref\netstandard1.4\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\ref\xamarinios10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\xamarinmac20\_._ +system.security.cryptography.x509certificates\4.3.0\ref\xamarintvos10\_._ +system.security.cryptography.x509certificates\4.3.0\ref\xamarinwatchos10\_._ +system.security.cryptography.x509certificates\4.3.0\runtimes\unix\lib\netstandard1.6\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\runtimes\win\lib\net46\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\runtimes\win\lib\net461\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\runtimes\win\lib\netcore50\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\runtimes\win\lib\netstandard1.6\System.Security.Cryptography.X509Certificates.dll +system.security.cryptography.x509certificates\4.3.0\system.security.cryptography.x509certificates.4.3.0.nupkg.sha512 +system.security.cryptography.x509certificates\4.3.0\system.security.cryptography.x509certificates.nuspec +system.security.cryptography.x509certificates\4.3.0\ThirdPartyNotices.txt +system.security.cryptography.xml\4.5.0\.signature.p7s +system.security.cryptography.xml\4.5.0\lib\net461\System.Security.Cryptography.Xml.dll +system.security.cryptography.xml\4.5.0\lib\netstandard2.0\System.Security.Cryptography.Xml.dll +system.security.cryptography.xml\4.5.0\LICENSE.TXT +system.security.cryptography.xml\4.5.0\ref\net461\System.Security.Cryptography.Xml.dll +system.security.cryptography.xml\4.5.0\ref\netstandard2.0\System.Security.Cryptography.Xml.dll +system.security.cryptography.xml\4.5.0\system.security.cryptography.xml.4.5.0.nupkg.sha512 +system.security.cryptography.xml\4.5.0\system.security.cryptography.xml.nuspec +system.security.cryptography.xml\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.cryptography.xml\4.5.0\useSharedDesignerContext.txt +system.security.cryptography.xml\4.5.0\version.txt +system.security.permissions\4.5.0\.signature.p7s +system.security.permissions\4.5.0\lib\net461\System.Security.Permissions.dll +system.security.permissions\4.5.0\lib\netstandard2.0\System.Security.Permissions.dll +system.security.permissions\4.5.0\LICENSE.TXT +system.security.permissions\4.5.0\ref\net461\System.Security.Permissions.dll +system.security.permissions\4.5.0\ref\netstandard2.0\System.Security.Permissions.dll +system.security.permissions\4.5.0\system.security.permissions.4.5.0.nupkg.sha512 +system.security.permissions\4.5.0\system.security.permissions.nuspec +system.security.permissions\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.permissions\4.5.0\useSharedDesignerContext.txt +system.security.permissions\4.5.0\version.txt +system.security.principal.windows\4.3.0\dotnet_library_license.txt +system.security.principal.windows\4.3.0\lib\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\ref\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\ref\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\runtimes\unix\lib\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\runtimes\win\lib\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\runtimes\win\lib\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.3.0\system.security.principal.windows.4.3.0.nupkg.sha512 +system.security.principal.windows\4.3.0\system.security.principal.windows.nuspec +system.security.principal.windows\4.3.0\ThirdPartyNotices.txt +system.security.principal.windows\4.5.0\.signature.p7s +system.security.principal.windows\4.5.0\lib\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\lib\net461\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\lib\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\lib\netstandard2.0\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\lib\uap10.0.16299\_._ +system.security.principal.windows\4.5.0\LICENSE.TXT +system.security.principal.windows\4.5.0\ref\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\ref\net461\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\ref\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\ref\netstandard2.0\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\ref\uap10.0.16299\_._ +system.security.principal.windows\4.5.0\runtimes\unix\lib\netcoreapp2.0\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\net46\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\net461\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\netstandard1.3\System.Security.Principal.Windows.dll +system.security.principal.windows\4.5.0\runtimes\win\lib\uap10.0.16299\_._ +system.security.principal.windows\4.5.0\system.security.principal.windows.4.5.0.nupkg.sha512 +system.security.principal.windows\4.5.0\system.security.principal.windows.nuspec +system.security.principal.windows\4.5.0\THIRD-PARTY-NOTICES.TXT +system.security.principal.windows\4.5.0\useSharedDesignerContext.txt +system.security.principal.windows\4.5.0\version.txt +system.security.principal\4.3.0\dotnet_library_license.txt +system.security.principal\4.3.0\lib\MonoAndroid10\_._ +system.security.principal\4.3.0\lib\MonoTouch10\_._ +system.security.principal\4.3.0\lib\net45\_._ +system.security.principal\4.3.0\lib\netcore50\System.Security.Principal.dll +system.security.principal\4.3.0\lib\netstandard1.0\System.Security.Principal.dll +system.security.principal\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.security.principal\4.3.0\lib\win8\_._ +system.security.principal\4.3.0\lib\wp80\_._ +system.security.principal\4.3.0\lib\wpa81\_._ +system.security.principal\4.3.0\lib\xamarinios10\_._ +system.security.principal\4.3.0\lib\xamarinmac20\_._ +system.security.principal\4.3.0\lib\xamarintvos10\_._ +system.security.principal\4.3.0\lib\xamarinwatchos10\_._ +system.security.principal\4.3.0\ref\MonoAndroid10\_._ +system.security.principal\4.3.0\ref\MonoTouch10\_._ +system.security.principal\4.3.0\ref\net45\_._ +system.security.principal\4.3.0\ref\netcore50\System.Security.Principal.dll +system.security.principal\4.3.0\ref\netstandard1.0\System.Security.Principal.dll +system.security.principal\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.security.principal\4.3.0\ref\win8\_._ +system.security.principal\4.3.0\ref\wp80\_._ +system.security.principal\4.3.0\ref\wpa81\_._ +system.security.principal\4.3.0\ref\xamarinios10\_._ +system.security.principal\4.3.0\ref\xamarinmac20\_._ +system.security.principal\4.3.0\ref\xamarintvos10\_._ +system.security.principal\4.3.0\ref\xamarinwatchos10\_._ +system.security.principal\4.3.0\system.security.principal.4.3.0.nupkg.sha512 +system.security.principal\4.3.0\system.security.principal.nuspec +system.security.principal\4.3.0\ThirdPartyNotices.txt +system.spatial\5.8.2\lib\net40\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\System.Spatial.dll +system.spatial\5.8.2\lib\net40\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\net40\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\System.Spatial.dll +system.spatial\5.8.2\lib\netstandard1.1\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\netstandard1.1\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\System.Spatial.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net40+sl5+wp8+win8+wpa\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\System.Spatial.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\portable-net45+wp8+win8+wpa\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\de\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\es\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\fr\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\it\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\ja\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\ko\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\ru\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\System.Spatial.dll +system.spatial\5.8.2\lib\sl4\zh-Hans\System.Spatial.resources.dll +system.spatial\5.8.2\lib\sl4\zh-Hant\System.Spatial.resources.dll +system.spatial\5.8.2\system.spatial.5.8.2.nupkg.sha512 +system.spatial\5.8.2\system.spatial.nuspec +system.text.encoding.codepages\4.3.0\dotnet_library_license.txt +system.text.encoding.codepages\4.3.0\lib\MonoAndroid10\_._ +system.text.encoding.codepages\4.3.0\lib\MonoTouch10\_._ +system.text.encoding.codepages\4.3.0\lib\net46\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.3.0\lib\xamarinios10\_._ +system.text.encoding.codepages\4.3.0\lib\xamarinmac20\_._ +system.text.encoding.codepages\4.3.0\lib\xamarintvos10\_._ +system.text.encoding.codepages\4.3.0\lib\xamarinwatchos10\_._ +system.text.encoding.codepages\4.3.0\ref\MonoAndroid10\_._ +system.text.encoding.codepages\4.3.0\ref\MonoTouch10\_._ +system.text.encoding.codepages\4.3.0\ref\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.3.0\ref\xamarinios10\_._ +system.text.encoding.codepages\4.3.0\ref\xamarinmac20\_._ +system.text.encoding.codepages\4.3.0\ref\xamarintvos10\_._ +system.text.encoding.codepages\4.3.0\ref\xamarinwatchos10\_._ +system.text.encoding.codepages\4.3.0\runtimes\unix\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.3.0\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.3.0\system.text.encoding.codepages.4.3.0.nupkg.sha512 +system.text.encoding.codepages\4.3.0\system.text.encoding.codepages.nuspec +system.text.encoding.codepages\4.3.0\ThirdPartyNotices.txt +system.text.encoding.codepages\4.5.0\.signature.p7s +system.text.encoding.codepages\4.5.0\lib\MonoAndroid10\_._ +system.text.encoding.codepages\4.5.0\lib\MonoTouch10\_._ +system.text.encoding.codepages\4.5.0\lib\net46\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\lib\net461\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\lib\netstandard2.0\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\lib\xamarinios10\_._ +system.text.encoding.codepages\4.5.0\lib\xamarinmac20\_._ +system.text.encoding.codepages\4.5.0\lib\xamarintvos10\_._ +system.text.encoding.codepages\4.5.0\lib\xamarinwatchos10\_._ +system.text.encoding.codepages\4.5.0\LICENSE.TXT +system.text.encoding.codepages\4.5.0\ref\MonoAndroid10\_._ +system.text.encoding.codepages\4.5.0\ref\MonoTouch10\_._ +system.text.encoding.codepages\4.5.0\ref\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\ref\netstandard2.0\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\ref\xamarinios10\_._ +system.text.encoding.codepages\4.5.0\ref\xamarinmac20\_._ +system.text.encoding.codepages\4.5.0\ref\xamarintvos10\_._ +system.text.encoding.codepages\4.5.0\ref\xamarinwatchos10\_._ +system.text.encoding.codepages\4.5.0\runtimes\win\lib\net461\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\runtimes\win\lib\netstandard2.0\System.Text.Encoding.CodePages.dll +system.text.encoding.codepages\4.5.0\system.text.encoding.codepages.4.5.0.nupkg.sha512 +system.text.encoding.codepages\4.5.0\system.text.encoding.codepages.nuspec +system.text.encoding.codepages\4.5.0\THIRD-PARTY-NOTICES.TXT +system.text.encoding.codepages\4.5.0\useSharedDesignerContext.txt +system.text.encoding.codepages\4.5.0\version.txt +system.text.encoding.extensions\4.0.11\dotnet_library_license.txt +system.text.encoding.extensions\4.0.11\lib\MonoAndroid10\_._ +system.text.encoding.extensions\4.0.11\lib\MonoTouch10\_._ +system.text.encoding.extensions\4.0.11\lib\net45\_._ +system.text.encoding.extensions\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding.extensions\4.0.11\lib\win8\_._ +system.text.encoding.extensions\4.0.11\lib\wp80\_._ +system.text.encoding.extensions\4.0.11\lib\wpa81\_._ +system.text.encoding.extensions\4.0.11\lib\xamarinios10\_._ +system.text.encoding.extensions\4.0.11\lib\xamarinmac20\_._ +system.text.encoding.extensions\4.0.11\lib\xamarintvos10\_._ +system.text.encoding.extensions\4.0.11\lib\xamarinwatchos10\_._ +system.text.encoding.extensions\4.0.11\ref\MonoAndroid10\_._ +system.text.encoding.extensions\4.0.11\ref\MonoTouch10\_._ +system.text.encoding.extensions\4.0.11\ref\net45\_._ +system.text.encoding.extensions\4.0.11\ref\netcore50\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.0.11\ref\netstandard1.0\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.0.11\ref\netstandard1.3\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding.extensions\4.0.11\ref\win8\_._ +system.text.encoding.extensions\4.0.11\ref\wp80\_._ +system.text.encoding.extensions\4.0.11\ref\wpa81\_._ +system.text.encoding.extensions\4.0.11\ref\xamarinios10\_._ +system.text.encoding.extensions\4.0.11\ref\xamarinmac20\_._ +system.text.encoding.extensions\4.0.11\ref\xamarintvos10\_._ +system.text.encoding.extensions\4.0.11\ref\xamarinwatchos10\_._ +system.text.encoding.extensions\4.0.11\system.text.encoding.extensions.4.0.11.nupkg.sha512 +system.text.encoding.extensions\4.0.11\system.text.encoding.extensions.nuspec +system.text.encoding.extensions\4.0.11\ThirdPartyNotices.txt +system.text.encoding.extensions\4.3.0\dotnet_library_license.txt +system.text.encoding.extensions\4.3.0\lib\MonoAndroid10\_._ +system.text.encoding.extensions\4.3.0\lib\MonoTouch10\_._ +system.text.encoding.extensions\4.3.0\lib\net45\_._ +system.text.encoding.extensions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding.extensions\4.3.0\lib\win8\_._ +system.text.encoding.extensions\4.3.0\lib\wp80\_._ +system.text.encoding.extensions\4.3.0\lib\wpa81\_._ +system.text.encoding.extensions\4.3.0\lib\xamarinios10\_._ +system.text.encoding.extensions\4.3.0\lib\xamarinmac20\_._ +system.text.encoding.extensions\4.3.0\lib\xamarintvos10\_._ +system.text.encoding.extensions\4.3.0\lib\xamarinwatchos10\_._ +system.text.encoding.extensions\4.3.0\ref\MonoAndroid10\_._ +system.text.encoding.extensions\4.3.0\ref\MonoTouch10\_._ +system.text.encoding.extensions\4.3.0\ref\net45\_._ +system.text.encoding.extensions\4.3.0\ref\netcore50\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.3.0\ref\netstandard1.0\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.3.0\ref\netstandard1.3\System.Text.Encoding.Extensions.dll +system.text.encoding.extensions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding.extensions\4.3.0\ref\win8\_._ +system.text.encoding.extensions\4.3.0\ref\wp80\_._ +system.text.encoding.extensions\4.3.0\ref\wpa81\_._ +system.text.encoding.extensions\4.3.0\ref\xamarinios10\_._ +system.text.encoding.extensions\4.3.0\ref\xamarinmac20\_._ +system.text.encoding.extensions\4.3.0\ref\xamarintvos10\_._ +system.text.encoding.extensions\4.3.0\ref\xamarinwatchos10\_._ +system.text.encoding.extensions\4.3.0\system.text.encoding.extensions.4.3.0.nupkg.sha512 +system.text.encoding.extensions\4.3.0\system.text.encoding.extensions.nuspec +system.text.encoding.extensions\4.3.0\ThirdPartyNotices.txt +system.text.encoding\4.0.11\dotnet_library_license.txt +system.text.encoding\4.0.11\lib\MonoAndroid10\_._ +system.text.encoding\4.0.11\lib\MonoTouch10\_._ +system.text.encoding\4.0.11\lib\net45\_._ +system.text.encoding\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding\4.0.11\lib\win8\_._ +system.text.encoding\4.0.11\lib\wp80\_._ +system.text.encoding\4.0.11\lib\wpa81\_._ +system.text.encoding\4.0.11\lib\xamarinios10\_._ +system.text.encoding\4.0.11\lib\xamarinmac20\_._ +system.text.encoding\4.0.11\lib\xamarintvos10\_._ +system.text.encoding\4.0.11\lib\xamarinwatchos10\_._ +system.text.encoding\4.0.11\ref\MonoAndroid10\_._ +system.text.encoding\4.0.11\ref\MonoTouch10\_._ +system.text.encoding\4.0.11\ref\net45\_._ +system.text.encoding\4.0.11\ref\netcore50\System.Text.Encoding.dll +system.text.encoding\4.0.11\ref\netstandard1.0\System.Text.Encoding.dll +system.text.encoding\4.0.11\ref\netstandard1.3\System.Text.Encoding.dll +system.text.encoding\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding\4.0.11\ref\win8\_._ +system.text.encoding\4.0.11\ref\wp80\_._ +system.text.encoding\4.0.11\ref\wpa81\_._ +system.text.encoding\4.0.11\ref\xamarinios10\_._ +system.text.encoding\4.0.11\ref\xamarinmac20\_._ +system.text.encoding\4.0.11\ref\xamarintvos10\_._ +system.text.encoding\4.0.11\ref\xamarinwatchos10\_._ +system.text.encoding\4.0.11\system.text.encoding.4.0.11.nupkg.sha512 +system.text.encoding\4.0.11\system.text.encoding.nuspec +system.text.encoding\4.0.11\ThirdPartyNotices.txt +system.text.encoding\4.3.0\dotnet_library_license.txt +system.text.encoding\4.3.0\lib\MonoAndroid10\_._ +system.text.encoding\4.3.0\lib\MonoTouch10\_._ +system.text.encoding\4.3.0\lib\net45\_._ +system.text.encoding\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding\4.3.0\lib\win8\_._ +system.text.encoding\4.3.0\lib\wp80\_._ +system.text.encoding\4.3.0\lib\wpa81\_._ +system.text.encoding\4.3.0\lib\xamarinios10\_._ +system.text.encoding\4.3.0\lib\xamarinmac20\_._ +system.text.encoding\4.3.0\lib\xamarintvos10\_._ +system.text.encoding\4.3.0\lib\xamarinwatchos10\_._ +system.text.encoding\4.3.0\ref\MonoAndroid10\_._ +system.text.encoding\4.3.0\ref\MonoTouch10\_._ +system.text.encoding\4.3.0\ref\net45\_._ +system.text.encoding\4.3.0\ref\netcore50\System.Text.Encoding.dll +system.text.encoding\4.3.0\ref\netstandard1.0\System.Text.Encoding.dll +system.text.encoding\4.3.0\ref\netstandard1.3\System.Text.Encoding.dll +system.text.encoding\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.encoding\4.3.0\ref\win8\_._ +system.text.encoding\4.3.0\ref\wp80\_._ +system.text.encoding\4.3.0\ref\wpa81\_._ +system.text.encoding\4.3.0\ref\xamarinios10\_._ +system.text.encoding\4.3.0\ref\xamarinmac20\_._ +system.text.encoding\4.3.0\ref\xamarintvos10\_._ +system.text.encoding\4.3.0\ref\xamarinwatchos10\_._ +system.text.encoding\4.3.0\system.text.encoding.4.3.0.nupkg.sha512 +system.text.encoding\4.3.0\system.text.encoding.nuspec +system.text.encoding\4.3.0\ThirdPartyNotices.txt +system.text.encodings.web\4.3.1\dotnet_library_license.txt +system.text.encodings.web\4.3.1\lib\netstandard1.0\System.Text.Encodings.Web.dll +system.text.encodings.web\4.3.1\system.text.encodings.web.4.3.1.nupkg.sha512 +system.text.encodings.web\4.3.1\system.text.encodings.web.nuspec +system.text.encodings.web\4.3.1\ThirdPartyNotices.txt +system.text.encodings.web\4.5.0\.signature.p7s +system.text.encodings.web\4.5.0\lib\netstandard1.0\System.Text.Encodings.Web.dll +system.text.encodings.web\4.5.0\lib\netstandard2.0\System.Text.Encodings.Web.dll +system.text.encodings.web\4.5.0\LICENSE.TXT +system.text.encodings.web\4.5.0\system.text.encodings.web.4.5.0.nupkg.sha512 +system.text.encodings.web\4.5.0\system.text.encodings.web.nuspec +system.text.encodings.web\4.5.0\THIRD-PARTY-NOTICES.TXT +system.text.encodings.web\4.5.0\useSharedDesignerContext.txt +system.text.encodings.web\4.5.0\version.txt +system.text.regularexpressions\4.1.0\dotnet_library_license.txt +system.text.regularexpressions\4.1.0\lib\MonoAndroid10\_._ +system.text.regularexpressions\4.1.0\lib\MonoTouch10\_._ +system.text.regularexpressions\4.1.0\lib\net45\_._ +system.text.regularexpressions\4.1.0\lib\net463\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\lib\netcore50\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\lib\netstandard1.6\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.regularexpressions\4.1.0\lib\win8\_._ +system.text.regularexpressions\4.1.0\lib\wp80\_._ +system.text.regularexpressions\4.1.0\lib\wpa81\_._ +system.text.regularexpressions\4.1.0\lib\xamarinios10\_._ +system.text.regularexpressions\4.1.0\lib\xamarinmac20\_._ +system.text.regularexpressions\4.1.0\lib\xamarintvos10\_._ +system.text.regularexpressions\4.1.0\lib\xamarinwatchos10\_._ +system.text.regularexpressions\4.1.0\ref\MonoAndroid10\_._ +system.text.regularexpressions\4.1.0\ref\MonoTouch10\_._ +system.text.regularexpressions\4.1.0\ref\net45\_._ +system.text.regularexpressions\4.1.0\ref\net463\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\netcore50\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\netstandard1.0\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\netstandard1.3\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\netstandard1.6\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.1.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.regularexpressions\4.1.0\ref\win8\_._ +system.text.regularexpressions\4.1.0\ref\wp80\_._ +system.text.regularexpressions\4.1.0\ref\wpa81\_._ +system.text.regularexpressions\4.1.0\ref\xamarinios10\_._ +system.text.regularexpressions\4.1.0\ref\xamarinmac20\_._ +system.text.regularexpressions\4.1.0\ref\xamarintvos10\_._ +system.text.regularexpressions\4.1.0\ref\xamarinwatchos10\_._ +system.text.regularexpressions\4.1.0\system.text.regularexpressions.4.1.0.nupkg.sha512 +system.text.regularexpressions\4.1.0\system.text.regularexpressions.nuspec +system.text.regularexpressions\4.1.0\ThirdPartyNotices.txt +system.text.regularexpressions\4.3.0\dotnet_library_license.txt +system.text.regularexpressions\4.3.0\lib\MonoAndroid10\_._ +system.text.regularexpressions\4.3.0\lib\MonoTouch10\_._ +system.text.regularexpressions\4.3.0\lib\net45\_._ +system.text.regularexpressions\4.3.0\lib\net463\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\lib\netcore50\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\lib\netstandard1.6\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.text.regularexpressions\4.3.0\lib\win8\_._ +system.text.regularexpressions\4.3.0\lib\wp80\_._ +system.text.regularexpressions\4.3.0\lib\wpa81\_._ +system.text.regularexpressions\4.3.0\lib\xamarinios10\_._ +system.text.regularexpressions\4.3.0\lib\xamarinmac20\_._ +system.text.regularexpressions\4.3.0\lib\xamarintvos10\_._ +system.text.regularexpressions\4.3.0\lib\xamarinwatchos10\_._ +system.text.regularexpressions\4.3.0\ref\MonoAndroid10\_._ +system.text.regularexpressions\4.3.0\ref\MonoTouch10\_._ +system.text.regularexpressions\4.3.0\ref\net45\_._ +system.text.regularexpressions\4.3.0\ref\net463\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netcore50\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netcoreapp1.1\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netstandard1.0\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netstandard1.3\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\netstandard1.6\System.Text.RegularExpressions.dll +system.text.regularexpressions\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.text.regularexpressions\4.3.0\ref\win8\_._ +system.text.regularexpressions\4.3.0\ref\wp80\_._ +system.text.regularexpressions\4.3.0\ref\wpa81\_._ +system.text.regularexpressions\4.3.0\ref\xamarinios10\_._ +system.text.regularexpressions\4.3.0\ref\xamarinmac20\_._ +system.text.regularexpressions\4.3.0\ref\xamarintvos10\_._ +system.text.regularexpressions\4.3.0\ref\xamarinwatchos10\_._ +system.text.regularexpressions\4.3.0\system.text.regularexpressions.4.3.0.nupkg.sha512 +system.text.regularexpressions\4.3.0\system.text.regularexpressions.nuspec +system.text.regularexpressions\4.3.0\ThirdPartyNotices.txt +system.threading.channels\4.5.0\.signature.p7s +system.threading.channels\4.5.0\lib\netcoreapp2.1\System.Threading.Channels.dll +system.threading.channels\4.5.0\lib\netstandard1.3\System.Threading.Channels.dll +system.threading.channels\4.5.0\lib\netstandard2.0\System.Threading.Channels.dll +system.threading.channels\4.5.0\LICENSE.TXT +system.threading.channels\4.5.0\system.threading.channels.4.5.0.nupkg.sha512 +system.threading.channels\4.5.0\system.threading.channels.nuspec +system.threading.channels\4.5.0\THIRD-PARTY-NOTICES.TXT +system.threading.channels\4.5.0\useSharedDesignerContext.txt +system.threading.channels\4.5.0\version.txt +system.threading.tasks.extensions\4.0.0\dotnet_library_license.txt +system.threading.tasks.extensions\4.0.0\lib\netstandard1.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.0.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.0.0\system.threading.tasks.extensions.4.0.0.nupkg.sha512 +system.threading.tasks.extensions\4.0.0\system.threading.tasks.extensions.nuspec +system.threading.tasks.extensions\4.0.0\ThirdPartyNotices.txt +system.threading.tasks.extensions\4.3.0\dotnet_library_license.txt +system.threading.tasks.extensions\4.3.0\lib\netstandard1.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.3.0\system.threading.tasks.extensions.4.3.0.nupkg.sha512 +system.threading.tasks.extensions\4.3.0\system.threading.tasks.extensions.nuspec +system.threading.tasks.extensions\4.3.0\ThirdPartyNotices.txt +system.threading.tasks.extensions\4.5.1\.signature.p7s +system.threading.tasks.extensions\4.5.1\lib\MonoAndroid10\_._ +system.threading.tasks.extensions\4.5.1\lib\MonoTouch10\_._ +system.threading.tasks.extensions\4.5.1\lib\netcoreapp2.1\_._ +system.threading.tasks.extensions\4.5.1\lib\netstandard1.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\lib\xamarinios10\_._ +system.threading.tasks.extensions\4.5.1\lib\xamarinmac20\_._ +system.threading.tasks.extensions\4.5.1\lib\xamarintvos10\_._ +system.threading.tasks.extensions\4.5.1\lib\xamarinwatchos10\_._ +system.threading.tasks.extensions\4.5.1\LICENSE.TXT +system.threading.tasks.extensions\4.5.1\ref\MonoAndroid10\_._ +system.threading.tasks.extensions\4.5.1\ref\MonoTouch10\_._ +system.threading.tasks.extensions\4.5.1\ref\netcoreapp2.1\_._ +system.threading.tasks.extensions\4.5.1\ref\netstandard1.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\ref\netstandard2.0\System.Threading.Tasks.Extensions.dll +system.threading.tasks.extensions\4.5.1\ref\xamarinios10\_._ +system.threading.tasks.extensions\4.5.1\ref\xamarinmac20\_._ +system.threading.tasks.extensions\4.5.1\ref\xamarintvos10\_._ +system.threading.tasks.extensions\4.5.1\ref\xamarinwatchos10\_._ +system.threading.tasks.extensions\4.5.1\system.threading.tasks.extensions.4.5.1.nupkg.sha512 +system.threading.tasks.extensions\4.5.1\system.threading.tasks.extensions.nuspec +system.threading.tasks.extensions\4.5.1\THIRD-PARTY-NOTICES.TXT +system.threading.tasks.extensions\4.5.1\useSharedDesignerContext.txt +system.threading.tasks.extensions\4.5.1\version.txt +system.threading.tasks.parallel\4.3.0\dotnet_library_license.txt +system.threading.tasks.parallel\4.3.0\lib\MonoAndroid10\_._ +system.threading.tasks.parallel\4.3.0\lib\MonoTouch10\_._ +system.threading.tasks.parallel\4.3.0\lib\net45\_._ +system.threading.tasks.parallel\4.3.0\lib\netcore50\System.Threading.Tasks.Parallel.dll +system.threading.tasks.parallel\4.3.0\lib\netstandard1.3\System.Threading.Tasks.Parallel.dll +system.threading.tasks.parallel\4.3.0\lib\portable-net45+win8+wpa81\_._ +system.threading.tasks.parallel\4.3.0\lib\win8\_._ +system.threading.tasks.parallel\4.3.0\lib\wpa81\_._ +system.threading.tasks.parallel\4.3.0\lib\xamarinios10\_._ +system.threading.tasks.parallel\4.3.0\lib\xamarinmac20\_._ +system.threading.tasks.parallel\4.3.0\lib\xamarintvos10\_._ +system.threading.tasks.parallel\4.3.0\lib\xamarinwatchos10\_._ +system.threading.tasks.parallel\4.3.0\ref\MonoAndroid10\_._ +system.threading.tasks.parallel\4.3.0\ref\MonoTouch10\_._ +system.threading.tasks.parallel\4.3.0\ref\net45\_._ +system.threading.tasks.parallel\4.3.0\ref\netcore50\System.Threading.Tasks.Parallel.dll +system.threading.tasks.parallel\4.3.0\ref\netstandard1.1\System.Threading.Tasks.Parallel.dll +system.threading.tasks.parallel\4.3.0\ref\portable-net45+win8+wpa81\_._ +system.threading.tasks.parallel\4.3.0\ref\win8\_._ +system.threading.tasks.parallel\4.3.0\ref\wpa81\_._ +system.threading.tasks.parallel\4.3.0\ref\xamarinios10\_._ +system.threading.tasks.parallel\4.3.0\ref\xamarinmac20\_._ +system.threading.tasks.parallel\4.3.0\ref\xamarintvos10\_._ +system.threading.tasks.parallel\4.3.0\ref\xamarinwatchos10\_._ +system.threading.tasks.parallel\4.3.0\system.threading.tasks.parallel.4.3.0.nupkg.sha512 +system.threading.tasks.parallel\4.3.0\system.threading.tasks.parallel.nuspec +system.threading.tasks.parallel\4.3.0\ThirdPartyNotices.txt +system.threading.tasks\4.0.11\dotnet_library_license.txt +system.threading.tasks\4.0.11\lib\MonoAndroid10\_._ +system.threading.tasks\4.0.11\lib\MonoTouch10\_._ +system.threading.tasks\4.0.11\lib\net45\_._ +system.threading.tasks\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.threading.tasks\4.0.11\lib\win8\_._ +system.threading.tasks\4.0.11\lib\wp80\_._ +system.threading.tasks\4.0.11\lib\wpa81\_._ +system.threading.tasks\4.0.11\lib\xamarinios10\_._ +system.threading.tasks\4.0.11\lib\xamarinmac20\_._ +system.threading.tasks\4.0.11\lib\xamarintvos10\_._ +system.threading.tasks\4.0.11\lib\xamarinwatchos10\_._ +system.threading.tasks\4.0.11\ref\MonoAndroid10\_._ +system.threading.tasks\4.0.11\ref\MonoTouch10\_._ +system.threading.tasks\4.0.11\ref\net45\_._ +system.threading.tasks\4.0.11\ref\netcore50\System.Threading.Tasks.dll +system.threading.tasks\4.0.11\ref\netstandard1.0\System.Threading.Tasks.dll +system.threading.tasks\4.0.11\ref\netstandard1.3\System.Threading.Tasks.dll +system.threading.tasks\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.threading.tasks\4.0.11\ref\win8\_._ +system.threading.tasks\4.0.11\ref\wp80\_._ +system.threading.tasks\4.0.11\ref\wpa81\_._ +system.threading.tasks\4.0.11\ref\xamarinios10\_._ +system.threading.tasks\4.0.11\ref\xamarinmac20\_._ +system.threading.tasks\4.0.11\ref\xamarintvos10\_._ +system.threading.tasks\4.0.11\ref\xamarinwatchos10\_._ +system.threading.tasks\4.0.11\system.threading.tasks.4.0.11.nupkg.sha512 +system.threading.tasks\4.0.11\system.threading.tasks.nuspec +system.threading.tasks\4.0.11\ThirdPartyNotices.txt +system.threading.tasks\4.3.0\dotnet_library_license.txt +system.threading.tasks\4.3.0\lib\MonoAndroid10\_._ +system.threading.tasks\4.3.0\lib\MonoTouch10\_._ +system.threading.tasks\4.3.0\lib\net45\_._ +system.threading.tasks\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.threading.tasks\4.3.0\lib\win8\_._ +system.threading.tasks\4.3.0\lib\wp80\_._ +system.threading.tasks\4.3.0\lib\wpa81\_._ +system.threading.tasks\4.3.0\lib\xamarinios10\_._ +system.threading.tasks\4.3.0\lib\xamarinmac20\_._ +system.threading.tasks\4.3.0\lib\xamarintvos10\_._ +system.threading.tasks\4.3.0\lib\xamarinwatchos10\_._ +system.threading.tasks\4.3.0\ref\MonoAndroid10\_._ +system.threading.tasks\4.3.0\ref\MonoTouch10\_._ +system.threading.tasks\4.3.0\ref\net45\_._ +system.threading.tasks\4.3.0\ref\netcore50\System.Threading.Tasks.dll +system.threading.tasks\4.3.0\ref\netstandard1.0\System.Threading.Tasks.dll +system.threading.tasks\4.3.0\ref\netstandard1.3\System.Threading.Tasks.dll +system.threading.tasks\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.threading.tasks\4.3.0\ref\win8\_._ +system.threading.tasks\4.3.0\ref\wp80\_._ +system.threading.tasks\4.3.0\ref\wpa81\_._ +system.threading.tasks\4.3.0\ref\xamarinios10\_._ +system.threading.tasks\4.3.0\ref\xamarinmac20\_._ +system.threading.tasks\4.3.0\ref\xamarintvos10\_._ +system.threading.tasks\4.3.0\ref\xamarinwatchos10\_._ +system.threading.tasks\4.3.0\system.threading.tasks.4.3.0.nupkg.sha512 +system.threading.tasks\4.3.0\system.threading.tasks.nuspec +system.threading.tasks\4.3.0\ThirdPartyNotices.txt +system.threading.thread\4.3.0\dotnet_library_license.txt +system.threading.thread\4.3.0\lib\MonoAndroid10\_._ +system.threading.thread\4.3.0\lib\MonoTouch10\_._ +system.threading.thread\4.3.0\lib\net46\System.Threading.Thread.dll +system.threading.thread\4.3.0\lib\netcore50\_._ +system.threading.thread\4.3.0\lib\netstandard1.3\System.Threading.Thread.dll +system.threading.thread\4.3.0\lib\xamarinios10\_._ +system.threading.thread\4.3.0\lib\xamarinmac20\_._ +system.threading.thread\4.3.0\lib\xamarintvos10\_._ +system.threading.thread\4.3.0\lib\xamarinwatchos10\_._ +system.threading.thread\4.3.0\ref\MonoAndroid10\_._ +system.threading.thread\4.3.0\ref\MonoTouch10\_._ +system.threading.thread\4.3.0\ref\net46\System.Threading.Thread.dll +system.threading.thread\4.3.0\ref\netstandard1.3\System.Threading.Thread.dll +system.threading.thread\4.3.0\ref\xamarinios10\_._ +system.threading.thread\4.3.0\ref\xamarinmac20\_._ +system.threading.thread\4.3.0\ref\xamarintvos10\_._ +system.threading.thread\4.3.0\ref\xamarinwatchos10\_._ +system.threading.thread\4.3.0\system.threading.thread.4.3.0.nupkg.sha512 +system.threading.thread\4.3.0\system.threading.thread.nuspec +system.threading.thread\4.3.0\ThirdPartyNotices.txt +system.threading.threadpool\4.3.0\dotnet_library_license.txt +system.threading.threadpool\4.3.0\lib\MonoAndroid10\_._ +system.threading.threadpool\4.3.0\lib\MonoTouch10\_._ +system.threading.threadpool\4.3.0\lib\net46\System.Threading.ThreadPool.dll +system.threading.threadpool\4.3.0\lib\netcore50\_._ +system.threading.threadpool\4.3.0\lib\netstandard1.3\System.Threading.ThreadPool.dll +system.threading.threadpool\4.3.0\lib\xamarinios10\_._ +system.threading.threadpool\4.3.0\lib\xamarinmac20\_._ +system.threading.threadpool\4.3.0\lib\xamarintvos10\_._ +system.threading.threadpool\4.3.0\lib\xamarinwatchos10\_._ +system.threading.threadpool\4.3.0\ref\MonoAndroid10\_._ +system.threading.threadpool\4.3.0\ref\MonoTouch10\_._ +system.threading.threadpool\4.3.0\ref\net46\System.Threading.ThreadPool.dll +system.threading.threadpool\4.3.0\ref\netstandard1.3\System.Threading.ThreadPool.dll +system.threading.threadpool\4.3.0\ref\xamarinios10\_._ +system.threading.threadpool\4.3.0\ref\xamarinmac20\_._ +system.threading.threadpool\4.3.0\ref\xamarintvos10\_._ +system.threading.threadpool\4.3.0\ref\xamarinwatchos10\_._ +system.threading.threadpool\4.3.0\system.threading.threadpool.4.3.0.nupkg.sha512 +system.threading.threadpool\4.3.0\system.threading.threadpool.nuspec +system.threading.threadpool\4.3.0\ThirdPartyNotices.txt +system.threading.timer\4.0.1\dotnet_library_license.txt +system.threading.timer\4.0.1\lib\MonoAndroid10\_._ +system.threading.timer\4.0.1\lib\MonoTouch10\_._ +system.threading.timer\4.0.1\lib\net451\_._ +system.threading.timer\4.0.1\lib\portable-net451+win81+wpa81\_._ +system.threading.timer\4.0.1\lib\win81\_._ +system.threading.timer\4.0.1\lib\wpa81\_._ +system.threading.timer\4.0.1\lib\xamarinios10\_._ +system.threading.timer\4.0.1\lib\xamarinmac20\_._ +system.threading.timer\4.0.1\lib\xamarintvos10\_._ +system.threading.timer\4.0.1\lib\xamarinwatchos10\_._ +system.threading.timer\4.0.1\ref\MonoAndroid10\_._ +system.threading.timer\4.0.1\ref\MonoTouch10\_._ +system.threading.timer\4.0.1\ref\net451\_._ +system.threading.timer\4.0.1\ref\netcore50\System.Threading.Timer.dll +system.threading.timer\4.0.1\ref\netstandard1.2\System.Threading.Timer.dll +system.threading.timer\4.0.1\ref\portable-net451+win81+wpa81\_._ +system.threading.timer\4.0.1\ref\win81\_._ +system.threading.timer\4.0.1\ref\wpa81\_._ +system.threading.timer\4.0.1\ref\xamarinios10\_._ +system.threading.timer\4.0.1\ref\xamarinmac20\_._ +system.threading.timer\4.0.1\ref\xamarintvos10\_._ +system.threading.timer\4.0.1\ref\xamarinwatchos10\_._ +system.threading.timer\4.0.1\system.threading.timer.4.0.1.nupkg.sha512 +system.threading.timer\4.0.1\system.threading.timer.nuspec +system.threading.timer\4.0.1\ThirdPartyNotices.txt +system.threading.timer\4.3.0\dotnet_library_license.txt +system.threading.timer\4.3.0\lib\MonoAndroid10\_._ +system.threading.timer\4.3.0\lib\MonoTouch10\_._ +system.threading.timer\4.3.0\lib\net451\_._ +system.threading.timer\4.3.0\lib\portable-net451+win81+wpa81\_._ +system.threading.timer\4.3.0\lib\win81\_._ +system.threading.timer\4.3.0\lib\wpa81\_._ +system.threading.timer\4.3.0\lib\xamarinios10\_._ +system.threading.timer\4.3.0\lib\xamarinmac20\_._ +system.threading.timer\4.3.0\lib\xamarintvos10\_._ +system.threading.timer\4.3.0\lib\xamarinwatchos10\_._ +system.threading.timer\4.3.0\ref\MonoAndroid10\_._ +system.threading.timer\4.3.0\ref\MonoTouch10\_._ +system.threading.timer\4.3.0\ref\net451\_._ +system.threading.timer\4.3.0\ref\netcore50\System.Threading.Timer.dll +system.threading.timer\4.3.0\ref\netstandard1.2\System.Threading.Timer.dll +system.threading.timer\4.3.0\ref\portable-net451+win81+wpa81\_._ +system.threading.timer\4.3.0\ref\win81\_._ +system.threading.timer\4.3.0\ref\wpa81\_._ +system.threading.timer\4.3.0\ref\xamarinios10\_._ +system.threading.timer\4.3.0\ref\xamarinmac20\_._ +system.threading.timer\4.3.0\ref\xamarintvos10\_._ +system.threading.timer\4.3.0\ref\xamarinwatchos10\_._ +system.threading.timer\4.3.0\system.threading.timer.4.3.0.nupkg.sha512 +system.threading.timer\4.3.0\system.threading.timer.nuspec +system.threading.timer\4.3.0\ThirdPartyNotices.txt +system.threading\4.0.11\dotnet_library_license.txt +system.threading\4.0.11\lib\MonoAndroid10\_._ +system.threading\4.0.11\lib\MonoTouch10\_._ +system.threading\4.0.11\lib\net45\_._ +system.threading\4.0.11\lib\netcore50\System.Threading.dll +system.threading\4.0.11\lib\netstandard1.3\System.Threading.dll +system.threading\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.threading\4.0.11\lib\win8\_._ +system.threading\4.0.11\lib\wp80\_._ +system.threading\4.0.11\lib\wpa81\_._ +system.threading\4.0.11\lib\xamarinios10\_._ +system.threading\4.0.11\lib\xamarinmac20\_._ +system.threading\4.0.11\lib\xamarintvos10\_._ +system.threading\4.0.11\lib\xamarinwatchos10\_._ +system.threading\4.0.11\ref\MonoAndroid10\_._ +system.threading\4.0.11\ref\MonoTouch10\_._ +system.threading\4.0.11\ref\net45\_._ +system.threading\4.0.11\ref\netcore50\System.Threading.dll +system.threading\4.0.11\ref\netstandard1.0\System.Threading.dll +system.threading\4.0.11\ref\netstandard1.3\System.Threading.dll +system.threading\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.threading\4.0.11\ref\win8\_._ +system.threading\4.0.11\ref\wp80\_._ +system.threading\4.0.11\ref\wpa81\_._ +system.threading\4.0.11\ref\xamarinios10\_._ +system.threading\4.0.11\ref\xamarinmac20\_._ +system.threading\4.0.11\ref\xamarintvos10\_._ +system.threading\4.0.11\ref\xamarinwatchos10\_._ +system.threading\4.0.11\runtimes\aot\lib\netcore50\System.Threading.dll +system.threading\4.0.11\system.threading.4.0.11.nupkg.sha512 +system.threading\4.0.11\system.threading.nuspec +system.threading\4.0.11\ThirdPartyNotices.txt +system.threading\4.3.0\dotnet_library_license.txt +system.threading\4.3.0\lib\MonoAndroid10\_._ +system.threading\4.3.0\lib\MonoTouch10\_._ +system.threading\4.3.0\lib\net45\_._ +system.threading\4.3.0\lib\netcore50\System.Threading.dll +system.threading\4.3.0\lib\netstandard1.3\System.Threading.dll +system.threading\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.threading\4.3.0\lib\win8\_._ +system.threading\4.3.0\lib\wp80\_._ +system.threading\4.3.0\lib\wpa81\_._ +system.threading\4.3.0\lib\xamarinios10\_._ +system.threading\4.3.0\lib\xamarinmac20\_._ +system.threading\4.3.0\lib\xamarintvos10\_._ +system.threading\4.3.0\lib\xamarinwatchos10\_._ +system.threading\4.3.0\ref\MonoAndroid10\_._ +system.threading\4.3.0\ref\MonoTouch10\_._ +system.threading\4.3.0\ref\net45\_._ +system.threading\4.3.0\ref\netcore50\System.Threading.dll +system.threading\4.3.0\ref\netstandard1.0\System.Threading.dll +system.threading\4.3.0\ref\netstandard1.3\System.Threading.dll +system.threading\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.threading\4.3.0\ref\win8\_._ +system.threading\4.3.0\ref\wp80\_._ +system.threading\4.3.0\ref\wpa81\_._ +system.threading\4.3.0\ref\xamarinios10\_._ +system.threading\4.3.0\ref\xamarinmac20\_._ +system.threading\4.3.0\ref\xamarintvos10\_._ +system.threading\4.3.0\ref\xamarinwatchos10\_._ +system.threading\4.3.0\runtimes\aot\lib\netcore50\System.Threading.dll +system.threading\4.3.0\system.threading.4.3.0.nupkg.sha512 +system.threading\4.3.0\system.threading.nuspec +system.threading\4.3.0\ThirdPartyNotices.txt +system.valuetuple\4.3.0\dotnet_library_license.txt +system.valuetuple\4.3.0\lib\netstandard1.0\.xml +system.valuetuple\4.3.0\lib\netstandard1.0\System.ValueTuple.dll +system.valuetuple\4.3.0\lib\portable-net40+sl4+win8+wp8\.xml +system.valuetuple\4.3.0\lib\portable-net40+sl4+win8+wp8\System.ValueTuple.dll +system.valuetuple\4.3.0\system.valuetuple.4.3.0.nupkg.sha512 +system.valuetuple\4.3.0\system.valuetuple.nuspec +system.valuetuple\4.3.0\ThirdPartyNotices.txt +system.valuetuple\4.5.0\.signature.p7s +system.valuetuple\4.5.0\lib\MonoAndroid10\_._ +system.valuetuple\4.5.0\lib\MonoTouch10\_._ +system.valuetuple\4.5.0\lib\net461\System.ValueTuple.dll +system.valuetuple\4.5.0\lib\net47\System.ValueTuple.dll +system.valuetuple\4.5.0\lib\netcoreapp2.0\_._ +system.valuetuple\4.5.0\lib\netstandard1.0\System.ValueTuple.dll +system.valuetuple\4.5.0\lib\netstandard2.0\_._ +system.valuetuple\4.5.0\lib\portable-net40+sl4+win8+wp8\System.ValueTuple.dll +system.valuetuple\4.5.0\lib\uap10.0.16299\_._ +system.valuetuple\4.5.0\lib\xamarinios10\_._ +system.valuetuple\4.5.0\lib\xamarinmac20\_._ +system.valuetuple\4.5.0\lib\xamarintvos10\_._ +system.valuetuple\4.5.0\lib\xamarinwatchos10\_._ +system.valuetuple\4.5.0\LICENSE.TXT +system.valuetuple\4.5.0\ref\MonoAndroid10\_._ +system.valuetuple\4.5.0\ref\MonoTouch10\_._ +system.valuetuple\4.5.0\ref\net461\System.ValueTuple.dll +system.valuetuple\4.5.0\ref\net47\System.ValueTuple.dll +system.valuetuple\4.5.0\ref\netcoreapp2.0\_._ +system.valuetuple\4.5.0\ref\netstandard2.0\_._ +system.valuetuple\4.5.0\ref\portable-net40+sl4+win8+wp8\System.ValueTuple.dll +system.valuetuple\4.5.0\ref\uap10.0.16299\_._ +system.valuetuple\4.5.0\ref\xamarinios10\_._ +system.valuetuple\4.5.0\ref\xamarinmac20\_._ +system.valuetuple\4.5.0\ref\xamarintvos10\_._ +system.valuetuple\4.5.0\ref\xamarinwatchos10\_._ +system.valuetuple\4.5.0\system.valuetuple.4.5.0.nupkg.sha512 +system.valuetuple\4.5.0\system.valuetuple.nuspec +system.valuetuple\4.5.0\THIRD-PARTY-NOTICES.TXT +system.valuetuple\4.5.0\useSharedDesignerContext.txt +system.valuetuple\4.5.0\version.txt +system.xml.readerwriter\4.0.11\dotnet_library_license.txt +system.xml.readerwriter\4.0.11\lib\MonoAndroid10\_._ +system.xml.readerwriter\4.0.11\lib\MonoTouch10\_._ +system.xml.readerwriter\4.0.11\lib\net45\_._ +system.xml.readerwriter\4.0.11\lib\netcore50\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\lib\netstandard1.3\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.readerwriter\4.0.11\lib\win8\_._ +system.xml.readerwriter\4.0.11\lib\wp80\_._ +system.xml.readerwriter\4.0.11\lib\wpa81\_._ +system.xml.readerwriter\4.0.11\lib\xamarinios10\_._ +system.xml.readerwriter\4.0.11\lib\xamarinmac20\_._ +system.xml.readerwriter\4.0.11\lib\xamarintvos10\_._ +system.xml.readerwriter\4.0.11\lib\xamarinwatchos10\_._ +system.xml.readerwriter\4.0.11\ref\MonoAndroid10\_._ +system.xml.readerwriter\4.0.11\ref\MonoTouch10\_._ +system.xml.readerwriter\4.0.11\ref\net45\_._ +system.xml.readerwriter\4.0.11\ref\netcore50\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\ref\netstandard1.0\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\ref\netstandard1.3\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.readerwriter\4.0.11\ref\win8\_._ +system.xml.readerwriter\4.0.11\ref\wp80\_._ +system.xml.readerwriter\4.0.11\ref\wpa81\_._ +system.xml.readerwriter\4.0.11\ref\xamarinios10\_._ +system.xml.readerwriter\4.0.11\ref\xamarinmac20\_._ +system.xml.readerwriter\4.0.11\ref\xamarintvos10\_._ +system.xml.readerwriter\4.0.11\ref\xamarinwatchos10\_._ +system.xml.readerwriter\4.0.11\system.xml.readerwriter.4.0.11.nupkg.sha512 +system.xml.readerwriter\4.0.11\system.xml.readerwriter.nuspec +system.xml.readerwriter\4.0.11\ThirdPartyNotices.txt +system.xml.readerwriter\4.3.0\dotnet_library_license.txt +system.xml.readerwriter\4.3.0\lib\MonoAndroid10\_._ +system.xml.readerwriter\4.3.0\lib\MonoTouch10\_._ +system.xml.readerwriter\4.3.0\lib\net45\_._ +system.xml.readerwriter\4.3.0\lib\net46\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\lib\netcore50\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\lib\netstandard1.3\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.readerwriter\4.3.0\lib\win8\_._ +system.xml.readerwriter\4.3.0\lib\wp80\_._ +system.xml.readerwriter\4.3.0\lib\wpa81\_._ +system.xml.readerwriter\4.3.0\lib\xamarinios10\_._ +system.xml.readerwriter\4.3.0\lib\xamarinmac20\_._ +system.xml.readerwriter\4.3.0\lib\xamarintvos10\_._ +system.xml.readerwriter\4.3.0\lib\xamarinwatchos10\_._ +system.xml.readerwriter\4.3.0\ref\MonoAndroid10\_._ +system.xml.readerwriter\4.3.0\ref\MonoTouch10\_._ +system.xml.readerwriter\4.3.0\ref\net45\_._ +system.xml.readerwriter\4.3.0\ref\net46\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\ref\netcore50\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\ref\netstandard1.0\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\ref\netstandard1.3\System.Xml.ReaderWriter.dll +system.xml.readerwriter\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.readerwriter\4.3.0\ref\win8\_._ +system.xml.readerwriter\4.3.0\ref\wp80\_._ +system.xml.readerwriter\4.3.0\ref\wpa81\_._ +system.xml.readerwriter\4.3.0\ref\xamarinios10\_._ +system.xml.readerwriter\4.3.0\ref\xamarinmac20\_._ +system.xml.readerwriter\4.3.0\ref\xamarintvos10\_._ +system.xml.readerwriter\4.3.0\ref\xamarinwatchos10\_._ +system.xml.readerwriter\4.3.0\system.xml.readerwriter.4.3.0.nupkg.sha512 +system.xml.readerwriter\4.3.0\system.xml.readerwriter.nuspec +system.xml.readerwriter\4.3.0\ThirdPartyNotices.txt +system.xml.xdocument\4.0.11\dotnet_library_license.txt +system.xml.xdocument\4.0.11\lib\MonoAndroid10\_._ +system.xml.xdocument\4.0.11\lib\MonoTouch10\_._ +system.xml.xdocument\4.0.11\lib\net45\_._ +system.xml.xdocument\4.0.11\lib\netcore50\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\lib\netstandard1.3\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.xdocument\4.0.11\lib\win8\_._ +system.xml.xdocument\4.0.11\lib\wp80\_._ +system.xml.xdocument\4.0.11\lib\wpa81\_._ +system.xml.xdocument\4.0.11\lib\xamarinios10\_._ +system.xml.xdocument\4.0.11\lib\xamarinmac20\_._ +system.xml.xdocument\4.0.11\lib\xamarintvos10\_._ +system.xml.xdocument\4.0.11\lib\xamarinwatchos10\_._ +system.xml.xdocument\4.0.11\ref\MonoAndroid10\_._ +system.xml.xdocument\4.0.11\ref\MonoTouch10\_._ +system.xml.xdocument\4.0.11\ref\net45\_._ +system.xml.xdocument\4.0.11\ref\netcore50\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\ref\netstandard1.0\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\ref\netstandard1.3\System.Xml.XDocument.dll +system.xml.xdocument\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.xdocument\4.0.11\ref\win8\_._ +system.xml.xdocument\4.0.11\ref\wp80\_._ +system.xml.xdocument\4.0.11\ref\wpa81\_._ +system.xml.xdocument\4.0.11\ref\xamarinios10\_._ +system.xml.xdocument\4.0.11\ref\xamarinmac20\_._ +system.xml.xdocument\4.0.11\ref\xamarintvos10\_._ +system.xml.xdocument\4.0.11\ref\xamarinwatchos10\_._ +system.xml.xdocument\4.0.11\system.xml.xdocument.4.0.11.nupkg.sha512 +system.xml.xdocument\4.0.11\system.xml.xdocument.nuspec +system.xml.xdocument\4.0.11\ThirdPartyNotices.txt +system.xml.xdocument\4.3.0\dotnet_library_license.txt +system.xml.xdocument\4.3.0\lib\MonoAndroid10\_._ +system.xml.xdocument\4.3.0\lib\MonoTouch10\_._ +system.xml.xdocument\4.3.0\lib\net45\_._ +system.xml.xdocument\4.3.0\lib\netcore50\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\lib\netstandard1.3\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.xdocument\4.3.0\lib\win8\_._ +system.xml.xdocument\4.3.0\lib\wp80\_._ +system.xml.xdocument\4.3.0\lib\wpa81\_._ +system.xml.xdocument\4.3.0\lib\xamarinios10\_._ +system.xml.xdocument\4.3.0\lib\xamarinmac20\_._ +system.xml.xdocument\4.3.0\lib\xamarintvos10\_._ +system.xml.xdocument\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xdocument\4.3.0\ref\MonoAndroid10\_._ +system.xml.xdocument\4.3.0\ref\MonoTouch10\_._ +system.xml.xdocument\4.3.0\ref\net45\_._ +system.xml.xdocument\4.3.0\ref\netcore50\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\ref\netstandard1.0\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\ref\netstandard1.3\System.Xml.XDocument.dll +system.xml.xdocument\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.xdocument\4.3.0\ref\win8\_._ +system.xml.xdocument\4.3.0\ref\wp80\_._ +system.xml.xdocument\4.3.0\ref\wpa81\_._ +system.xml.xdocument\4.3.0\ref\xamarinios10\_._ +system.xml.xdocument\4.3.0\ref\xamarinmac20\_._ +system.xml.xdocument\4.3.0\ref\xamarintvos10\_._ +system.xml.xdocument\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xdocument\4.3.0\system.xml.xdocument.4.3.0.nupkg.sha512 +system.xml.xdocument\4.3.0\system.xml.xdocument.nuspec +system.xml.xdocument\4.3.0\ThirdPartyNotices.txt +system.xml.xmldocument\4.0.1\dotnet_library_license.txt +system.xml.xmldocument\4.0.1\lib\MonoAndroid10\_._ +system.xml.xmldocument\4.0.1\lib\MonoTouch10\_._ +system.xml.xmldocument\4.0.1\lib\net46\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.0.1\lib\netstandard1.3\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.0.1\lib\xamarinios10\_._ +system.xml.xmldocument\4.0.1\lib\xamarinmac20\_._ +system.xml.xmldocument\4.0.1\lib\xamarintvos10\_._ +system.xml.xmldocument\4.0.1\lib\xamarinwatchos10\_._ +system.xml.xmldocument\4.0.1\ref\MonoAndroid10\_._ +system.xml.xmldocument\4.0.1\ref\MonoTouch10\_._ +system.xml.xmldocument\4.0.1\ref\net46\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.0.1\ref\netstandard1.3\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.0.1\ref\xamarinios10\_._ +system.xml.xmldocument\4.0.1\ref\xamarinmac20\_._ +system.xml.xmldocument\4.0.1\ref\xamarintvos10\_._ +system.xml.xmldocument\4.0.1\ref\xamarinwatchos10\_._ +system.xml.xmldocument\4.0.1\system.xml.xmldocument.4.0.1.nupkg.sha512 +system.xml.xmldocument\4.0.1\system.xml.xmldocument.nuspec +system.xml.xmldocument\4.0.1\ThirdPartyNotices.txt +system.xml.xmldocument\4.3.0\dotnet_library_license.txt +system.xml.xmldocument\4.3.0\lib\MonoAndroid10\_._ +system.xml.xmldocument\4.3.0\lib\MonoTouch10\_._ +system.xml.xmldocument\4.3.0\lib\net46\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.3.0\lib\netstandard1.3\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.3.0\lib\xamarinios10\_._ +system.xml.xmldocument\4.3.0\lib\xamarinmac20\_._ +system.xml.xmldocument\4.3.0\lib\xamarintvos10\_._ +system.xml.xmldocument\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xmldocument\4.3.0\ref\MonoAndroid10\_._ +system.xml.xmldocument\4.3.0\ref\MonoTouch10\_._ +system.xml.xmldocument\4.3.0\ref\net46\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.3.0\ref\netstandard1.3\System.Xml.XmlDocument.dll +system.xml.xmldocument\4.3.0\ref\xamarinios10\_._ +system.xml.xmldocument\4.3.0\ref\xamarinmac20\_._ +system.xml.xmldocument\4.3.0\ref\xamarintvos10\_._ +system.xml.xmldocument\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xmldocument\4.3.0\system.xml.xmldocument.4.3.0.nupkg.sha512 +system.xml.xmldocument\4.3.0\system.xml.xmldocument.nuspec +system.xml.xmldocument\4.3.0\ThirdPartyNotices.txt +system.xml.xmlserializer\4.0.11\dotnet_library_license.txt +system.xml.xmlserializer\4.0.11\lib\MonoAndroid10\_._ +system.xml.xmlserializer\4.0.11\lib\MonoTouch10\_._ +system.xml.xmlserializer\4.0.11\lib\net45\_._ +system.xml.xmlserializer\4.0.11\lib\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\lib\netstandard1.3\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.xmlserializer\4.0.11\lib\win8\_._ +system.xml.xmlserializer\4.0.11\lib\wp80\_._ +system.xml.xmlserializer\4.0.11\lib\wpa81\_._ +system.xml.xmlserializer\4.0.11\lib\xamarinios10\_._ +system.xml.xmlserializer\4.0.11\lib\xamarinmac20\_._ +system.xml.xmlserializer\4.0.11\lib\xamarintvos10\_._ +system.xml.xmlserializer\4.0.11\lib\xamarinwatchos10\_._ +system.xml.xmlserializer\4.0.11\ref\MonoAndroid10\_._ +system.xml.xmlserializer\4.0.11\ref\MonoTouch10\_._ +system.xml.xmlserializer\4.0.11\ref\net45\_._ +system.xml.xmlserializer\4.0.11\ref\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\ref\netstandard1.0\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\ref\netstandard1.3\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.xmlserializer\4.0.11\ref\win8\_._ +system.xml.xmlserializer\4.0.11\ref\wp80\_._ +system.xml.xmlserializer\4.0.11\ref\wpa81\_._ +system.xml.xmlserializer\4.0.11\ref\xamarinios10\_._ +system.xml.xmlserializer\4.0.11\ref\xamarinmac20\_._ +system.xml.xmlserializer\4.0.11\ref\xamarintvos10\_._ +system.xml.xmlserializer\4.0.11\ref\xamarinwatchos10\_._ +system.xml.xmlserializer\4.0.11\runtimes\aot\lib\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.0.11\system.xml.xmlserializer.4.0.11.nupkg.sha512 +system.xml.xmlserializer\4.0.11\system.xml.xmlserializer.nuspec +system.xml.xmlserializer\4.0.11\ThirdPartyNotices.txt +system.xml.xmlserializer\4.3.0\dotnet_library_license.txt +system.xml.xmlserializer\4.3.0\lib\MonoAndroid10\_._ +system.xml.xmlserializer\4.3.0\lib\MonoTouch10\_._ +system.xml.xmlserializer\4.3.0\lib\net45\_._ +system.xml.xmlserializer\4.3.0\lib\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\lib\netstandard1.3\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.xml.xmlserializer\4.3.0\lib\win8\_._ +system.xml.xmlserializer\4.3.0\lib\wp80\_._ +system.xml.xmlserializer\4.3.0\lib\wpa81\_._ +system.xml.xmlserializer\4.3.0\lib\xamarinios10\_._ +system.xml.xmlserializer\4.3.0\lib\xamarinmac20\_._ +system.xml.xmlserializer\4.3.0\lib\xamarintvos10\_._ +system.xml.xmlserializer\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xmlserializer\4.3.0\ref\MonoAndroid10\_._ +system.xml.xmlserializer\4.3.0\ref\MonoTouch10\_._ +system.xml.xmlserializer\4.3.0\ref\net45\_._ +system.xml.xmlserializer\4.3.0\ref\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\ref\netstandard1.0\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\ref\netstandard1.3\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.xml.xmlserializer\4.3.0\ref\win8\_._ +system.xml.xmlserializer\4.3.0\ref\wp80\_._ +system.xml.xmlserializer\4.3.0\ref\wpa81\_._ +system.xml.xmlserializer\4.3.0\ref\xamarinios10\_._ +system.xml.xmlserializer\4.3.0\ref\xamarinmac20\_._ +system.xml.xmlserializer\4.3.0\ref\xamarintvos10\_._ +system.xml.xmlserializer\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xmlserializer\4.3.0\runtimes\aot\lib\netcore50\System.Xml.XmlSerializer.dll +system.xml.xmlserializer\4.3.0\system.xml.xmlserializer.4.3.0.nupkg.sha512 +system.xml.xmlserializer\4.3.0\system.xml.xmlserializer.nuspec +system.xml.xmlserializer\4.3.0\ThirdPartyNotices.txt +system.xml.xpath.xdocument\4.3.0\dotnet_library_license.txt +system.xml.xpath.xdocument\4.3.0\lib\MonoAndroid10\_._ +system.xml.xpath.xdocument\4.3.0\lib\MonoTouch10\_._ +system.xml.xpath.xdocument\4.3.0\lib\net46\System.Xml.XPath.XDocument.dll +system.xml.xpath.xdocument\4.3.0\lib\netstandard1.3\System.Xml.XPath.XDocument.dll +system.xml.xpath.xdocument\4.3.0\lib\xamarinios10\_._ +system.xml.xpath.xdocument\4.3.0\lib\xamarinmac20\_._ +system.xml.xpath.xdocument\4.3.0\lib\xamarintvos10\_._ +system.xml.xpath.xdocument\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xpath.xdocument\4.3.0\ref\MonoAndroid10\_._ +system.xml.xpath.xdocument\4.3.0\ref\MonoTouch10\_._ +system.xml.xpath.xdocument\4.3.0\ref\net46\System.Xml.XPath.XDocument.dll +system.xml.xpath.xdocument\4.3.0\ref\netstandard1.3\System.Xml.XPath.XDocument.dll +system.xml.xpath.xdocument\4.3.0\ref\xamarinios10\_._ +system.xml.xpath.xdocument\4.3.0\ref\xamarinmac20\_._ +system.xml.xpath.xdocument\4.3.0\ref\xamarintvos10\_._ +system.xml.xpath.xdocument\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xpath.xdocument\4.3.0\system.xml.xpath.xdocument.4.3.0.nupkg.sha512 +system.xml.xpath.xdocument\4.3.0\system.xml.xpath.xdocument.nuspec +system.xml.xpath.xdocument\4.3.0\ThirdPartyNotices.txt +system.xml.xpath\4.3.0\dotnet_library_license.txt +system.xml.xpath\4.3.0\lib\MonoAndroid10\_._ +system.xml.xpath\4.3.0\lib\MonoTouch10\_._ +system.xml.xpath\4.3.0\lib\net46\System.Xml.XPath.dll +system.xml.xpath\4.3.0\lib\netstandard1.3\System.Xml.XPath.dll +system.xml.xpath\4.3.0\lib\xamarinios10\_._ +system.xml.xpath\4.3.0\lib\xamarinmac20\_._ +system.xml.xpath\4.3.0\lib\xamarintvos10\_._ +system.xml.xpath\4.3.0\lib\xamarinwatchos10\_._ +system.xml.xpath\4.3.0\ref\MonoAndroid10\_._ +system.xml.xpath\4.3.0\ref\MonoTouch10\_._ +system.xml.xpath\4.3.0\ref\net46\System.Xml.XPath.dll +system.xml.xpath\4.3.0\ref\netstandard1.3\System.Xml.XPath.dll +system.xml.xpath\4.3.0\ref\xamarinios10\_._ +system.xml.xpath\4.3.0\ref\xamarinmac20\_._ +system.xml.xpath\4.3.0\ref\xamarintvos10\_._ +system.xml.xpath\4.3.0\ref\xamarinwatchos10\_._ +system.xml.xpath\4.3.0\system.xml.xpath.4.3.0.nupkg.sha512 +system.xml.xpath\4.3.0\system.xml.xpath.nuspec +system.xml.xpath\4.3.0\ThirdPartyNotices.txt +windowsazure.storage\8.1.4\lib\net45\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\net45\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\netstandard1.0\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\netstandard1.0\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\netstandard1.3\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\netstandard1.3\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\win8\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\win8\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\wp8\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\wp8\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\lib\wpa\Microsoft.WindowsAzure.Storage.dll +windowsazure.storage\8.1.4\lib\wpa\Microsoft.WindowsAzure.Storage.pdb +windowsazure.storage\8.1.4\windowsazure.storage.8.1.4.nupkg.sha512 +windowsazure.storage\8.1.4\windowsazure.storage.nuspec diff --git a/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.2.txt b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.2.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.3.txt b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.3.txt new file mode 100644 index 0000000000..35771464bf --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.3.txt @@ -0,0 +1,368 @@ +microsoft.netcore.app\2.1.0\.signature.p7s +microsoft.netcore.app\2.1.0\build\netcoreapp2.1\Microsoft.NETCore.App.PlatformManifest.txt +microsoft.netcore.app\2.1.0\build\netcoreapp2.1\Microsoft.NETCore.App.props +microsoft.netcore.app\2.1.0\build\netcoreapp2.1\Microsoft.NETCore.App.targets +microsoft.netcore.app\2.1.0\LICENSE.TXT +microsoft.netcore.app\2.1.0\microsoft.netcore.app.2.1.0.nupkg.sha512 +microsoft.netcore.app\2.1.0\microsoft.netcore.app.nuspec +microsoft.netcore.app\2.1.0\Microsoft.NETCore.App.versions.txt +microsoft.netcore.app\2.1.0\ref\netcoreapp\_._ +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\Microsoft.CSharp.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\Microsoft.VisualBasic.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\Microsoft.Win32.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\mscorlib.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\netstandard.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.AppContext.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Buffers.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Concurrent.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Immutable.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.NonGeneric.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Specialized.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.Annotations.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.DataAnnotations.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.EventBasedAsync.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ComponentModel.TypeConverter.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Configuration.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Console.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Core.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Data.Common.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Data.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Contracts.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Debug.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.DiagnosticSource.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.FileVersionInfo.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Process.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.StackTrace.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.TextWriterTraceListener.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Tools.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.TraceSource.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.Tracing.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Drawing.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Drawing.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Dynamic.Runtime.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Globalization.Calendars.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Globalization.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Globalization.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Compression.Brotli.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Compression.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Compression.FileSystem.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Compression.ZipFile.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.FileSystem.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.FileSystem.DriveInfo.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.FileSystem.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.FileSystem.Watcher.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.IsolatedStorage.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.MemoryMappedFiles.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.Pipes.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.IO.UnmanagedMemoryStream.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Expressions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Parallel.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Queryable.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Memory.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Http.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.HttpListener.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Mail.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.NameResolution.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.NetworkInformation.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Ping.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Requests.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Security.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.ServicePoint.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.Sockets.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebClient.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebHeaderCollection.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebProxy.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebSockets.Client.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Net.WebSockets.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Numerics.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Numerics.Vectors.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ObjectModel.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.DispatchProxy.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Emit.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Emit.ILGeneration.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Emit.Lightweight.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Metadata.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.TypeExtensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Resources.Reader.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Resources.ResourceManager.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Resources.Writer.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.CompilerServices.VisualC.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Handles.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.InteropServices.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.InteropServices.RuntimeInformation.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.InteropServices.WindowsRuntime.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Loader.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Numerics.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Formatters.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Json.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Xml.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Claims.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.Algorithms.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.Csp.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.Encoding.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.Primitives.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Cryptography.X509Certificates.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.Principal.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Security.SecureString.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ServiceModel.Web.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ServiceProcess.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Text.Encoding.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Text.Encoding.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Text.RegularExpressions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Overlapped.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Tasks.Dataflow.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Tasks.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Tasks.Extensions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Tasks.Parallel.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Thread.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.ThreadPool.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Threading.Timer.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Transactions.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Transactions.Local.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.ValueTuple.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Web.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Web.HttpUtility.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Windows.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.Linq.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.ReaderWriter.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.Serialization.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XDocument.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XmlDocument.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XmlSerializer.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XPath.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Xml.XPath.XDocument.dll +microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\WindowsBase.dll +microsoft.netcore.app\2.1.0\runtime.json +microsoft.netcore.app\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnetapphost\2.1.0\.signature.p7s +microsoft.netcore.dotnetapphost\2.1.0\LICENSE.TXT +microsoft.netcore.dotnetapphost\2.1.0\microsoft.netcore.dotnetapphost.2.1.0.nupkg.sha512 +microsoft.netcore.dotnetapphost\2.1.0\microsoft.netcore.dotnetapphost.nuspec +microsoft.netcore.dotnetapphost\2.1.0\runtime.json +microsoft.netcore.dotnetapphost\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostpolicy\2.1.0\.signature.p7s +microsoft.netcore.dotnethostpolicy\2.1.0\LICENSE.TXT +microsoft.netcore.dotnethostpolicy\2.1.0\microsoft.netcore.dotnethostpolicy.2.1.0.nupkg.sha512 +microsoft.netcore.dotnethostpolicy\2.1.0\microsoft.netcore.dotnethostpolicy.nuspec +microsoft.netcore.dotnethostpolicy\2.1.0\runtime.json +microsoft.netcore.dotnethostpolicy\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostresolver\2.1.0\.signature.p7s +microsoft.netcore.dotnethostresolver\2.1.0\LICENSE.TXT +microsoft.netcore.dotnethostresolver\2.1.0\microsoft.netcore.dotnethostresolver.2.1.0.nupkg.sha512 +microsoft.netcore.dotnethostresolver\2.1.0\microsoft.netcore.dotnethostresolver.nuspec +microsoft.netcore.dotnethostresolver\2.1.0\runtime.json +microsoft.netcore.dotnethostresolver\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.targets\2.1.0\.signature.p7s +microsoft.netcore.targets\2.1.0\lib\netstandard1.0\_._ +microsoft.netcore.targets\2.1.0\LICENSE.TXT +microsoft.netcore.targets\2.1.0\microsoft.netcore.targets.2.1.0.nupkg.sha512 +microsoft.netcore.targets\2.1.0\microsoft.netcore.targets.nuspec +microsoft.netcore.targets\2.1.0\runtime.json +microsoft.netcore.targets\2.1.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.targets\2.1.0\useSharedDesignerContext.txt +microsoft.netcore.targets\2.1.0\version.txt +microsoft.visualstudio.web.codegeneration.contracts\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.3\microsoft.visualstudio.web.codegeneration.contracts.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.3\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.3\microsoft.visualstudio.web.codegeneration.core.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.3\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.3\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.3\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.3\microsoft.visualstudio.web.codegeneration.design.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.3\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.3\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.3\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.3\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.3\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.3\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.3\microsoft.visualstudio.web.codegeneration.templating.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.3\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.3\microsoft.visualstudio.web.codegeneration.utils.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.3\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.3\microsoft.visualstudio.web.codegeneration.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.3\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\microsoft.visualstudio.web.codegenerators.mvc.2.1.3.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.3\Templates\ViewGenerator\List.cshtml diff --git a/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.4.txt b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.4.txt new file mode 100644 index 0000000000..f7116bcbe5 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.4.txt @@ -0,0 +1,187 @@ +microsoft.visualstudio.web.codegeneration.contracts\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.4\microsoft.visualstudio.web.codegeneration.contracts.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.4\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.4\microsoft.visualstudio.web.codegeneration.core.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.4\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.4\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.4\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.4\microsoft.visualstudio.web.codegeneration.design.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.4\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.4\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.4\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.4\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.4\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.4\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.4\microsoft.visualstudio.web.codegeneration.templating.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.4\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.4\microsoft.visualstudio.web.codegeneration.utils.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.4\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.4\microsoft.visualstudio.web.codegeneration.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.4\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\microsoft.visualstudio.web.codegenerators.mvc.2.1.4.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.4\Templates\ViewGenerator\List.cshtml diff --git a/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.5.txt b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.5.txt new file mode 100644 index 0000000000..e16aa65b04 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.5.txt @@ -0,0 +1,205 @@ +microsoft.aspnetcore.razor.design\2.1.2\.signature.p7s +microsoft.aspnetcore.razor.design\2.1.2\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets +microsoft.aspnetcore.razor.design\2.1.2\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.1.2\buildMultiTargeting\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.1.2\microsoft.aspnetcore.razor.design.2.1.2.nupkg.sha512 +microsoft.aspnetcore.razor.design\2.1.2\microsoft.aspnetcore.razor.design.nuspec +microsoft.aspnetcore.razor.design\2.1.2\tasks\net46\Microsoft.AspNetCore.Razor.Tasks.dll +microsoft.aspnetcore.razor.design\2.1.2\tasks\netstandard2.0\Microsoft.AspNetCore.Razor.Tasks.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Microsoft.CodeAnalysis.CSharp.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Microsoft.CodeAnalysis.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Microsoft.CodeAnalysis.Razor.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\Newtonsoft.Json.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\runtimes\unix\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\rzc.deps.json +microsoft.aspnetcore.razor.design\2.1.2\tools\rzc.dll +microsoft.aspnetcore.razor.design\2.1.2\tools\rzc.runtimeconfig.json +microsoft.visualstudio.web.codegeneration.contracts\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.5\microsoft.visualstudio.web.codegeneration.contracts.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.5\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.5\microsoft.visualstudio.web.codegeneration.core.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.5\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.5\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.5\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.5\microsoft.visualstudio.web.codegeneration.design.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.5\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.5\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.5\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.5\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.5\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.5\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.5\microsoft.visualstudio.web.codegeneration.templating.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.5\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.5\microsoft.visualstudio.web.codegeneration.utils.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.5\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.5\microsoft.visualstudio.web.codegeneration.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.5\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\microsoft.visualstudio.web.codegenerators.mvc.2.1.5.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.5\Templates\ViewGenerator\List.cshtml diff --git a/src/PackageArchive/Archive.CiServer/Archive.CiServer.zipproj b/src/PackageArchive/Archive.CiServer/Archive.CiServer.zipproj new file mode 100644 index 0000000000..770299f91d --- /dev/null +++ b/src/PackageArchive/Archive.CiServer/Archive.CiServer.zipproj @@ -0,0 +1,14 @@ + + + + + + + nuGetPackagesArchive-ci-server-$(PackageVersion).zip + false + false + false + + + + diff --git a/src/PackageArchive/Archive.Lzma/Archive.Lzma.lzmaproj b/src/PackageArchive/Archive.Lzma/Archive.Lzma.lzmaproj new file mode 100644 index 0000000000..a0dcc7e6d3 --- /dev/null +++ b/src/PackageArchive/Archive.Lzma/Archive.Lzma.lzmaproj @@ -0,0 +1,14 @@ + + + + + + + nuGetPackagesArchive-$(PackageVersion).lzma + false + true + true + + + + diff --git a/src/PackageArchive/Archive.props b/src/PackageArchive/Archive.props new file mode 100644 index 0000000000..81c2c200b0 --- /dev/null +++ b/src/PackageArchive/Archive.props @@ -0,0 +1,13 @@ + + + + + + + + + netcoreapp3.0 + + 99.9 + + diff --git a/src/PackageArchive/Archive.targets b/src/PackageArchive/Archive.targets new file mode 100644 index 0000000000..9775f74148 --- /dev/null +++ b/src/PackageArchive/Archive.targets @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + $(CollectInputsDependsOn);CollectNupkgExclusions + $(CollectInputsDependsOn);CollectXmlExclusions + $(CollectInputsDependsOn);CollectBaselineExclusions + + + + + + + + + + + <_ArchiveItemXml Include="$(RestorePackagesPath)**\*.xml" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$([MSBuild]::Subtract($(AspNetCorePatchVersion), 1)) + + + + + + + + diff --git a/src/PackageArchive/Directory.Build.props b/src/PackageArchive/Directory.Build.props new file mode 100644 index 0000000000..3a70818a8d --- /dev/null +++ b/src/PackageArchive/Directory.Build.props @@ -0,0 +1,13 @@ + + + + + + true + + true + + $([MSBuild]::NormalizePath('$(RepositoryRoot)obj\pkgs\')) + + + diff --git a/src/PackageArchive/Directory.Build.targets b/src/PackageArchive/Directory.Build.targets new file mode 100644 index 0000000000..058246e408 --- /dev/null +++ b/src/PackageArchive/Directory.Build.targets @@ -0,0 +1 @@ + diff --git a/src/PackageArchive/README.md b/src/PackageArchive/README.md new file mode 100644 index 0000000000..6ac17c97a2 --- /dev/null +++ b/src/PackageArchive/README.md @@ -0,0 +1,6 @@ +PackageArchive +============== + +See [docs/PackageArchives.md](/docs/PackageArchives.md) for details. + +See [ZipManifestGenerator](/src/PackageArchive/ZipManifestGenerator) for instructions on updating the build for new releases. diff --git a/src/PackageArchive/Scenario.ClassLibrary/Scenario.ClassLibrary.csproj b/src/PackageArchive/Scenario.ClassLibrary/Scenario.ClassLibrary.csproj new file mode 100644 index 0000000000..4ed79ffecc --- /dev/null +++ b/src/PackageArchive/Scenario.ClassLibrary/Scenario.ClassLibrary.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/src/PackageArchive/Scenario.ConsoleApp/Scenario.ConsoleApp.csproj b/src/PackageArchive/Scenario.ConsoleApp/Scenario.ConsoleApp.csproj new file mode 100644 index 0000000000..d5e6b40bed --- /dev/null +++ b/src/PackageArchive/Scenario.ConsoleApp/Scenario.ConsoleApp.csproj @@ -0,0 +1,17 @@ + + + + + 99.9 + netcoreapp3.0 + 3.0.0 + + $(MicrosoftNETCoreApp30PackageVersion) + $([MSbuild]::ValueOrDefault('$(NETCoreImplicitVersion)','$(MaxImplicitVersion)')) + + + + + + + diff --git a/src/PackageArchive/Scenario.WebApp/Scenario.WebApp.csproj b/src/PackageArchive/Scenario.WebApp/Scenario.WebApp.csproj new file mode 100644 index 0000000000..fddeb37cf2 --- /dev/null +++ b/src/PackageArchive/Scenario.WebApp/Scenario.WebApp.csproj @@ -0,0 +1,29 @@ + + + + + 99.9 + netcoreapp3.0 + 3.0.0 + + $(MicrosoftAspNetCoreAppPackageVersion) + $([MSBuild]::ValueOrDefault('$(AspNetCoreImplicitVersion)','$(MaxImplicitVersion)')) + + + + + + + + + + + + + + + + + + + diff --git a/src/PackageArchive/ZipManifestGenerator/Program.cs b/src/PackageArchive/ZipManifestGenerator/Program.cs new file mode 100644 index 0000000000..883d21b7c4 --- /dev/null +++ b/src/PackageArchive/ZipManifestGenerator/Program.cs @@ -0,0 +1,80 @@ +// 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.IO; +using System.IO.Compression; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; + +namespace ZipManifestGenerator +{ + class Program + { + private static void PrintUsage() + { + Console.WriteLine(@" +Usage: + + A file path or URL to the ZIP file. + The output file path for the ZIP manifest file."); + } + + public static async Task Main(string[] args) + { + if (args.Length != 2) + { + Console.Error.WriteLine("Invalid arguments"); + PrintUsage(); + return 1; + } + + var zipPath = args[0]; + var manifestOutputPath = args[1]; + + var shouldCleanupZip = false; + + if (zipPath.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + shouldCleanupZip = true; + var url = zipPath; + Console.WriteLine($"log: Downloading {url}"); + zipPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".zip"); + var response = await new HttpClient().GetAsync(url); + response.EnsureSuccessStatusCode(); + + using (var outStream = File.Create(zipPath)) + { + var responseStream = await response.Content.ReadAsStreamAsync(); + await responseStream.CopyToAsync(outStream); + } + } + + try + { + Console.WriteLine($"log: Generating manifest in {manifestOutputPath}"); + + using (var zipStream = File.OpenRead(zipPath)) + using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Read)) + using (var manifest = File.Create(manifestOutputPath)) + using (var writer = new StreamWriter(manifest)) + { + foreach (var file in zip.Entries.OrderBy(_ => _.FullName)) + { + writer.WriteLine(file.FullName.Replace("/", "\\")); + } + } + } + finally + { + if (shouldCleanupZip) + { + File.Delete(zipPath); + } + } + + return 0; + } + } +} diff --git a/src/PackageArchive/ZipManifestGenerator/README.md b/src/PackageArchive/ZipManifestGenerator/README.md new file mode 100644 index 0000000000..9922f2e465 --- /dev/null +++ b/src/PackageArchive/ZipManifestGenerator/README.md @@ -0,0 +1,31 @@ +ZipManifestGenerator +--------- + +This console app is used to generate the list of files in a zip archive. + +Usage: +``` +Usage: + + A file path or URL to the ZIP file. + The output file path for the ZIP manifest file. + +Example: dotnet run ./archive.zip files.txt +``` + +## Example for servicing updates + +To generate a new manifest for the incremental CI server package caches, you would run + +```ps1 +$ProdConBuild='20180919-01' +$Version='2.1.5' + +$patchUrl = "https://dotnetfeed.blob.core.windows.net/orchestrated-release-2-1/${ProdconBuild}/final/assets/aspnetcore/Runtime/${Version}/nuGetPackagesArchive-ci-server-${Version}.patch.zip" + +dotnet run $patchUrl "../Archive.CiServer.Patch/ArchiveBaseline.${Version}.txt" + +$compatPatchUrl = "https://dotnetfeed.blob.core.windows.net/orchestrated-release-2-1/${ProdconBuild}/final/assets/aspnetcore/Runtime/${Version}/nuGetPackagesArchive-ci-server-compat-${Version}.patch.zip" + +dotnet run $compatPatchUrl "../Archive.CiServer.Patch.Compat/ArchiveBaseline.${Version}.txt" +``` diff --git a/src/PackageArchive/ZipManifestGenerator/ZipManifestGenerator.csproj b/src/PackageArchive/ZipManifestGenerator/ZipManifestGenerator.csproj new file mode 100644 index 0000000000..b7d3a43622 --- /dev/null +++ b/src/PackageArchive/ZipManifestGenerator/ZipManifestGenerator.csproj @@ -0,0 +1,11 @@ + + + + exe + netcoreapp2.1 + false + 7.1 + false + + + diff --git a/src/PackageArchive/ZipManifestGenerator/ZipManifestGenerator.sln b/src/PackageArchive/ZipManifestGenerator/ZipManifestGenerator.sln new file mode 100644 index 0000000000..4651885a71 --- /dev/null +++ b/src/PackageArchive/ZipManifestGenerator/ZipManifestGenerator.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZipManifestGenerator", "ZipManifestGenerator.csproj", "{4706B37C-3B37-4331-84FC-107657BDEC4E}" +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(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Debug|x64.ActiveCfg = Debug|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Debug|x64.Build.0 = Debug|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Debug|x86.ActiveCfg = Debug|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Debug|x86.Build.0 = Debug|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Release|Any CPU.Build.0 = Release|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Release|x64.ActiveCfg = Release|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Release|x64.Build.0 = Release|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Release|x86.ActiveCfg = Release|Any CPU + {4706B37C-3B37-4331-84FC-107657BDEC4E}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/Packages/Directory.Build.props b/src/Packages/Directory.Build.props new file mode 100644 index 0000000000..02d2ee4d23 --- /dev/null +++ b/src/Packages/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Packages/Directory.Build.targets b/src/Packages/Directory.Build.targets new file mode 100644 index 0000000000..db9b73869a --- /dev/null +++ b/src/Packages/Directory.Build.targets @@ -0,0 +1,11 @@ + + + + + NuGetPackage + $(PackageId) + $(PackageVersion) + + + + diff --git a/src/Packages/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj b/src/Packages/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj new file mode 100644 index 0000000000..d53330052a --- /dev/null +++ b/src/Packages/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj @@ -0,0 +1,21 @@ + + + + false + false + netcoreapp3.0 + aspnetcore + false + Provides a default set of APIs for building an ASP.NET Core application, and also includes API for third-party integrations with ASP.NET Core. + +This package requires the ASP.NET Core runtime. This runtime is installed by the .NET Core SDK, or can be acquired separately using installers available at https://aka.ms/dotnet-download. + + + + + + + + + + diff --git a/src/Packages/Microsoft.AspNetCore.All/build/netcoreapp3.0/Microsoft.AspNetCore.All.props b/src/Packages/Microsoft.AspNetCore.All/build/netcoreapp3.0/Microsoft.AspNetCore.All.props new file mode 100644 index 0000000000..0295c8a39f --- /dev/null +++ b/src/Packages/Microsoft.AspNetCore.All/build/netcoreapp3.0/Microsoft.AspNetCore.All.props @@ -0,0 +1,19 @@ + + + + + <_AspNetCoreAppSharedFxIsEnabled>false + + + <_AspNetCoreAllSharedFxIsEnabled>true + + diff --git a/src/Packages/Microsoft.AspNetCore.All/build/netcoreapp3.0/Microsoft.AspNetCore.All.targets b/src/Packages/Microsoft.AspNetCore.All/build/netcoreapp3.0/Microsoft.AspNetCore.All.targets new file mode 100644 index 0000000000..c4f1f46390 --- /dev/null +++ b/src/Packages/Microsoft.AspNetCore.All/build/netcoreapp3.0/Microsoft.AspNetCore.All.targets @@ -0,0 +1,18 @@ + + + + Microsoft.AspNetCore.All + + + + + + diff --git a/src/Packages/Microsoft.AspNetCore.All/lib/netcoreapp3.0/_._ b/src/Packages/Microsoft.AspNetCore.All/lib/netcoreapp3.0/_._ new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Packages/Microsoft.AspNetCore.Analyzers/Microsoft.AspNetCore.Analyzers.csproj b/src/Packages/Microsoft.AspNetCore.Analyzers/Microsoft.AspNetCore.Analyzers.csproj new file mode 100644 index 0000000000..a9f9071719 --- /dev/null +++ b/src/Packages/Microsoft.AspNetCore.Analyzers/Microsoft.AspNetCore.Analyzers.csproj @@ -0,0 +1,18 @@ + + + + false + false + netstandard2.0 + aspnetcore + Microsoft.AspNetCore.Analyzers + + $(ExperimentalVersionPrefix) + $(ExperimentalVersionSuffix) + $(ExperimentalPackageVersion) + false + + false + + + diff --git a/src/Packages/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj b/src/Packages/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj new file mode 100644 index 0000000000..696eb182db --- /dev/null +++ b/src/Packages/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj @@ -0,0 +1,21 @@ + + + + false + false + netcoreapp3.0 + aspnetcore + false + Provides a default set of APIs for building an ASP.NET Core application. + +This package requires the ASP.NET Core runtime. This runtime is installed by the .NET Core SDK, or can be acquired separately using installers available at https://aka.ms/dotnet-download. + + + + + + + + + + diff --git a/src/Packages/Microsoft.AspNetCore.App/build/netcoreapp3.0/Microsoft.AspNetCore.App.props b/src/Packages/Microsoft.AspNetCore.App/build/netcoreapp3.0/Microsoft.AspNetCore.App.props new file mode 100644 index 0000000000..b68699c5b3 --- /dev/null +++ b/src/Packages/Microsoft.AspNetCore.App/build/netcoreapp3.0/Microsoft.AspNetCore.App.props @@ -0,0 +1,21 @@ + + + + <_AspNetCoreAppSharedFxIsEnabled Condition=" '$(_AspNetCoreAppSharedFxIsEnabled)' == '' ">true + + + + + + + + diff --git a/src/Packages/Microsoft.AspNetCore.App/build/netcoreapp3.0/Microsoft.AspNetCore.App.targets b/src/Packages/Microsoft.AspNetCore.App/build/netcoreapp3.0/Microsoft.AspNetCore.App.targets new file mode 100644 index 0000000000..2e222008cc --- /dev/null +++ b/src/Packages/Microsoft.AspNetCore.App/build/netcoreapp3.0/Microsoft.AspNetCore.App.targets @@ -0,0 +1,18 @@ + + + + Microsoft.AspNetCore.App + + + + + + diff --git a/src/Packages/Microsoft.AspNetCore.App/lib/netcoreapp3.0/_._ b/src/Packages/Microsoft.AspNetCore.App/lib/netcoreapp3.0/_._ new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Cli.FunctionalTests/AssemblyInfo.cs b/test/Cli.FunctionalTests/AssemblyInfo.cs new file mode 100644 index 0000000000..cbe539e977 --- /dev/null +++ b/test/Cli.FunctionalTests/AssemblyInfo.cs @@ -0,0 +1,26 @@ +// 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 Cli.FunctionalTests.Util; +using NUnit.Framework; + +// Run all test cases in parallel +[assembly: Parallelizable(ParallelScope.Children)] + +[SetUpFixture] +public class AssemblySetUp +{ + public static string TempDir { get; private set; } + + [OneTimeSetUp] + public void SetUp() + { + TempDir = IOUtil.GetTempDir(); + } + + [OneTimeTearDown] + public void TearDown() + { + IOUtil.DeleteDir(TempDir); + } +} diff --git a/test/Cli.FunctionalTests/Cli.FunctionalTests.csproj b/test/Cli.FunctionalTests/Cli.FunctionalTests.csproj new file mode 100644 index 0000000000..b2227fad1e --- /dev/null +++ b/test/Cli.FunctionalTests/Cli.FunctionalTests.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp2.1 + false + latest + + https://api.nuget.org/v3/index.json; + + + + + + + + + + + + diff --git a/test/Cli.FunctionalTests/Cli.FunctionalTests.sln b/test/Cli.FunctionalTests/Cli.FunctionalTests.sln new file mode 100644 index 0000000000..82d40614d1 --- /dev/null +++ b/test/Cli.FunctionalTests/Cli.FunctionalTests.sln @@ -0,0 +1,30 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28016.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cli.FunctionalTests", "Cli.FunctionalTests.csproj", "{D44EA496-EF83-4D47-8C45-4DAF5A1B0070}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0EC88B4E-B1F2-4183-9EBF-BF66C45D19D7}" + ProjectSection(SolutionItems) = preProject + ..\..\.azure\pipelines\e2e-tests.yml = ..\..\.azure\pipelines\e2e-tests.yml + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D44EA496-EF83-4D47-8C45-4DAF5A1B0070}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D44EA496-EF83-4D47-8C45-4DAF5A1B0070}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D44EA496-EF83-4D47-8C45-4DAF5A1B0070}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D44EA496-EF83-4D47-8C45-4DAF5A1B0070}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {70432DA7-DCE4-4F73-A00C-E1AB180DDD6A} + EndGlobalSection +EndGlobal diff --git a/test/Cli.FunctionalTests/Directory.Build.props b/test/Cli.FunctionalTests/Directory.Build.props new file mode 100644 index 0000000000..6d087b3032 --- /dev/null +++ b/test/Cli.FunctionalTests/Directory.Build.props @@ -0,0 +1,2 @@ + + diff --git a/test/Cli.FunctionalTests/Directory.Build.rsp b/test/Cli.FunctionalTests/Directory.Build.rsp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Cli.FunctionalTests/Directory.Build.targets b/test/Cli.FunctionalTests/Directory.Build.targets new file mode 100644 index 0000000000..6d087b3032 --- /dev/null +++ b/test/Cli.FunctionalTests/Directory.Build.targets @@ -0,0 +1,2 @@ + + diff --git a/test/Cli.FunctionalTests/NuGet.config b/test/Cli.FunctionalTests/NuGet.config new file mode 100644 index 0000000000..4bb3170917 --- /dev/null +++ b/test/Cli.FunctionalTests/NuGet.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/test/Cli.FunctionalTests/NuGetPackageSource.cs b/test/Cli.FunctionalTests/NuGetPackageSource.cs new file mode 100644 index 0000000000..e1bbce195a --- /dev/null +++ b/test/Cli.FunctionalTests/NuGetPackageSource.cs @@ -0,0 +1,60 @@ +// 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; + +namespace Cli.FunctionalTests +{ + public class NuGetPackageSource + { + public static NuGetPackageSource None { get; } = new NuGetPackageSource + { + Name = nameof(None), + SourceArgumentLazy = new Lazy(string.Empty), + }; + + public static NuGetPackageSource NuGetOrg { get; } = new NuGetPackageSource + { + Name = nameof(NuGetOrg), + SourceArgumentLazy = new Lazy("--source https://api.nuget.org/v3/index.json"), + }; + + public static NuGetPackageSource DotNetCore { get; } = new NuGetPackageSource + { + Name = nameof(DotNetCore), + SourceArgumentLazy = new Lazy("--source https://dotnet.myget.org/F/dotnet-core/api/v3/index.json"), + }; + + public static NuGetPackageSource EnvironmentVariable { get; } = new NuGetPackageSource + { + Name = nameof(EnvironmentVariable), + SourceArgumentLazy = new Lazy(() => GetSourceArgumentFromEnvironment()), + }; + + public static NuGetPackageSource EnvironmentVariableAndNuGetOrg { get; } = new NuGetPackageSource + { + Name = nameof(EnvironmentVariableAndNuGetOrg), + SourceArgumentLazy = new Lazy(() => string.Join(" ", EnvironmentVariable.SourceArgument, NuGetOrg.SourceArgument)), + }; + + private NuGetPackageSource() { } + + public string Name { get; private set; } + public string SourceArgument => SourceArgumentLazy.Value; + private Lazy SourceArgumentLazy { get; set; } + + public override string ToString() => Name; + + private static string GetSourceArgumentFromEnvironment() + { + var sourceString = Environment.GetEnvironmentVariable("NUGET_PACKAGE_SOURCE") ?? + throw new InvalidOperationException("Environment variable NUGET_PACKAGE_SOURCE is required but not set"); + + // Split on pipe and remove blank entries + var sources = sourceString.Split('|').Where(s => !string.IsNullOrWhiteSpace(s)); + + return string.Join(" ", sources.Select(s => $"--source {s}")); + } + } +} diff --git a/test/Cli.FunctionalTests/README.md b/test/Cli.FunctionalTests/README.md new file mode 100644 index 0000000000..4587c251c1 --- /dev/null +++ b/test/Cli.FunctionalTests/README.md @@ -0,0 +1,5 @@ +# Cli.FunctionalTests + +This folder contains tests for ASP.NET Core scenarios in the .NET Core CLI. + +This tests in this folder is meant to be kept in isolation from the rest of the repo, and are not invoked during the course of a regular build. diff --git a/test/Cli.FunctionalTests/RuntimeIdentifier.cs b/test/Cli.FunctionalTests/RuntimeIdentifier.cs new file mode 100644 index 0000000000..7e638a6935 --- /dev/null +++ b/test/Cli.FunctionalTests/RuntimeIdentifier.cs @@ -0,0 +1,55 @@ +// 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.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Cli.FunctionalTests +{ + // https://docs.microsoft.com/en-us/dotnet/core/rid-catalog + public class RuntimeIdentifier + { + public static RuntimeIdentifier None = new RuntimeIdentifier() { + Name = "none", + OSPlatforms = new[] { OSPlatform.Linux, OSPlatform.OSX, OSPlatform.Windows, }, + }; + + public static RuntimeIdentifier Linux_x64 = new RuntimeIdentifier() { + Name = "linux-x64", + OSPlatforms = new[] { OSPlatform.Linux, }, + ExecutableFileExtension = string.Empty, + }; + + public static RuntimeIdentifier OSX_x64 = new RuntimeIdentifier() + { + Name = "osx-x64", + OSPlatforms = new[] { OSPlatform.OSX, }, + ExecutableFileExtension = string.Empty, + }; + + public static RuntimeIdentifier Win_x64 = new RuntimeIdentifier() + { + Name = "win-x64", + OSPlatforms = new[] { OSPlatform.Windows, }, + ExecutableFileExtension = ".exe", + }; + + public static IEnumerable All = new[] + { + RuntimeIdentifier.None, + RuntimeIdentifier.Linux_x64, + RuntimeIdentifier.OSX_x64, + RuntimeIdentifier.Win_x64, + }; + + private RuntimeIdentifier() { } + + public string Name { get; private set; } + public string RuntimeArgument => (this == None) ? string.Empty : $"--runtime {Name}"; + public string Path => (this == None) ? string.Empty : Name; + public IEnumerable OSPlatforms { get; private set; } + public string ExecutableFileExtension { get; private set; } + + public override string ToString() => Name; + } +} diff --git a/test/Cli.FunctionalTests/TemplateTests.cs b/test/Cli.FunctionalTests/TemplateTests.cs new file mode 100644 index 0000000000..7e8143114f --- /dev/null +++ b/test/Cli.FunctionalTests/TemplateTests.cs @@ -0,0 +1,220 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Net; +using System.Runtime.InteropServices; +using Cli.FunctionalTests.Templates; +using Cli.FunctionalTests.Util; +using NuGet.Versioning; +using NUnit.Framework; + +namespace Cli.FunctionalTests +{ + [TestFixture] + public class TemplateTests + { + [Test] + [TestCaseSource(nameof(RestoreData))] + public void _1_Restore(Template template) + { + var expected = template.ExpectedObjFilesAfterRestore; + var actual = template.ObjFilesAfterRestore; + CollectionAssert.AreEquivalent(expected, actual); + } + + [Test] + [TestCaseSource(nameof(RestoreData))] + public void _2_RestoreIncremental(Template template) + { + var expected = template.ExpectedObjFilesAfterRestore; + var actual = template.ObjFilesAfterRestoreIncremental; + CollectionAssert.AreEquivalent(expected, actual); + } + + [Test] + [TestCaseSource(nameof(BuildData))] + public void _3_Build(Template template) + { + var expectedObj = template.ExpectedObjFilesAfterBuild; + var actualObj = template.ObjFilesAfterBuild; + CollectionAssert.AreEquivalent(expectedObj, actualObj); + + var expectedBin = template.ExpectedBinFilesAfterBuild; + var actualBin = template.BinFilesAfterBuild; + CollectionAssert.AreEquivalent(expectedBin, actualBin); + } + + [Test] + [TestCaseSource(nameof(BuildData))] + public void _4_BuildIncremental(Template template) + { + var expectedObj = template.ExpectedObjFilesAfterBuild; + var actualObj = template.ObjFilesAfterBuildIncremental; + CollectionAssert.AreEquivalent(expectedObj, actualObj); + + var expectedBin = template.ExpectedBinFilesAfterBuild; + var actualBin = template.BinFilesAfterBuildIncremental; + CollectionAssert.AreEquivalent(expectedBin, actualBin); + } + + [Test] + [TestCaseSource(nameof(RunData))] + public void _5_Run(Template template) + { + var statusCode = template.HttpResponseAfterRun.StatusCode; + Assert.AreEqual(HttpStatusCode.OK, statusCode, + GetMessage(statusCode, template.ServerOutputAfterRun, template.ServerErrorAfterRun)); + + statusCode = template.HttpsResponseAfterRun.StatusCode; + Assert.AreEqual(HttpStatusCode.OK, statusCode, + GetMessage(statusCode, template.ServerOutputAfterRun, template.ServerErrorAfterRun)); + } + + [NonParallelizable] + [Test] + [TestCaseSource(nameof(RunNonParallelizableData))] + public void _5_RunNonParallelizable(Template template) + { + _5_Run(template); + } + + [Test] + [TestCaseSource(nameof(PublishData))] + public void _6_Publish(Template template) + { + var expected = template.ExpectedFilesAfterPublish; + var actual = template.FilesAfterPublish; + CollectionAssert.AreEquivalent(expected, actual); + } + + [Test] + [TestCaseSource(nameof(PublishData))] + public void _7_PublishIncremental(Template template) + { + var expected = template.ExpectedFilesAfterPublish; + var actual = template.FilesAfterPublishIncremental; + CollectionAssert.AreEquivalent(expected, actual); + } + + [Test] + [TestCaseSource(nameof(ExecData))] + public void _8_Exec(Template template) + { + var statusCode = template.HttpResponseAfterExec.StatusCode; + Assert.AreEqual(HttpStatusCode.OK, statusCode, + GetMessage(statusCode, template.ServerOutputAfterExec, template.ServerErrorAfterExec)); + + statusCode = template.HttpsResponseAfterExec.StatusCode; + Assert.AreEqual(HttpStatusCode.OK, statusCode, + GetMessage(statusCode, template.ServerOutputAfterExec, template.ServerErrorAfterExec)); + } + + private static string GetMessage(HttpStatusCode statusCode, string serverOutput, string serverError) + { + return String.Join(Environment.NewLine, + $"StatusCode: {statusCode}", + string.Empty, + "ServerOutput", + "------------", + serverOutput, + string.Empty, + "ServerError", + "------------", + serverError); + } + + private static IEnumerable