diff options
| author | Rob Mensching <rob@firegiant.com> | 2021-05-11 08:05:16 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2021-05-11 08:05:16 -0700 |
| commit | 400d3eaae96f9cf9d15b448240b944473964ee31 (patch) | |
| tree | d2fa7d0e7e246da1b748136f152018d019411709 /src | |
| parent | e835776f17056097559c13f25b4c875c7361bd5b (diff) | |
| parent | 7c8e34de56b3348c5a421cd0cced183e1394c5c7 (diff) | |
| download | wix-400d3eaae96f9cf9d15b448240b944473964ee31.tar.gz wix-400d3eaae96f9cf9d15b448240b944473964ee31.tar.bz2 wix-400d3eaae96f9cf9d15b448240b944473964ee31.zip | |
Merge Iis.wixext
Diffstat (limited to 'src')
141 files changed, 26478 insertions, 0 deletions
diff --git a/src/ext/Iis/CSharp.Build.props b/src/ext/Iis/CSharp.Build.props new file mode 100644 index 00000000..b12f4c6e --- /dev/null +++ b/src/ext/Iis/CSharp.Build.props | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | <!-- | ||
| 3 | Do NOT modify this file. Update the canonical version in Home\repo-template\src\CSharp.Build.props | ||
| 4 | then update all of the repos. | ||
| 5 | --> | ||
| 6 | <Project> | ||
| 7 | <PropertyGroup> | ||
| 8 | <SignAssembly>true</SignAssembly> | ||
| 9 | <AssemblyOriginatorKeyFile>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk))</AssemblyOriginatorKeyFile> | ||
| 10 | </PropertyGroup> | ||
| 11 | </Project> | ||
diff --git a/src/ext/Iis/Cpp.Build.props b/src/ext/Iis/Cpp.Build.props new file mode 100644 index 00000000..9b7a1bb5 --- /dev/null +++ b/src/ext/Iis/Cpp.Build.props | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | <Project> | ||
| 5 | <PropertyGroup> | ||
| 6 | <Platform Condition=" '$(Platform)' == '' OR '$(Platform)' == 'AnyCPU' ">Win32</Platform> | ||
| 7 | <IntDir>$(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\</IntDir> | ||
| 8 | <OutDir>$(OutputPath)$(Platform)\</OutDir> | ||
| 9 | </PropertyGroup> | ||
| 10 | |||
| 11 | <PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'=='' AND '$(VisualStudioVersion)'>='15.0'"> | ||
| 12 | <WindowsTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</WindowsTargetPlatformVersion> | ||
| 13 | </PropertyGroup> | ||
| 14 | |||
| 15 | <ItemDefinitionGroup> | ||
| 16 | <ClCompile> | ||
| 17 | <DisableSpecificWarnings>$(DisableSpecificCompilerWarnings)</DisableSpecificWarnings> | ||
| 18 | <WarningLevel>Level4</WarningLevel> | ||
| 19 | <AdditionalIncludeDirectories>$(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||
| 20 | <PreprocessorDefinitions>WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
| 21 | <PrecompiledHeader>Use</PrecompiledHeader> | ||
| 22 | <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile> | ||
| 23 | <CallingConvention Condition="'$(Platform)'=='Win32'">StdCall</CallingConvention> | ||
| 24 | <TreatWarningAsError>true</TreatWarningAsError> | ||
| 25 | <ExceptionHandling>false</ExceptionHandling> | ||
| 26 | <AdditionalOptions>-YlprecompDefine</AdditionalOptions> | ||
| 27 | <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions> | ||
| 28 | <MultiProcessorCompilation Condition=" $(NUMBER_OF_PROCESSORS) > 4 ">true</MultiProcessorCompilation> | ||
| 29 | </ClCompile> | ||
| 30 | <ResourceCompile> | ||
| 31 | <PreprocessorDefinitions>$(ArmPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
| 32 | <AdditionalIncludeDirectories>$(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||
| 33 | </ResourceCompile> | ||
| 34 | <Lib> | ||
| 35 | <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> | ||
| 36 | </Lib> | ||
| 37 | <Link> | ||
| 38 | <SubSystem>$(ProjectSubSystem)</SubSystem> | ||
| 39 | <ModuleDefinitionFile>$(ProjectModuleDefinitionFile)</ModuleDefinitionFile> | ||
| 40 | <NoEntryPoint>$(ResourceOnlyDll)</NoEntryPoint> | ||
| 41 | <GenerateDebugInformation>true</GenerateDebugInformation> | ||
| 42 | <AdditionalDependencies>$(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies> | ||
| 43 | <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> | ||
| 44 | <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions> | ||
| 45 | </Link> | ||
| 46 | </ItemDefinitionGroup> | ||
| 47 | |||
| 48 | <ItemDefinitionGroup Condition=" '$(Platform)'=='Win32' and '$(PlatformToolset)'!='v100'"> | ||
| 49 | <ClCompile> | ||
| 50 | <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> | ||
| 51 | </ClCompile> | ||
| 52 | </ItemDefinitionGroup> | ||
| 53 | <ItemDefinitionGroup Condition=" '$(Platform)'=='arm' "> | ||
| 54 | <ClCompile> | ||
| 55 | <CallingConvention>CDecl</CallingConvention> | ||
| 56 | </ClCompile> | ||
| 57 | </ItemDefinitionGroup> | ||
| 58 | <ItemDefinitionGroup Condition=" '$(ConfigurationType)'=='StaticLibrary' "> | ||
| 59 | <ClCompile> | ||
| 60 | <DebugInformationFormat>OldStyle</DebugInformationFormat> | ||
| 61 | <OmitDefaultLibName>true</OmitDefaultLibName> | ||
| 62 | <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> | ||
| 63 | </ClCompile> | ||
| 64 | </ItemDefinitionGroup> | ||
| 65 | <ItemDefinitionGroup Condition=" '$(Configuration)'=='Debug' "> | ||
| 66 | <ClCompile> | ||
| 67 | <Optimization>Disabled</Optimization> | ||
| 68 | <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> | ||
| 69 | <PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
| 70 | <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> | ||
| 71 | </ClCompile> | ||
| 72 | </ItemDefinitionGroup> | ||
| 73 | <ItemDefinitionGroup Condition=" '$(Configuration)'=='Release' "> | ||
| 74 | <ClCompile> | ||
| 75 | <Optimization>MinSpace</Optimization> | ||
| 76 | <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
| 77 | <FunctionLevelLinking>true</FunctionLevelLinking> | ||
| 78 | <IntrinsicFunctions>true</IntrinsicFunctions> | ||
| 79 | <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | ||
| 80 | </ClCompile> | ||
| 81 | <Link> | ||
| 82 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | ||
| 83 | <OptimizeReferences>true</OptimizeReferences> | ||
| 84 | </Link> | ||
| 85 | </ItemDefinitionGroup> | ||
| 86 | </Project> | ||
diff --git a/src/ext/Iis/Directory.Build.props b/src/ext/Iis/Directory.Build.props new file mode 100644 index 00000000..f83cc154 --- /dev/null +++ b/src/ext/Iis/Directory.Build.props | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | <!-- | ||
| 4 | Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.props | ||
| 5 | then update all of the repos. | ||
| 6 | --> | ||
| 7 | <Project> | ||
| 8 | <PropertyGroup> | ||
| 9 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||
| 10 | <EnableSourceLink Condition=" '$(NCrunch)' == '1' ">false</EnableSourceLink> | ||
| 11 | <MSBuildWarningsAsMessages>MSB3246</MSBuildWarningsAsMessages> | ||
| 12 | |||
| 13 | <ProjectName Condition=" '$(ProjectName)' == '' ">$(MSBuildProjectName)</ProjectName> | ||
| 14 | <BaseOutputPath>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))</BaseOutputPath> | ||
| 15 | <BaseIntermediateOutputPath>$(BaseOutputPath)obj\$(ProjectName)\</BaseIntermediateOutputPath> | ||
| 16 | <OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath> | ||
| 17 | |||
| 18 | <Authors>WiX Toolset Team</Authors> | ||
| 19 | <Company>WiX Toolset</Company> | ||
| 20 | <Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright> | ||
| 21 | <PackageLicenseExpression>MS-RL</PackageLicenseExpression> | ||
| 22 | <Product>WiX Toolset</Product> | ||
| 23 | </PropertyGroup> | ||
| 24 | |||
| 25 | <Import Project="CSharp.Build.props" Condition=" '$(MSBuildProjectExtension)'=='.csproj' and Exists('CSharp.Build.props') " /> | ||
| 26 | <Import Project="Cpp.Build.props" Condition=" Exists('Cpp.Build.props') And '$(MSBuildProjectExtension)'=='.vcxproj' " /> | ||
| 27 | <Import Project="Wix.Build.props" Condition=" Exists('Wix.Build.props') And '$(MSBuildProjectExtension)'=='.wixproj' " /> | ||
| 28 | <Import Project="Custom.Build.props" Condition=" Exists('Custom.Build.props') " /> | ||
| 29 | </Project> | ||
diff --git a/src/ext/Iis/Directory.Build.targets b/src/ext/Iis/Directory.Build.targets new file mode 100644 index 00000000..dac7452a --- /dev/null +++ b/src/ext/Iis/Directory.Build.targets | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | <!-- | ||
| 4 | Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.targets | ||
| 5 | then update all of the repos. | ||
| 6 | --> | ||
| 7 | <!-- | ||
| 8 | Replace PackageReferences with ProjectReferences when the projects can be found in .sln. | ||
| 9 | See the original here: https://github.com/dotnet/sdk/issues/1151#issuecomment-385133284 | ||
| 10 | --> | ||
| 11 | <Project> | ||
| 12 | <PropertyGroup> | ||
| 13 | <ReplacePackageReferences>true</ReplacePackageReferences> | ||
| 14 | <TheSolutionPath Condition=" '$(NCrunch)'=='' ">$(SolutionPath)</TheSolutionPath> | ||
| 15 | <TheSolutionPath Condition=" '$(NCrunch)'=='1' ">$(NCrunchOriginalSolutionPath)</TheSolutionPath> | ||
| 16 | </PropertyGroup> | ||
| 17 | |||
| 18 | <Choose> | ||
| 19 | <When Condition="$(ReplacePackageReferences) AND '$(TheSolutionPath)' != '' AND '$(TheSolutionPath)' != '*undefined*' AND Exists('$(TheSolutionPath)')"> | ||
| 20 | |||
| 21 | <PropertyGroup> | ||
| 22 | <SolutionFileContent>$([System.IO.File]::ReadAllText($(TheSolutionPath)))</SolutionFileContent> | ||
| 23 | <SmartSolutionDir>$([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) ))</SmartSolutionDir> | ||
| 24 | <RegexPattern>(?<="[PackageName]", ")(.*)(?=", ")</RegexPattern> | ||
| 25 | </PropertyGroup> | ||
| 26 | |||
| 27 | <ItemGroup> | ||
| 28 | <!-- Keep the identity of the PackageReference --> | ||
| 29 | <SmartPackageReference Include="@(PackageReference)"> | ||
| 30 | <PackageName>%(Identity)</PackageName> | ||
| 31 | <InSolution>$(SolutionFileContent.Contains('\%(Identity).csproj'))</InSolution> | ||
| 32 | </SmartPackageReference> | ||
| 33 | |||
| 34 | <!-- Filter them by mapping them to another ItemGroup using the WithMetadataValue item function --> | ||
| 35 | <PackageInSolution Include="@(SmartPackageReference->WithMetadataValue('InSolution', True))"> | ||
| 36 | <Pattern>$(RegexPattern.Replace('[PackageName]','%(PackageName)') )</Pattern> | ||
| 37 | <SmartPath>$([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)'))</SmartPath> | ||
| 38 | </PackageInSolution> | ||
| 39 | |||
| 40 | <ProjectReference Include="@(PackageInSolution->'$(SmartSolutionDir)\%(SmartPath)' )"/> | ||
| 41 | |||
| 42 | <!-- Remove the package references that are now referenced as projects --> | ||
| 43 | <PackageReference Remove="@(PackageInSolution->'%(PackageName)' )"/> | ||
| 44 | </ItemGroup> | ||
| 45 | |||
| 46 | </When> | ||
| 47 | </Choose> | ||
| 48 | </Project> | ||
diff --git a/src/ext/Iis/Iis.wixext.sln b/src/ext/Iis/Iis.wixext.sln new file mode 100644 index 00000000..85323fde --- /dev/null +++ b/src/ext/Iis/Iis.wixext.sln | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | | ||
| 2 | Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| 3 | # Visual Studio Version 16 | ||
| 4 | VisualStudioVersion = 16.0.30204.135 | ||
| 5 | MinimumVisualStudioVersion = 10.0.40219.1 | ||
| 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iisca", "src\ca\iisca.vcxproj", "{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}" | ||
| 7 | EndProject | ||
| 8 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "iis", "src\wixlib\iis.wixproj", "{92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}" | ||
| 9 | EndProject | ||
| 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Iis.wixext", "src\wixext\WixToolset.Iis.wixext.csproj", "{612029FB-B5D4-4D7E-B794-A0E202BFE493}" | ||
| 11 | EndProject | ||
| 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Iis", "src\test\WixToolsetTest.Iis\WixToolsetTest.Iis.csproj", "{E62712D7-31A1-49E4-B1F4-0084FAD14193}" | ||
| 13 | EndProject | ||
| 14 | Global | ||
| 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| 16 | Debug|Any CPU = Debug|Any CPU | ||
| 17 | Debug|x86 = Debug|x86 | ||
| 18 | Release|Any CPU = Release|Any CPU | ||
| 19 | Release|x86 = Release|x86 | ||
| 20 | EndGlobalSection | ||
| 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| 22 | {CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Debug|Any CPU.ActiveCfg = Debug|Win32 | ||
| 23 | {CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Debug|Any CPU.Build.0 = Debug|Win32 | ||
| 24 | {CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Debug|x86.ActiveCfg = Debug|Win32 | ||
| 25 | {CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Debug|x86.Build.0 = Debug|Win32 | ||
| 26 | {CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Release|Any CPU.ActiveCfg = Release|Win32 | ||
| 27 | {CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Release|x86.ActiveCfg = Release|Win32 | ||
| 28 | {CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Release|x86.Build.0 = Release|Win32 | ||
| 29 | {92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Debug|Any CPU.ActiveCfg = Debug|x86 | ||
| 30 | {92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Debug|x86.ActiveCfg = Debug|x86 | ||
| 31 | {92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Debug|x86.Build.0 = Debug|x86 | ||
| 32 | {92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Release|Any CPU.ActiveCfg = Release|x86 | ||
| 33 | {92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Release|x86.ActiveCfg = Release|x86 | ||
| 34 | {92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Release|x86.Build.0 = Release|x86 | ||
| 35 | {612029FB-B5D4-4D7E-B794-A0E202BFE493}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| 36 | {612029FB-B5D4-4D7E-B794-A0E202BFE493}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| 37 | {612029FB-B5D4-4D7E-B794-A0E202BFE493}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
| 38 | {612029FB-B5D4-4D7E-B794-A0E202BFE493}.Debug|x86.Build.0 = Debug|Any CPU | ||
| 39 | {612029FB-B5D4-4D7E-B794-A0E202BFE493}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| 40 | {612029FB-B5D4-4D7E-B794-A0E202BFE493}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| 41 | {612029FB-B5D4-4D7E-B794-A0E202BFE493}.Release|x86.ActiveCfg = Release|Any CPU | ||
| 42 | {612029FB-B5D4-4D7E-B794-A0E202BFE493}.Release|x86.Build.0 = Release|Any CPU | ||
| 43 | {E62712D7-31A1-49E4-B1F4-0084FAD14193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| 44 | {E62712D7-31A1-49E4-B1F4-0084FAD14193}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| 45 | {E62712D7-31A1-49E4-B1F4-0084FAD14193}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
| 46 | {E62712D7-31A1-49E4-B1F4-0084FAD14193}.Debug|x86.Build.0 = Debug|Any CPU | ||
| 47 | {E62712D7-31A1-49E4-B1F4-0084FAD14193}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| 48 | {E62712D7-31A1-49E4-B1F4-0084FAD14193}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| 49 | {E62712D7-31A1-49E4-B1F4-0084FAD14193}.Release|x86.ActiveCfg = Release|Any CPU | ||
| 50 | {E62712D7-31A1-49E4-B1F4-0084FAD14193}.Release|x86.Build.0 = Release|Any CPU | ||
| 51 | EndGlobalSection | ||
| 52 | GlobalSection(SolutionProperties) = preSolution | ||
| 53 | HideSolutionNode = FALSE | ||
| 54 | EndGlobalSection | ||
| 55 | GlobalSection(ExtensibilityGlobals) = postSolution | ||
| 56 | SolutionGuid = {89256463-14A3-4968-8688-F75EC230B021} | ||
| 57 | EndGlobalSection | ||
| 58 | EndGlobal | ||
diff --git a/src/ext/Iis/README.md b/src/ext/Iis/README.md new file mode 100644 index 00000000..ddb21a82 --- /dev/null +++ b/src/ext/Iis/README.md | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | # Iis.wixext | ||
| 2 | WixToolset.Iis.wixext - Iis WiX Toolset Extension | ||
diff --git a/src/ext/Iis/appveyor.cmd b/src/ext/Iis/appveyor.cmd new file mode 100644 index 00000000..af993a8f --- /dev/null +++ b/src/ext/Iis/appveyor.cmd | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | @setlocal | ||
| 2 | @pushd %~dp0 | ||
| 3 | |||
| 4 | nuget restore || exit /b | ||
| 5 | |||
| 6 | msbuild -p:Configuration=Release -t:Restore || exit /b | ||
| 7 | |||
| 8 | msbuild -p:Configuration=Release src\test\WixToolsetTest.Iis\WixToolsetTest.Iis.csproj || exit /b | ||
| 9 | dotnet test -c Release --no-build src\test\WixToolsetTest.Iis || exit /b | ||
| 10 | |||
| 11 | msbuild -p:Configuration=Release -t:Pack src\wixext\WixToolset.Iis.wixext.csproj || exit /b | ||
| 12 | |||
| 13 | @popd | ||
| 14 | @endlocal \ No newline at end of file | ||
diff --git a/src/ext/Iis/appveyor.yml b/src/ext/Iis/appveyor.yml new file mode 100644 index 00000000..7c686b04 --- /dev/null +++ b/src/ext/Iis/appveyor.yml | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | # Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | # | ||
| 3 | # Do NOT modify this file. Update the canonical version in Home\repo-template\src\appveyor.yml | ||
| 4 | # then update all of the repos. | ||
| 5 | |||
| 6 | branches: | ||
| 7 | only: | ||
| 8 | - master | ||
| 9 | - develop | ||
| 10 | |||
| 11 | image: Visual Studio 2019 | ||
| 12 | |||
| 13 | version: 0.0.0.{build} | ||
| 14 | configuration: Release | ||
| 15 | |||
| 16 | environment: | ||
| 17 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | ||
| 18 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 | ||
| 19 | NUGET_XMLDOC_MODE: skip | ||
| 20 | |||
| 21 | build_script: | ||
| 22 | - appveyor.cmd | ||
| 23 | |||
| 24 | pull_requests: | ||
| 25 | do_not_increment_build_number: true | ||
| 26 | |||
| 27 | nuget: | ||
| 28 | disable_publish_on_pr: true | ||
| 29 | |||
| 30 | skip_branch_with_pr: true | ||
| 31 | skip_tags: true | ||
| 32 | |||
| 33 | artifacts: | ||
| 34 | - path: build\Release\**\*.nupkg | ||
| 35 | name: nuget | ||
| 36 | |||
| 37 | notifications: | ||
| 38 | - provider: Slack | ||
| 39 | incoming_webhook: | ||
| 40 | secure: p5xuu+4x2JHfwGDMDe5KcG1k7gZxqYc4jWVwvyNZv5cvkubPD2waJs5yXMAXZNN7Z63/3PWHb7q4KoY/99AjauYa1nZ4c5qYqRPFRBKTHfA= | ||
diff --git a/src/ext/Iis/ca/CustomMsiErrors.h b/src/ext/Iis/ca/CustomMsiErrors.h new file mode 100644 index 00000000..1fd8d050 --- /dev/null +++ b/src/ext/Iis/ca/CustomMsiErrors.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | #define msierrIISCannotConnect 26001 | ||
| 5 | #define msierrIISFailedReadWebSite 26002 | ||
| 6 | #define msierrIISFailedReadWebDirs 26003 | ||
| 7 | #define msierrIISFailedReadVDirs 26004 | ||
| 8 | #define msierrIISFailedReadFilters 26005 | ||
| 9 | #define msierrIISFailedReadAppPool 26006 | ||
| 10 | #define msierrIISFailedReadMimeMap 26007 | ||
| 11 | #define msierrIISFailedReadProp 26008 | ||
| 12 | #define msierrIISFailedReadWebSvcExt 26009 | ||
| 13 | #define msierrIISFailedReadWebError 26010 | ||
| 14 | #define msierrIISFailedReadHttpHeader 26011 | ||
| 15 | |||
| 16 | #define msierrIISFailedSchedTransaction 26031 | ||
| 17 | #define msierrIISFailedSchedInstallWebs 26032 | ||
| 18 | #define msierrIISFailedSchedInstallWebDirs 26033 | ||
| 19 | #define msierrIISFailedSchedInstallVDirs 26034 | ||
| 20 | #define msierrIISFailedSchedInstallFilters 26035 | ||
| 21 | #define msierrIISFailedSchedInstallAppPool 26036 | ||
| 22 | #define msierrIISFailedSchedInstallProp 26037 | ||
| 23 | #define msierrIISFailedSchedInstallWebSvcExt 26038 | ||
| 24 | |||
| 25 | #define msierrIISFailedSchedUninstallWebs 26051 | ||
| 26 | #define msierrIISFailedSchedUninstallWebDirs 26052 | ||
| 27 | #define msierrIISFailedSchedUninstallVDirs 26053 | ||
| 28 | #define msierrIISFailedSchedUninstallFilters 26054 | ||
| 29 | #define msierrIISFailedSchedUninstallAppPool 26055 | ||
| 30 | #define msierrIISFailedSchedUninstallProp 26056 | ||
| 31 | #define msierrIISFailedSchedUninstallWebSvcExt 26057 | ||
| 32 | |||
| 33 | #define msierrIISFailedStartTransaction 26101 | ||
| 34 | #define msierrIISFailedOpenKey 26102 | ||
| 35 | #define msierrIISFailedCreateKey 26103 | ||
| 36 | #define msierrIISFailedWriteData 26104 | ||
| 37 | #define msierrIISFailedCreateApp 26105 | ||
| 38 | #define msierrIISFailedDeleteKey 26106 | ||
| 39 | #define msierrIISFailedDeleteApp 26107 | ||
| 40 | #define msierrIISFailedDeleteValue 26108 | ||
| 41 | #define msierrIISFailedCommitInUse 26109 | ||
| 42 | |||
| 43 | // Last available value 26200 | ||
| 44 | |||
| 45 | #define msierrCERTFailedOpen 26351 | ||
| 46 | #define msierrCERTFailedAdd 26352 | ||
| 47 | |||
| 48 | // Last available value 26450 | ||
diff --git a/src/ext/Iis/ca/caDecor.h b/src/ext/Iis/ca/caDecor.h new file mode 100644 index 00000000..da274650 --- /dev/null +++ b/src/ext/Iis/ca/caDecor.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #if defined(_M_ARM64) | ||
| 6 | #define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_A64" | ||
| 7 | #elif defined(_M_AMD64) | ||
| 8 | #define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X64" | ||
| 9 | #elif defined(_M_ARM) | ||
| 10 | #define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_ARM" | ||
| 11 | #else | ||
| 12 | #define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X86" | ||
| 13 | #endif | ||
diff --git a/src/ext/Iis/ca/dllmain.cpp b/src/ext/Iis/ca/dllmain.cpp new file mode 100644 index 00000000..35ae6d1c --- /dev/null +++ b/src/ext/Iis/ca/dllmain.cpp | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | /******************************************************************** | ||
| 6 | DllMain - standard entry point for all WiX custom actions | ||
| 7 | |||
| 8 | ********************************************************************/ | ||
| 9 | extern "C" BOOL WINAPI DllMain( | ||
| 10 | IN HINSTANCE hInst, | ||
| 11 | IN ULONG ulReason, | ||
| 12 | IN LPVOID) | ||
| 13 | { | ||
| 14 | switch(ulReason) | ||
| 15 | { | ||
| 16 | case DLL_PROCESS_ATTACH: | ||
| 17 | WcaGlobalInitialize(hInst); | ||
| 18 | break; | ||
| 19 | |||
| 20 | case DLL_PROCESS_DETACH: | ||
| 21 | WcaGlobalFinalize(); | ||
| 22 | break; | ||
| 23 | } | ||
| 24 | |||
| 25 | return TRUE; | ||
| 26 | } | ||
diff --git a/src/ext/Iis/ca/iisca.cpp b/src/ext/Iis/ca/iisca.cpp new file mode 100644 index 00000000..37664a1c --- /dev/null +++ b/src/ext/Iis/ca/iisca.cpp | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
diff --git a/src/ext/Iis/ca/iisca.def b/src/ext/Iis/ca/iisca.def new file mode 100644 index 00000000..b9127da6 --- /dev/null +++ b/src/ext/Iis/ca/iisca.def | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | ; Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | |||
| 4 | LIBRARY "iisca" | ||
| 5 | |||
| 6 | EXPORTS | ||
| 7 | ;scacert.cpp | ||
| 8 | InstallCertificates | ||
| 9 | UninstallCertificates | ||
| 10 | ;scacertexec.cpp | ||
| 11 | AddUserCertificate | ||
| 12 | AddMachineCertificate | ||
| 13 | DeleteUserCertificate | ||
| 14 | DeleteMachineCertificate | ||
| 15 | ;scaexec.cpp | ||
| 16 | StartMetabaseTransaction | ||
| 17 | RollbackMetabaseTransaction | ||
| 18 | CommitMetabaseTransaction | ||
| 19 | |||
| 20 | WriteMetabaseChanges | ||
| 21 | |||
| 22 | StartIIS7ConfigTransaction | ||
| 23 | RollbackIIS7ConfigTransaction | ||
| 24 | CommitIIS7ConfigTransaction | ||
| 25 | |||
| 26 | WriteIIS7ConfigChanges | ||
| 27 | ;scasched.cpp | ||
| 28 | ConfigureIIs | ||
| 29 | ConfigureIIsExec | ||
| 30 | ConfigureIIs7Exec | ||
diff --git a/src/ext/Iis/ca/iisca.vcxproj b/src/ext/Iis/ca/iisca.vcxproj new file mode 100644 index 00000000..eb1174be --- /dev/null +++ b/src/ext/Iis/ca/iisca.vcxproj | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| 4 | <Import Project="..\..\packages\WixToolset.DUtil.4.0.30\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.30\build\WixToolset.DUtil.props')" /> | ||
| 5 | <Import Project="..\..\packages\WixToolset.WcaUtil.4.0.16\build\WixToolset.WcaUtil.props" Condition="Exists('..\..\packages\WixToolset.WcaUtil.4.0.16\build\WixToolset.WcaUtil.props')" /> | ||
| 6 | |||
| 7 | <ItemGroup Label="ProjectConfigurations"> | ||
| 8 | <ProjectConfiguration Include="Debug|Win32"> | ||
| 9 | <Configuration>Debug</Configuration> | ||
| 10 | <Platform>Win32</Platform> | ||
| 11 | </ProjectConfiguration> | ||
| 12 | <ProjectConfiguration Include="Release|Win32"> | ||
| 13 | <Configuration>Release</Configuration> | ||
| 14 | <Platform>Win32</Platform> | ||
| 15 | </ProjectConfiguration> | ||
| 16 | <ProjectConfiguration Include="Debug|x64"> | ||
| 17 | <Configuration>Debug</Configuration> | ||
| 18 | <Platform>x64</Platform> | ||
| 19 | </ProjectConfiguration> | ||
| 20 | <ProjectConfiguration Include="Release|x64"> | ||
| 21 | <Configuration>Release</Configuration> | ||
| 22 | <Platform>x64</Platform> | ||
| 23 | </ProjectConfiguration> | ||
| 24 | <ProjectConfiguration Include="Debug|ARM64"> | ||
| 25 | <Configuration>Debug</Configuration> | ||
| 26 | <Platform>ARM64</Platform> | ||
| 27 | </ProjectConfiguration> | ||
| 28 | <ProjectConfiguration Include="Release|ARM64"> | ||
| 29 | <Configuration>Release</Configuration> | ||
| 30 | <Platform>ARM64</Platform> | ||
| 31 | </ProjectConfiguration> | ||
| 32 | </ItemGroup> | ||
| 33 | |||
| 34 | <PropertyGroup Label="Globals"> | ||
| 35 | <ProjectGuid>{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}</ProjectGuid> | ||
| 36 | <ConfigurationType>DynamicLibrary</ConfigurationType> | ||
| 37 | <TargetName>iisca</TargetName> | ||
| 38 | <PlatformToolset>v142</PlatformToolset> | ||
| 39 | <CharacterSet>Unicode</CharacterSet> | ||
| 40 | <ProjectModuleDefinitionFile>iisca.def</ProjectModuleDefinitionFile> | ||
| 41 | <Description>WiX Toolset Iis CustomAction</Description> | ||
| 42 | </PropertyGroup> | ||
| 43 | |||
| 44 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | ||
| 45 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | ||
| 46 | |||
| 47 | <PropertyGroup> | ||
| 48 | <ProjectAdditionalLinkLibraries>crypt32.lib;msi.lib;Ws2_32.lib</ProjectAdditionalLinkLibraries> | ||
| 49 | </PropertyGroup> | ||
| 50 | |||
| 51 | <ItemGroup> | ||
| 52 | <ClCompile Include="dllmain.cpp"> | ||
| 53 | <PrecompiledHeader>Create</PrecompiledHeader> | ||
| 54 | </ClCompile> | ||
| 55 | <ClCompile Include="iisca.cpp" /> | ||
| 56 | <ClCompile Include="scaapppool.cpp" /> | ||
| 57 | <ClCompile Include="scaapppool7.cpp" /> | ||
| 58 | <ClCompile Include="scacert.cpp" /> | ||
| 59 | <ClCompile Include="scacertexec.cpp" /> | ||
| 60 | <ClCompile Include="scaexec.cpp" /> | ||
| 61 | <ClCompile Include="scaexecIIS7.cpp" /> | ||
| 62 | <ClCompile Include="scafilter.cpp" /> | ||
| 63 | <ClCompile Include="scafilter7.cpp" /> | ||
| 64 | <ClCompile Include="scahttpheader.cpp" /> | ||
| 65 | <ClCompile Include="scahttpheader7.cpp" /> | ||
| 66 | <ClCompile Include="scaiis.cpp" /> | ||
| 67 | <ClCompile Include="scaiis7.cpp" /> | ||
| 68 | <ClCompile Include="scamimemap.cpp" /> | ||
| 69 | <ClCompile Include="scamimemap7.cpp" /> | ||
| 70 | <ClCompile Include="scaproperty.cpp" /> | ||
| 71 | <ClCompile Include="scaproperty7.cpp" /> | ||
| 72 | <ClCompile Include="scasched.cpp" /> | ||
| 73 | <ClCompile Include="scassl.cpp" /> | ||
| 74 | <ClCompile Include="scassl7.cpp" /> | ||
| 75 | <ClCompile Include="scauser.cpp" /> | ||
| 76 | <ClCompile Include="scavdir.cpp" /> | ||
| 77 | <ClCompile Include="scavdir7.cpp" /> | ||
| 78 | <ClCompile Include="scaweb.cpp" /> | ||
| 79 | <ClCompile Include="scaweb7.cpp" /> | ||
| 80 | <ClCompile Include="scawebapp.cpp" /> | ||
| 81 | <ClCompile Include="scawebapp7.cpp" /> | ||
| 82 | <ClCompile Include="scawebappext.cpp" /> | ||
| 83 | <ClCompile Include="scawebappext7.cpp" /> | ||
| 84 | <ClCompile Include="scawebdir.cpp" /> | ||
| 85 | <ClCompile Include="scawebdir7.cpp" /> | ||
| 86 | <ClCompile Include="scaweberr.cpp" /> | ||
| 87 | <ClCompile Include="scaweberr7.cpp" /> | ||
| 88 | <ClCompile Include="scaweblog.cpp" /> | ||
| 89 | <ClCompile Include="scaweblog7.cpp" /> | ||
| 90 | <ClCompile Include="scawebprop.cpp" /> | ||
| 91 | <ClCompile Include="scawebprop7.cpp" /> | ||
| 92 | <ClCompile Include="scawebsvcext.cpp" /> | ||
| 93 | <ClCompile Include="scawebsvcext7.cpp" /> | ||
| 94 | <ClInclude Include="caSuffix.h" /> | ||
| 95 | <ClInclude Include="CustomMsiErrors.h" /> | ||
| 96 | <ClInclude Include="precomp.h" /> | ||
| 97 | <ClInclude Include="sca.h" /> | ||
| 98 | <ClInclude Include="scaapppool.h" /> | ||
| 99 | <ClInclude Include="scaapppool7.h" /> | ||
| 100 | <ClInclude Include="scacert.h" /> | ||
| 101 | <ClInclude Include="scacost.h" /> | ||
| 102 | <ClInclude Include="scaexecIIS7.h" /> | ||
| 103 | <ClInclude Include="scafilter.h" /> | ||
| 104 | <ClInclude Include="scafilter7.h" /> | ||
| 105 | <ClInclude Include="scahttpheader.h" /> | ||
| 106 | <ClInclude Include="scahttpheader7.h" /> | ||
| 107 | <ClInclude Include="scaiis.h" /> | ||
| 108 | <ClInclude Include="scaiis7.h" /> | ||
| 109 | <ClInclude Include="scamimemap.h" /> | ||
| 110 | <ClInclude Include="scamimemap7.h" /> | ||
| 111 | <ClInclude Include="scaproperty.h" /> | ||
| 112 | <ClInclude Include="scaproperty7.h" /> | ||
| 113 | <ClInclude Include="scassl.h" /> | ||
| 114 | <ClInclude Include="scassl7.h" /> | ||
| 115 | <ClInclude Include="scauser.h" /> | ||
| 116 | <ClInclude Include="scavdir.h" /> | ||
| 117 | <ClInclude Include="scavdir7.h" /> | ||
| 118 | <ClInclude Include="scaweb.h" /> | ||
| 119 | <ClInclude Include="scaweb7.h" /> | ||
| 120 | <ClInclude Include="scawebapp.h" /> | ||
| 121 | <ClInclude Include="scawebapp7.h" /> | ||
| 122 | <ClInclude Include="scawebappext.h" /> | ||
| 123 | <ClInclude Include="scawebappext7.h" /> | ||
| 124 | <ClInclude Include="scawebdir.h" /> | ||
| 125 | <ClInclude Include="scawebdir7.h" /> | ||
| 126 | <ClInclude Include="scaweberr.h" /> | ||
| 127 | <ClInclude Include="scaweberr7.h" /> | ||
| 128 | <ClInclude Include="scaweblog.h" /> | ||
| 129 | <ClInclude Include="scaweblog7.h" /> | ||
| 130 | <ClInclude Include="scawebprop.h" /> | ||
| 131 | <ClInclude Include="scawebprop7.h" /> | ||
| 132 | <ClInclude Include="scawebsvcext.h" /> | ||
| 133 | <ClInclude Include="scawebsvcext7.h" /> | ||
| 134 | <None Include="packages.config" /> | ||
| 135 | <None Include="iisca.def" /> | ||
| 136 | </ItemGroup> | ||
| 137 | |||
| 138 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||
| 139 | |||
| 140 | <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | ||
| 141 | <PropertyGroup> | ||
| 142 | <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> | ||
| 143 | </PropertyGroup> | ||
| 144 | <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.30\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.30\build\WixToolset.DUtil.props'))" /> | ||
| 145 | <Error Condition="!Exists('..\..\packages\WixToolset.WcaUtil.4.0.16\build\WixToolset.WcaUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.WcaUtil.4.0.16\build\WixToolset.WcaUtil.props'))" /> | ||
| 146 | </Target> | ||
| 147 | </Project> \ No newline at end of file | ||
diff --git a/src/ext/Iis/ca/packages.config b/src/ext/Iis/ca/packages.config new file mode 100644 index 00000000..e3dc0e43 --- /dev/null +++ b/src/ext/Iis/ca/packages.config | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <packages> | ||
| 3 | <package id="WixToolset.DUtil" version="4.0.30" targetFramework="native" /> | ||
| 4 | <package id="WixToolset.WcaUtil" version="4.0.16" targetFramework="native" /> | ||
| 5 | </packages> \ No newline at end of file | ||
diff --git a/src/ext/Iis/ca/precomp.h b/src/ext/Iis/ca/precomp.h new file mode 100644 index 00000000..85ee0890 --- /dev/null +++ b/src/ext/Iis/ca/precomp.h | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #if _WIN32_MSI < 150 | ||
| 6 | #define _WIN32_MSI 150 | ||
| 7 | #endif | ||
| 8 | |||
| 9 | #include <windows.h> | ||
| 10 | #include <msiquery.h> | ||
| 11 | #include <msidefs.h> | ||
| 12 | #include <strsafe.h> | ||
| 13 | |||
| 14 | #include <lm.h> // NetApi32.lib | ||
| 15 | |||
| 16 | #include <Dsgetdc.h> | ||
| 17 | #include <ComAdmin.h> | ||
| 18 | #include <ahadmin.h> // IIS 7 config | ||
| 19 | |||
| 20 | #define MAXUINT USHRT_MAX | ||
| 21 | |||
| 22 | #include "wcautil.h" | ||
| 23 | #include "wcawow64.h" | ||
| 24 | #include "wcawrapquery.h" | ||
| 25 | |||
| 26 | #include "certutil.h" | ||
| 27 | #include "cryputil.h" | ||
| 28 | #include "fileutil.h" | ||
| 29 | #include "iis7util.h" | ||
| 30 | #include "memutil.h" | ||
| 31 | #include "metautil.h" | ||
| 32 | #include "strutil.h" | ||
| 33 | #include "userutil.h" | ||
| 34 | #include "wiutil.h" | ||
| 35 | |||
| 36 | #include "CustomMsiErrors.h" | ||
| 37 | #include "sca.h" | ||
| 38 | #include "scacost.h" | ||
| 39 | #include "scacert.h" | ||
| 40 | #include "scafilter.h" | ||
| 41 | |||
| 42 | #include "scaiis.h" | ||
| 43 | #include "scaiis7.h" | ||
| 44 | #include "scaproperty.h" | ||
| 45 | #include "scaweb.h" | ||
| 46 | #include "scawebdir.h" | ||
| 47 | #include "scawebsvcext.h" | ||
| 48 | #include "scavdir.h" | ||
| 49 | #include "scaweb7.h" | ||
| 50 | #include "scaapppool7.h" | ||
| 51 | #include "scavdir7.h" | ||
| 52 | #include "scawebapp7.h" | ||
| 53 | #include "scawebappext7.h" | ||
| 54 | #include "scamimemap7.h" | ||
| 55 | #include "scawebprop7.h" | ||
| 56 | #include "scaweblog7.h" | ||
| 57 | #include "scafilter7.h" | ||
| 58 | #include "scahttpheader7.h" | ||
| 59 | #include "scaweberr7.h" | ||
| 60 | #include "scawebsvcext7.h" | ||
| 61 | #include "scaproperty7.h" | ||
| 62 | #include "scawebdir7.h" | ||
| 63 | #include "scassl7.h" | ||
| 64 | #include "scaexecIIS7.h" | ||
| 65 | |||
| 66 | #include "caDecor.h" | ||
diff --git a/src/ext/Iis/ca/sca.h b/src/ext/Iis/ca/sca.h new file mode 100644 index 00000000..64567dcb --- /dev/null +++ b/src/ext/Iis/ca/sca.h | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #define MAGIC_MULTISZ_CHAR 127 | ||
| 6 | |||
| 7 | // Generic action enum. | ||
| 8 | enum SCA_ACTION | ||
| 9 | { | ||
| 10 | SCA_ACTION_NONE, | ||
| 11 | SCA_ACTION_INSTALL, | ||
| 12 | SCA_ACTION_UNINSTALL | ||
| 13 | }; | ||
| 14 | |||
| 15 | |||
| 16 | // IIS Metabase actions | ||
| 17 | enum METABASE_ACTION | ||
| 18 | { | ||
| 19 | MBA_UNKNOWNACTION = 0, | ||
| 20 | MBA_CREATEKEY, | ||
| 21 | MBA_DELETEKEY, | ||
| 22 | MBA_WRITEVALUE, | ||
| 23 | MBA_DELETEVALUE, | ||
| 24 | MBA_CREATEAPP, | ||
| 25 | MBA_DELETEAPP, | ||
| 26 | }; | ||
| 27 | |||
| 28 | // IIS 7 Config actions | ||
| 29 | enum IIS_CONFIG_ACTION | ||
| 30 | { | ||
| 31 | IIS_CREATE, | ||
| 32 | IIS_DELETE, | ||
| 33 | IIS_SITE, | ||
| 34 | IIS_APPLICATION, | ||
| 35 | IIS_APPPOOL, | ||
| 36 | IIS_APPPOOL_RECYCLE_MIN, | ||
| 37 | IIS_APPPOOL_RECYCLE_REQ, | ||
| 38 | IIS_APPPOOL_RECYCLE_TIMES, | ||
| 39 | IIS_APPPOOL_RECYCLE_VIRMEM, | ||
| 40 | IIS_APPPOOL_RECYCLE_PRIVMEM, | ||
| 41 | IIS_APPPOOL_RECYCLE_IDLTIMEOUT, | ||
| 42 | IIS_APPPOOL_RECYCLE_QUEUELIMIT, | ||
| 43 | IIS_APPPOOL_RECYCLE_CPU_PCT, | ||
| 44 | IIS_APPPOOL_RECYCLE_CPU_REFRESH, | ||
| 45 | IIS_APPPOOL_RECYCLE_CPU_ACTION, | ||
| 46 | IIS_APPPOOL_MAXPROCESS, | ||
| 47 | IIS_APPPOOL_IDENTITY, | ||
| 48 | IIS_APPPOOL_USER, | ||
| 49 | IIS_APPPOOL_PWD, | ||
| 50 | IIS_APPPOOL_32BIT, | ||
| 51 | IIS_APPPOOL_MANAGED_PIPELINE_MODE, | ||
| 52 | IIS_APPPOOL_MANAGED_RUNTIME_VERSION, | ||
| 53 | IIS_APPPOOL_END, | ||
| 54 | IIS_APPEXT_BEGIN, | ||
| 55 | IIS_APPEXT, | ||
| 56 | IIS_APPEXT_END, | ||
| 57 | IIS_VDIR, | ||
| 58 | IIS_BINDING, | ||
| 59 | IIS_MIMEMAP_BEGIN, | ||
| 60 | IIS_MIMEMAP, | ||
| 61 | IIS_MIMEMAP_END, | ||
| 62 | IIS_DIRPROP_BEGIN, | ||
| 63 | IIS_DIRPROP_ACCESS, | ||
| 64 | IIS_DIRPROP_AUTH, | ||
| 65 | IIS_DIRPROP_USER, | ||
| 66 | IIS_DIRPROP_PWD, | ||
| 67 | IIS_DIRPROP_PWDCTRL, | ||
| 68 | IIS_DIRPROP_LOG, | ||
| 69 | IIS_DIRPROP_DEFDOCS, | ||
| 70 | IIS_DIRPROP_SSLFLAGS, | ||
| 71 | IIS_DIRPROP_AUTHPROVID, | ||
| 72 | IIS_DIRPROP_ASPERROR, | ||
| 73 | IIS_DIRPROP_HTTPEXPIRES, | ||
| 74 | IIS_DIRPROP_MAXAGE, | ||
| 75 | IIS_DIRPROP_CACHECUST, | ||
| 76 | IIS_DIRPROP_NOCUSTERROR, | ||
| 77 | IIS_DIRPROP_LOGVISITS, | ||
| 78 | IIS_DIRPROP_END, | ||
| 79 | IIS_WEBLOG, | ||
| 80 | IIS_FILTER_BEGIN, | ||
| 81 | IIS_FILTER_GLOBAL_BEGIN, | ||
| 82 | IIS_FILTER, | ||
| 83 | IIS_FILTER_END, | ||
| 84 | IIS_HTTP_HEADER_BEGIN, | ||
| 85 | IIS_HTTP_HEADER, | ||
| 86 | IIS_HTTP_HEADER_END, | ||
| 87 | IIS_WEBERROR_BEGIN, | ||
| 88 | IIS_WEBERROR, | ||
| 89 | IIS_WEBERROR_END, | ||
| 90 | IIS_WEB_SVC_EXT, | ||
| 91 | IIS_PROPERTY, | ||
| 92 | IIS_PROPERTY_MAXBAND, | ||
| 93 | IIS_PROPERTY_LOGUTF8, | ||
| 94 | IIS_WEBDIR, | ||
| 95 | IIS_ASP_BEGIN, | ||
| 96 | IIS_ASP_SESSIONSTATE, | ||
| 97 | IIS_ASP_SESSIONTIMEOUT, | ||
| 98 | IIS_ASP_BUFFER, | ||
| 99 | IIS_ASP_PARENTPATHS, | ||
| 100 | IIS_ASP_SCRIPTLANG, | ||
| 101 | IIS_ASP_SCRIPTTIMEOUT, | ||
| 102 | IIS_ASP_SCRIPTSERVERDEBUG, | ||
| 103 | IIS_ASP_SCRIPTCLIENTDEBUG, | ||
| 104 | IIS_ASP_END, | ||
| 105 | IIS_SSL_BINDING | ||
| 106 | }; | ||
| 107 | |||
| 108 | |||
| 109 | // user creation attributes definitions | ||
| 110 | enum SCAU_ATTRIBUTES | ||
| 111 | { | ||
| 112 | SCAU_DONT_EXPIRE_PASSWRD = 0x00000001, | ||
| 113 | SCAU_PASSWD_CANT_CHANGE = 0x00000002, | ||
| 114 | SCAU_PASSWD_CHANGE_REQD_ON_LOGIN = 0x00000004, | ||
| 115 | SCAU_DISABLE_ACCOUNT = 0x00000008, | ||
| 116 | SCAU_FAIL_IF_EXISTS = 0x00000010, | ||
| 117 | SCAU_UPDATE_IF_EXISTS = 0x00000020, | ||
| 118 | SCAU_ALLOW_LOGON_AS_SERVICE = 0x00000040, | ||
| 119 | SCAU_ALLOW_LOGON_AS_BATCH = 0x00000080, | ||
| 120 | |||
| 121 | SCAU_DONT_REMOVE_ON_UNINSTALL = 0x00000100, | ||
| 122 | SCAU_DONT_CREATE_USER = 0x00000200, | ||
| 123 | SCAU_NON_VITAL = 0x00000400, | ||
| 124 | }; | ||
diff --git a/src/ext/Iis/ca/scaapppool.cpp b/src/ext/Iis/ca/scaapppool.cpp new file mode 100644 index 00000000..781c55ca --- /dev/null +++ b/src/ext/Iis/ca/scaapppool.cpp | |||
| @@ -0,0 +1,594 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | /*------------------------------------------------------------------ | ||
| 6 | AppPool table: | ||
| 7 | |||
| 8 | Column Type Nullable Example Value | ||
| 9 | AppPool s72 No TestPool | ||
| 10 | Name s72 No "TestPool" | ||
| 11 | Component_ s72 No ComponentName | ||
| 12 | Attributes i2 No 8 (APATTR_OTHERUSER) | ||
| 13 | User_ s72 Yes UserKey | ||
| 14 | RecycleMinutes i2 Yes 500 | ||
| 15 | RecycleRequests i2 Yes 5000 | ||
| 16 | RecycleTimes s72 Yes "1:45,13:30,22:00" | ||
| 17 | IdleTimeout i2 Yes 15 | ||
| 18 | QueueLimit i2 Yes 500 | ||
| 19 | CPUMon s72 Yes "65,500,1" (65% CPU usage, 500 minutes, Shutdown Action) | ||
| 20 | MaxProc i2 Yes 5 | ||
| 21 | ManagedRuntimeVersion s72 Yes "v2.0" | ||
| 22 | ManagedPipelineMode s72 Yes "Integrated" | ||
| 23 | |||
| 24 | Notes: | ||
| 25 | RecycleTimes is a comma delimeted list of times. CPUMon is a | ||
| 26 | comma delimeted list of the following format: | ||
| 27 | <percent CPU usage>,<refress minutes>,<Action>. The values for | ||
| 28 | Action are 1 (Shutdown) and 0 (No Action). | ||
| 29 | |||
| 30 | ------------------------------------------------------------------*/ | ||
| 31 | |||
| 32 | enum eAppPoolQuery { apqAppPool = 1, apqName, apqComponent, apqAttributes, apqUser, apqRecycleMinutes, apqRecycleRequests, apqRecycleTimes, apqVirtualMemory, apqPrivateMemory, apqIdleTimeout, apqQueueLimit, apqCpuMon, apqMaxProc, apqManagedRuntimeVersion, apqManagedPipelineMode, apqInstalled, apqAction }; | ||
| 33 | |||
| 34 | enum eComponentAttrQuery { caqComponent = 1, caqAttributes }; | ||
| 35 | |||
| 36 | // prototypes | ||
| 37 | static HRESULT AppPoolExists( | ||
| 38 | __in IMSAdminBase* piMetabase, | ||
| 39 | __in LPCWSTR wzAppPool | ||
| 40 | ); | ||
| 41 | |||
| 42 | // functions | ||
| 43 | |||
| 44 | void ScaAppPoolFreeList( | ||
| 45 | __in SCA_APPPOOL* psapList | ||
| 46 | ) | ||
| 47 | { | ||
| 48 | SCA_APPPOOL* psapDelete = psapList; | ||
| 49 | while (psapList) | ||
| 50 | { | ||
| 51 | psapDelete = psapList; | ||
| 52 | psapList = psapList->psapNext; | ||
| 53 | |||
| 54 | MemFree(psapDelete); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | |||
| 59 | HRESULT ScaAppPoolRead( | ||
| 60 | __inout SCA_APPPOOL** ppsapList, | ||
| 61 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 62 | __inout LPWSTR *ppwzCustomActionData | ||
| 63 | ) | ||
| 64 | { | ||
| 65 | Assert(ppsapList); | ||
| 66 | |||
| 67 | HRESULT hr = S_OK; | ||
| 68 | |||
| 69 | MSIHANDLE hRec, hRecComp; | ||
| 70 | LPWSTR pwzData = NULL; | ||
| 71 | SCA_APPPOOL* psap = NULL; | ||
| 72 | WCA_WRAPQUERY_HANDLE hAppPoolQuery = NULL; | ||
| 73 | WCA_WRAPQUERY_HANDLE hComponentQuery = NULL; | ||
| 74 | |||
| 75 | hr = WcaBeginUnwrapQuery(&hAppPoolQuery, ppwzCustomActionData); | ||
| 76 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 77 | |||
| 78 | if (0 == WcaGetQueryRecords(hAppPoolQuery)) | ||
| 79 | { | ||
| 80 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaAppPoolRead() - required table not present"); | ||
| 81 | ExitFunction1(hr = S_FALSE); | ||
| 82 | } | ||
| 83 | |||
| 84 | hr = WcaBeginUnwrapQuery(&hComponentQuery, ppwzCustomActionData); | ||
| 85 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 86 | |||
| 87 | // loop through all the AppPools | ||
| 88 | while (S_OK == (hr = WcaFetchWrappedRecord(hAppPoolQuery, &hRec))) | ||
| 89 | { | ||
| 90 | // Add this record's information into the list of things to process. | ||
| 91 | hr = AddAppPoolToList(ppsapList); | ||
| 92 | ExitOnFailure(hr, "failed to add app pool to app pool list"); | ||
| 93 | |||
| 94 | psap = *ppsapList; | ||
| 95 | |||
| 96 | hr = WcaGetRecordString(hRec, apqComponent, &pwzData); | ||
| 97 | ExitOnFailure(hr, "failed to get AppPool.Component"); | ||
| 98 | |||
| 99 | if (pwzData && *pwzData) | ||
| 100 | { | ||
| 101 | psap->fHasComponent = TRUE; | ||
| 102 | |||
| 103 | hr = ::StringCchCopyW(psap->wzComponent, countof(psap->wzComponent), pwzData); | ||
| 104 | ExitOnFailure(hr, "failed to copy component name: %ls", pwzData); | ||
| 105 | |||
| 106 | hr = WcaGetRecordInteger(hRec, apqInstalled, (int *)&psap->isInstalled); | ||
| 107 | ExitOnFailure(hr, "Failed to get Component installed state for app pool"); | ||
| 108 | |||
| 109 | hr = WcaGetRecordInteger(hRec, apqAction, (int *)&psap->isAction); | ||
| 110 | ExitOnFailure(hr, "Failed to get Component action state for app pool"); | ||
| 111 | |||
| 112 | WcaFetchWrappedReset(hComponentQuery); | ||
| 113 | hr = WcaFetchWrappedRecordWhereString(hComponentQuery, caqComponent, psap->wzComponent, &hRecComp); | ||
| 114 | ExitOnFailure(hr, "Failed to fetch Component.Attributes for Component '%ls'", psap->wzComponent); | ||
| 115 | |||
| 116 | hr = WcaGetRecordInteger(hRecComp, caqAttributes, &psap->iCompAttributes); | ||
| 117 | ExitOnFailure(hr, "failed to get Component.Attributes"); | ||
| 118 | } | ||
| 119 | |||
| 120 | hr = WcaGetRecordString(hRec, apqAppPool, &pwzData); | ||
| 121 | ExitOnFailure(hr, "failed to get AppPool.AppPool"); | ||
| 122 | hr = ::StringCchCopyW(psap->wzAppPool, countof(psap->wzAppPool), pwzData); | ||
| 123 | ExitOnFailure(hr, "failed to copy AppPool name: %ls", pwzData); | ||
| 124 | |||
| 125 | hr = WcaGetRecordString(hRec, apqName, &pwzData); | ||
| 126 | ExitOnFailure(hr, "failed to get AppPool.Name"); | ||
| 127 | hr = ::StringCchCopyW(psap->wzName, countof(psap->wzName), pwzData); | ||
| 128 | ExitOnFailure(hr, "failed to copy app pool name: %ls", pwzData); | ||
| 129 | hr = ::StringCchPrintfW(psap->wzKey, countof(psap->wzKey), L"/LM/W3SVC/AppPools/%s", pwzData); | ||
| 130 | ExitOnFailure(hr, "failed to format app pool key name"); | ||
| 131 | |||
| 132 | hr = WcaGetRecordInteger(hRec, apqAttributes, &psap->iAttributes); | ||
| 133 | ExitOnFailure(hr, "failed to get AppPool.Attributes"); | ||
| 134 | |||
| 135 | hr = WcaGetRecordString(hRec, apqUser, &pwzData); | ||
| 136 | ExitOnFailure(hr, "failed to get AppPool.User"); | ||
| 137 | hr = ScaGetUserDeferred(pwzData, hUserQuery, &psap->suUser); | ||
| 138 | ExitOnFailure(hr, "failed to get user: %ls", pwzData); | ||
| 139 | |||
| 140 | hr = WcaGetRecordInteger(hRec, apqRecycleRequests, &psap->iRecycleRequests); | ||
| 141 | ExitOnFailure(hr, "failed to get AppPool.RecycleRequests"); | ||
| 142 | |||
| 143 | hr = WcaGetRecordInteger(hRec, apqRecycleMinutes, &psap->iRecycleMinutes); | ||
| 144 | ExitOnFailure(hr, "failed to get AppPool.Minutes"); | ||
| 145 | |||
| 146 | hr = WcaGetRecordString(hRec, apqRecycleTimes, &pwzData); | ||
| 147 | ExitOnFailure(hr, "failed to get AppPool.RecycleTimes"); | ||
| 148 | hr = ::StringCchCopyW(psap->wzRecycleTimes, countof(psap->wzRecycleTimes), pwzData); | ||
| 149 | ExitOnFailure(hr, "failed to copy recycle value: %ls", pwzData); | ||
| 150 | |||
| 151 | hr = WcaGetRecordInteger(hRec, apqVirtualMemory, &psap->iVirtualMemory); | ||
| 152 | ExitOnFailure(hr, "failed to get AppPool.VirtualMemory"); | ||
| 153 | |||
| 154 | hr = WcaGetRecordInteger(hRec, apqPrivateMemory, &psap->iPrivateMemory); | ||
| 155 | ExitOnFailure(hr, "failed to get AppPool.PrivateMemory"); | ||
| 156 | |||
| 157 | hr = WcaGetRecordInteger(hRec, apqIdleTimeout, &psap->iIdleTimeout); | ||
| 158 | ExitOnFailure(hr, "failed to get AppPool.IdleTimeout"); | ||
| 159 | |||
| 160 | hr = WcaGetRecordInteger(hRec, apqQueueLimit, &psap->iQueueLimit); | ||
| 161 | ExitOnFailure(hr, "failed to get AppPool.QueueLimit"); | ||
| 162 | |||
| 163 | hr = WcaGetRecordString(hRec, apqCpuMon, &pwzData); | ||
| 164 | ExitOnFailure(hr, "failed to get AppPool.CPUMon"); | ||
| 165 | hr = ::StringCchCopyW(psap->wzCpuMon, countof(psap->wzCpuMon), pwzData); | ||
| 166 | ExitOnFailure(hr, "failed to copy cpu monitor value: %ls", pwzData); | ||
| 167 | |||
| 168 | hr = WcaGetRecordInteger(hRec, apqMaxProc, &psap->iMaxProcesses); | ||
| 169 | ExitOnFailure(hr, "failed to get AppPool.MaxProc"); | ||
| 170 | |||
| 171 | hr = WcaGetRecordString(hRec, apqManagedRuntimeVersion, &pwzData); | ||
| 172 | ExitOnFailure(hr, "failed to get AppPool.ManagedRuntimeVersion"); | ||
| 173 | hr = ::StringCchCopyW(psap->wzManagedRuntimeVersion, countof(psap->wzManagedRuntimeVersion), pwzData); | ||
| 174 | ExitOnFailure(hr, "failed to copy ManagedRuntimeVersion value: %ls", pwzData); | ||
| 175 | |||
| 176 | hr = WcaGetRecordString(hRec, apqManagedPipelineMode, &pwzData); | ||
| 177 | ExitOnFailure(hr, "failed to get AppPool.ManagedPipelineMode"); | ||
| 178 | hr = ::StringCchCopyW(psap->wzManagedPipelineMode, countof(psap->wzManagedPipelineMode), pwzData); | ||
| 179 | ExitOnFailure(hr, "failed to copy ManagedPipelineMode value: %ls", pwzData); | ||
| 180 | |||
| 181 | } | ||
| 182 | |||
| 183 | if (E_NOMOREITEMS == hr) | ||
| 184 | { | ||
| 185 | hr = S_OK; | ||
| 186 | } | ||
| 187 | ExitOnFailure(hr, "failure while processing AppPools"); | ||
| 188 | |||
| 189 | LExit: | ||
| 190 | WcaFinishUnwrapQuery(hAppPoolQuery); | ||
| 191 | WcaFinishUnwrapQuery(hComponentQuery); | ||
| 192 | |||
| 193 | ReleaseStr(pwzData); | ||
| 194 | return hr; | ||
| 195 | } | ||
| 196 | |||
| 197 | |||
| 198 | HRESULT ScaFindAppPool( | ||
| 199 | __in IMSAdminBase* piMetabase, | ||
| 200 | __in LPCWSTR wzAppPool, | ||
| 201 | __out_ecount(cchName) LPWSTR wzName, | ||
| 202 | __in DWORD cchName, | ||
| 203 | __in SCA_APPPOOL *psapList | ||
| 204 | ) | ||
| 205 | { | ||
| 206 | Assert(piMetabase && wzAppPool && *wzAppPool && wzName && *wzName); | ||
| 207 | |||
| 208 | HRESULT hr = S_OK; | ||
| 209 | |||
| 210 | // check memory first | ||
| 211 | SCA_APPPOOL* psap = psapList; | ||
| 212 | for (; psap; psap = psap->psapNext) | ||
| 213 | { | ||
| 214 | if (0 == lstrcmpW(psap->wzAppPool, wzAppPool)) | ||
| 215 | { | ||
| 216 | break; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | ExitOnNull(psap, hr, HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Could not find the app pool: %ls", wzAppPool); | ||
| 220 | |||
| 221 | // copy the web app pool name | ||
| 222 | hr = ::StringCchCopyW(wzName, cchName, psap->wzName); | ||
| 223 | ExitOnFailure(hr, "failed to copy app pool name while finding app pool: %ls", psap->wzName); | ||
| 224 | |||
| 225 | // if it's not being installed now, check if it exists already | ||
| 226 | if (!psap->fHasComponent) | ||
| 227 | { | ||
| 228 | hr = AppPoolExists(piMetabase, psap->wzName); | ||
| 229 | ExitOnFailure(hr, "failed to check for existence of app pool: %ls", psap->wzName); | ||
| 230 | } | ||
| 231 | |||
| 232 | LExit: | ||
| 233 | return hr; | ||
| 234 | } | ||
| 235 | |||
| 236 | |||
| 237 | static HRESULT AppPoolExists( | ||
| 238 | __in IMSAdminBase* piMetabase, | ||
| 239 | __in LPCWSTR wzAppPool | ||
| 240 | ) | ||
| 241 | { | ||
| 242 | Assert(piMetabase && wzAppPool && *wzAppPool); | ||
| 243 | |||
| 244 | HRESULT hr = S_OK; | ||
| 245 | WCHAR wzSubKey[METADATA_MAX_NAME_LEN]; | ||
| 246 | |||
| 247 | for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex) | ||
| 248 | { | ||
| 249 | hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/AppPools", wzSubKey, dwIndex); | ||
| 250 | if (SUCCEEDED(hr) && 0 == lstrcmpW(wzSubKey, wzAppPool)) | ||
| 251 | { | ||
| 252 | hr = S_OK; | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | if (E_NOMOREITEMS == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
| 258 | { | ||
| 259 | hr = S_FALSE; | ||
| 260 | } | ||
| 261 | |||
| 262 | return hr; | ||
| 263 | } | ||
| 264 | |||
| 265 | |||
| 266 | HRESULT ScaAppPoolInstall( | ||
| 267 | __in IMSAdminBase* piMetabase, | ||
| 268 | __in SCA_APPPOOL* psapList | ||
| 269 | ) | ||
| 270 | { | ||
| 271 | Assert(piMetabase); | ||
| 272 | |||
| 273 | HRESULT hr = S_OK; | ||
| 274 | |||
| 275 | for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext) | ||
| 276 | { | ||
| 277 | // if we are installing the app pool | ||
| 278 | if (psap->fHasComponent && WcaIsInstalling(psap->isInstalled, psap->isAction)) | ||
| 279 | { | ||
| 280 | hr = ScaWriteAppPool(piMetabase, psap); | ||
| 281 | ExitOnFailure(hr, "failed to write AppPool '%ls' to metabase", psap->wzAppPool); | ||
| 282 | } | ||
| 283 | } | ||
| 284 | |||
| 285 | LExit: | ||
| 286 | return hr; | ||
| 287 | } | ||
| 288 | |||
| 289 | |||
| 290 | HRESULT ScaAppPoolUninstall( | ||
| 291 | __in IMSAdminBase* piMetabase, | ||
| 292 | __in SCA_APPPOOL* psapList | ||
| 293 | ) | ||
| 294 | { | ||
| 295 | Assert(piMetabase); | ||
| 296 | |||
| 297 | HRESULT hr = S_OK; | ||
| 298 | |||
| 299 | for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext) | ||
| 300 | { | ||
| 301 | // if we are uninstalling the app pool | ||
| 302 | if (psap->fHasComponent && WcaIsUninstalling(psap->isInstalled, psap->isAction)) | ||
| 303 | { | ||
| 304 | hr = ScaRemoveAppPool(piMetabase, psap); | ||
| 305 | ExitOnFailure(hr, "Failed to remove AppPool '%ls' from metabase", psap->wzAppPool); | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | LExit: | ||
| 310 | return hr; | ||
| 311 | } | ||
| 312 | |||
| 313 | |||
| 314 | HRESULT ScaWriteAppPool( | ||
| 315 | __in IMSAdminBase* piMetabase, | ||
| 316 | __in SCA_APPPOOL* psap | ||
| 317 | ) | ||
| 318 | { | ||
| 319 | Assert(piMetabase && psap); | ||
| 320 | |||
| 321 | HRESULT hr = S_OK; | ||
| 322 | DWORD dwIdentity = 0xFFFFFFFF; | ||
| 323 | BOOL fExists = FALSE; | ||
| 324 | LPWSTR pwzValue = NULL; | ||
| 325 | LPWSTR wz = NULL; | ||
| 326 | |||
| 327 | hr = AppPoolExists(piMetabase, psap->wzName); | ||
| 328 | ExitOnFailure(hr, "failed to check if app pool already exists"); | ||
| 329 | if (S_FALSE == hr) | ||
| 330 | { | ||
| 331 | // didn't find the AppPool key, so we need to create it | ||
| 332 | hr = ScaCreateMetabaseKey(piMetabase, psap->wzKey, L""); | ||
| 333 | ExitOnFailure(hr, "failed to create AppPool key: %ls", psap->wzKey); | ||
| 334 | |||
| 335 | // mark it as an AppPool | ||
| 336 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsApplicationPool"); | ||
| 337 | ExitOnFailure(hr, "failed to mark key as AppPool key: %ls", psap->wzKey); | ||
| 338 | |||
| 339 | // TODO: Make this an Attribute? | ||
| 340 | // set autostart value | ||
| 341 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_AUTO_START, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)1); | ||
| 342 | ExitOnFailure(hr, "failed to mark key as AppPool key: %ls", psap->wzKey); | ||
| 343 | } | ||
| 344 | else | ||
| 345 | { | ||
| 346 | fExists = TRUE; | ||
| 347 | } | ||
| 348 | |||
| 349 | // | ||
| 350 | // Set the AppPool Recycling Tab | ||
| 351 | // | ||
| 352 | if (MSI_NULL_INTEGER != psap->iRecycleMinutes) | ||
| 353 | { | ||
| 354 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_TIME, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iRecycleMinutes)); | ||
| 355 | ExitOnFailure(hr, "failed to set periodic restart time"); | ||
| 356 | } | ||
| 357 | |||
| 358 | if (MSI_NULL_INTEGER != psap->iRecycleRequests) | ||
| 359 | { | ||
| 360 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_REQUEST_COUNT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iRecycleRequests)); | ||
| 361 | ExitOnFailure(hr, "failed to set periodic restart request count"); | ||
| 362 | } | ||
| 363 | |||
| 364 | if (*psap->wzRecycleTimes) | ||
| 365 | { | ||
| 366 | // Add another NULL' onto pwz since it's a 'MULTISZ' | ||
| 367 | hr = StrAllocString(&pwzValue, psap->wzRecycleTimes, 0); | ||
| 368 | ExitOnFailure(hr, "failed to allocate string for MULTISZ"); | ||
| 369 | hr = StrAllocConcat(&pwzValue, L"\0", 1); | ||
| 370 | ExitOnFailure(hr, "failed to add second null to RecycleTime multisz"); | ||
| 371 | |||
| 372 | // Replace the commas with NULLs | ||
| 373 | wz = pwzValue; | ||
| 374 | while (NULL != (wz = wcschr(wz, L','))) | ||
| 375 | { | ||
| 376 | *wz = L'\0'; | ||
| 377 | ++wz; | ||
| 378 | } | ||
| 379 | |||
| 380 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_SCHEDULE, METADATA_INHERIT, IIS_MD_UT_SERVER, MULTISZ_METADATA, (LPVOID)pwzValue); | ||
| 381 | ExitOnFailure(hr, "failed to set periodic restart schedule"); | ||
| 382 | } | ||
| 383 | |||
| 384 | if (MSI_NULL_INTEGER != psap->iVirtualMemory) | ||
| 385 | { | ||
| 386 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_MEMORY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iVirtualMemory)); | ||
| 387 | ExitOnFailure(hr, "failed to set periodic restart memory count"); | ||
| 388 | } | ||
| 389 | |||
| 390 | if (MSI_NULL_INTEGER != psap->iPrivateMemory) | ||
| 391 | { | ||
| 392 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_PRIVATE_MEMORY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iPrivateMemory)); | ||
| 393 | ExitOnFailure(hr, "failed to set periodic restart private memory count"); | ||
| 394 | } | ||
| 395 | |||
| 396 | |||
| 397 | // | ||
| 398 | // Set AppPool Performance Tab | ||
| 399 | // | ||
| 400 | if (MSI_NULL_INTEGER != psap->iIdleTimeout) | ||
| 401 | { | ||
| 402 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_IDLE_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iIdleTimeout)); | ||
| 403 | ExitOnFailure(hr, "failed to set idle timeout value"); | ||
| 404 | } | ||
| 405 | |||
| 406 | if (MSI_NULL_INTEGER != psap->iQueueLimit) | ||
| 407 | { | ||
| 408 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_UL_APPPOOL_QUEUE_LENGTH, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iQueueLimit)); | ||
| 409 | ExitOnFailure(hr, "failed to set request queue limit value"); | ||
| 410 | } | ||
| 411 | |||
| 412 | if (*psap->wzCpuMon) | ||
| 413 | { | ||
| 414 | hr = StrAllocString(&pwzValue, psap->wzCpuMon, 0); | ||
| 415 | ExitOnFailure(hr, "failed to allocate CPUMonitor string"); | ||
| 416 | |||
| 417 | DWORD dwPercent = 0; | ||
| 418 | DWORD dwRefreshMinutes = 0; | ||
| 419 | DWORD dwAction = 0; | ||
| 420 | |||
| 421 | dwPercent = wcstoul(pwzValue, &wz, 10); | ||
| 422 | if (100 < dwPercent) | ||
| 423 | { | ||
| 424 | ExitOnFailure(hr = E_INVALIDARG, "invalid maximum cpu percentage value: %d", dwPercent); | ||
| 425 | } | ||
| 426 | if (wz && L',' == *wz) | ||
| 427 | { | ||
| 428 | ++wz; | ||
| 429 | dwRefreshMinutes = wcstoul(wz, &wz, 10); | ||
| 430 | if (wz && L',' == *wz) | ||
| 431 | { | ||
| 432 | ++wz; | ||
| 433 | dwAction = wcstoul(wz, &wz, 10); | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | if (dwPercent) | ||
| 438 | { | ||
| 439 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_LIMIT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)(dwPercent * 1000))); | ||
| 440 | ExitOnFailure(hr, "failed to set CPU percentage max"); | ||
| 441 | } | ||
| 442 | if (dwRefreshMinutes) | ||
| 443 | { | ||
| 444 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_RESET_INTERVAL, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwRefreshMinutes)); | ||
| 445 | ExitOnFailure(hr, "failed to set refresh CPU minutes"); | ||
| 446 | } | ||
| 447 | if (dwAction) | ||
| 448 | { | ||
| 449 | // 0 = No Action | ||
| 450 | // 1 = Shutdown | ||
| 451 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_ACTION, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwAction)); | ||
| 452 | ExitOnFailure(hr, "failed to set CPU action"); | ||
| 453 | } | ||
| 454 | } | ||
| 455 | |||
| 456 | if (MSI_NULL_INTEGER != psap->iMaxProcesses) | ||
| 457 | { | ||
| 458 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_MAX_PROCESS_COUNT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iMaxProcesses)); | ||
| 459 | ExitOnFailure(hr, "failed to set web garden maximum worker processes"); | ||
| 460 | } | ||
| 461 | |||
| 462 | // TODO: Health Tab if anyone wants it? | ||
| 463 | |||
| 464 | // | ||
| 465 | // Set the AppPool Identity tab | ||
| 466 | // | ||
| 467 | if (psap->iAttributes & APATTR_NETSERVICE) | ||
| 468 | { | ||
| 469 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE; | ||
| 470 | } | ||
| 471 | else if (psap->iAttributes & APATTR_LOCSERVICE) | ||
| 472 | { | ||
| 473 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE; | ||
| 474 | } | ||
| 475 | else if (psap->iAttributes & APATTR_LOCSYSTEM) | ||
| 476 | { | ||
| 477 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM; | ||
| 478 | } | ||
| 479 | else if (psap->iAttributes & APATTR_OTHERUSER) | ||
| 480 | { | ||
| 481 | if (!*psap->suUser.wzDomain || CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzDomain, -1, L".", -1)) | ||
| 482 | { | ||
| 483 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"NetworkService", -1)) | ||
| 484 | { | ||
| 485 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE; | ||
| 486 | } | ||
| 487 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"LocalService", -1)) | ||
| 488 | { | ||
| 489 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE; | ||
| 490 | } | ||
| 491 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"LocalSystem", -1)) | ||
| 492 | { | ||
| 493 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM; | ||
| 494 | } | ||
| 495 | else | ||
| 496 | { | ||
| 497 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzDomain, -1, L"NT AUTHORITY", -1)) | ||
| 501 | { | ||
| 502 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"NETWORK SERVICE", -1)) | ||
| 503 | { | ||
| 504 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE; | ||
| 505 | } | ||
| 506 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"SERVICE", -1)) | ||
| 507 | { | ||
| 508 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE; | ||
| 509 | } | ||
| 510 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"SYSTEM", -1)) | ||
| 511 | { | ||
| 512 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM; | ||
| 513 | } | ||
| 514 | else | ||
| 515 | { | ||
| 516 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER; | ||
| 517 | } | ||
| 518 | } | ||
| 519 | else | ||
| 520 | { | ||
| 521 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER; | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | if (-1 != dwIdentity) | ||
| 526 | { | ||
| 527 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_IDENTITY_TYPE, METADATA_INHERIT , IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwIdentity)); | ||
| 528 | ExitOnFailure(hr, "failed to set app pool identity"); | ||
| 529 | |||
| 530 | if (MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER == dwIdentity) | ||
| 531 | { | ||
| 532 | if (*psap->suUser.wzDomain) | ||
| 533 | { | ||
| 534 | hr = StrAllocFormatted(&pwzValue, L"%s\\%s", psap->suUser.wzDomain, psap->suUser.wzName); | ||
| 535 | ExitOnFailure(hr, "failed to format user name: %ls domain: %ls", psap->suUser.wzName, psap->suUser.wzDomain); | ||
| 536 | } | ||
| 537 | else | ||
| 538 | { | ||
| 539 | hr = StrAllocFormatted(&pwzValue, L"%s", psap->suUser.wzName); | ||
| 540 | ExitOnFailure(hr, "failed to format user name: %ls", psap->suUser.wzName); | ||
| 541 | } | ||
| 542 | |||
| 543 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_WAM_USER_NAME, METADATA_INHERIT , IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pwzValue); | ||
| 544 | ExitOnFailure(hr, "failed to set app pool identity name"); | ||
| 545 | |||
| 546 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_WAM_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)psap->suUser.wzPassword); | ||
| 547 | ExitOnFailure(hr, "failed to set app pool identity password"); | ||
| 548 | } | ||
| 549 | } | ||
| 550 | |||
| 551 | LExit: | ||
| 552 | ReleaseStr(pwzValue); | ||
| 553 | |||
| 554 | return hr; | ||
| 555 | } | ||
| 556 | |||
| 557 | |||
| 558 | HRESULT ScaRemoveAppPool( | ||
| 559 | __in IMSAdminBase* piMetabase, | ||
| 560 | __in SCA_APPPOOL* psap | ||
| 561 | ) | ||
| 562 | { | ||
| 563 | Assert(piMetabase && psap); | ||
| 564 | |||
| 565 | HRESULT hr = S_OK; | ||
| 566 | |||
| 567 | // simply remove the root key and everything else is pulled at the same time | ||
| 568 | if (0 != lstrlenW(psap->wzKey)) | ||
| 569 | { | ||
| 570 | hr = ScaDeleteMetabaseKey(piMetabase, psap->wzKey, L""); | ||
| 571 | ExitOnFailure(hr, "failed to delete AppPool key: %ls", psap->wzKey); | ||
| 572 | } | ||
| 573 | |||
| 574 | // TODO: Maybe check to make sure any web sites that are using this AppPool are put back in the 'DefaultAppPool' | ||
| 575 | |||
| 576 | LExit: | ||
| 577 | return hr; | ||
| 578 | } | ||
| 579 | |||
| 580 | |||
| 581 | HRESULT AddAppPoolToList( | ||
| 582 | __in SCA_APPPOOL** ppsapList | ||
| 583 | ) | ||
| 584 | { | ||
| 585 | HRESULT hr = S_OK; | ||
| 586 | SCA_APPPOOL* psap = static_cast<SCA_APPPOOL*>(MemAlloc(sizeof(SCA_APPPOOL), TRUE)); | ||
| 587 | ExitOnNull(psap, hr, E_OUTOFMEMORY, "failed to allocate memory for new element in app pool list"); | ||
| 588 | |||
| 589 | psap->psapNext = *ppsapList; | ||
| 590 | *ppsapList = psap; | ||
| 591 | |||
| 592 | LExit: | ||
| 593 | return hr; | ||
| 594 | } | ||
diff --git a/src/ext/Iis/ca/scaapppool.h b/src/ext/Iis/ca/scaapppool.h new file mode 100644 index 00000000..68575fcb --- /dev/null +++ b/src/ext/Iis/ca/scaapppool.h | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scauser.h" | ||
| 6 | |||
| 7 | // Identity | ||
| 8 | #define APATTR_NETSERVICE 0x0001 // Network Service | ||
| 9 | #define APATTR_LOCSERVICE 0x0002 // Local Service | ||
| 10 | #define APATTR_LOCSYSTEM 0x0004 // Local System | ||
| 11 | #define APATTR_OTHERUSER 0x0008 // Other User | ||
| 12 | |||
| 13 | struct SCA_APPPOOL | ||
| 14 | { | ||
| 15 | // iis app pool configuation information | ||
| 16 | WCHAR wzAppPool[MAX_DARWIN_KEY + 1]; | ||
| 17 | WCHAR wzName[METADATA_MAX_NAME_LEN + 1]; | ||
| 18 | WCHAR wzKey[METADATA_MAX_NAME_LEN + 1]; | ||
| 19 | WCHAR wzComponent[METADATA_MAX_NAME_LEN + 1]; | ||
| 20 | BOOL fHasComponent; | ||
| 21 | INSTALLSTATE isInstalled; | ||
| 22 | INSTALLSTATE isAction; | ||
| 23 | INT iAttributes; | ||
| 24 | |||
| 25 | SCA_USER suUser; | ||
| 26 | |||
| 27 | INT iRecycleRequests; | ||
| 28 | INT iRecycleMinutes; | ||
| 29 | WCHAR wzRecycleTimes[MAX_DARWIN_KEY + 1]; | ||
| 30 | INT iVirtualMemory; | ||
| 31 | INT iPrivateMemory; | ||
| 32 | |||
| 33 | INT iIdleTimeout; | ||
| 34 | INT iQueueLimit; | ||
| 35 | WCHAR wzCpuMon[MAX_DARWIN_KEY + 1]; | ||
| 36 | INT iMaxProcesses; | ||
| 37 | WCHAR wzManagedPipelineMode[MAX_DARWIN_KEY + 1]; | ||
| 38 | WCHAR wzManagedRuntimeVersion[MAX_DARWIN_KEY + 1]; | ||
| 39 | |||
| 40 | int iCompAttributes; | ||
| 41 | |||
| 42 | SCA_APPPOOL *psapNext; | ||
| 43 | }; | ||
| 44 | |||
| 45 | |||
| 46 | // prototypes | ||
| 47 | |||
| 48 | HRESULT ScaAppPoolRead( | ||
| 49 | __inout SCA_APPPOOL** ppsapList, | ||
| 50 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 51 | __inout LPWSTR *ppwzCustomActionData | ||
| 52 | ); | ||
| 53 | |||
| 54 | void ScaAppPoolFreeList( | ||
| 55 | __in SCA_APPPOOL* psapList | ||
| 56 | ); | ||
| 57 | |||
| 58 | HRESULT ScaFindAppPool( | ||
| 59 | __in IMSAdminBase* piMetabase, | ||
| 60 | __in LPCWSTR wzAppPool, | ||
| 61 | __out_ecount(cchName) LPWSTR wzName, | ||
| 62 | __in DWORD cchName, | ||
| 63 | __in SCA_APPPOOL *psapList | ||
| 64 | ); | ||
| 65 | |||
| 66 | HRESULT ScaAppPoolInstall( | ||
| 67 | __in IMSAdminBase* piMetabase, | ||
| 68 | __in SCA_APPPOOL* psapList | ||
| 69 | ); | ||
| 70 | |||
| 71 | HRESULT ScaAppPoolUninstall( | ||
| 72 | __in IMSAdminBase* piMetabase, | ||
| 73 | __in SCA_APPPOOL* psapList | ||
| 74 | ); | ||
| 75 | |||
| 76 | HRESULT ScaWriteAppPool( | ||
| 77 | __in IMSAdminBase* piMetabase, | ||
| 78 | __in SCA_APPPOOL* psap | ||
| 79 | ); | ||
| 80 | |||
| 81 | HRESULT ScaRemoveAppPool( | ||
| 82 | __in IMSAdminBase* piMetabase, | ||
| 83 | __in SCA_APPPOOL* psap | ||
| 84 | ); | ||
| 85 | |||
| 86 | HRESULT AddAppPoolToList( | ||
| 87 | __in SCA_APPPOOL** ppsapList | ||
| 88 | ); | ||
diff --git a/src/ext/Iis/ca/scaapppool7.cpp b/src/ext/Iis/ca/scaapppool7.cpp new file mode 100644 index 00000000..0fac4346 --- /dev/null +++ b/src/ext/Iis/ca/scaapppool7.cpp | |||
| @@ -0,0 +1,401 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // prototypes | ||
| 6 | static HRESULT AppPoolExists( | ||
| 7 | __in LPCWSTR wzAppPool | ||
| 8 | ); | ||
| 9 | |||
| 10 | // functions | ||
| 11 | HRESULT ScaFindAppPool7( | ||
| 12 | __in LPCWSTR wzAppPool, | ||
| 13 | __out_ecount(cchName) LPWSTR wzName, | ||
| 14 | __in DWORD cchName, | ||
| 15 | __in SCA_APPPOOL *psapList | ||
| 16 | ) | ||
| 17 | { | ||
| 18 | Assert(wzAppPool && *wzAppPool && wzName && *wzName); | ||
| 19 | |||
| 20 | HRESULT hr = S_OK; | ||
| 21 | |||
| 22 | // check memory first | ||
| 23 | SCA_APPPOOL* psap = psapList; | ||
| 24 | for (; psap; psap = psap->psapNext) | ||
| 25 | { | ||
| 26 | if (0 == wcscmp(psap->wzAppPool, wzAppPool)) | ||
| 27 | { | ||
| 28 | break; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | ExitOnNull(psap, hr, HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Could not find the app pool: %ls", wzAppPool); | ||
| 32 | |||
| 33 | // copy the web app pool name | ||
| 34 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 35 | hr = ::StringCchCopyW(wzName, cchName, psap->wzName); | ||
| 36 | ExitOnFailure(hr, "failed to copy app pool name while finding app pool: %ls", psap->wzName); | ||
| 37 | |||
| 38 | // if it's not being installed now, check if it exists already | ||
| 39 | if (!psap->fHasComponent) | ||
| 40 | { | ||
| 41 | hr = AppPoolExists(psap->wzName); | ||
| 42 | ExitOnFailure(hr, "failed to check for existence of app pool: %ls", psap->wzName); | ||
| 43 | } | ||
| 44 | |||
| 45 | LExit: | ||
| 46 | return hr; | ||
| 47 | } | ||
| 48 | |||
| 49 | |||
| 50 | static HRESULT AppPoolExists( | ||
| 51 | __in LPCWSTR /*wzAppPool*/ | ||
| 52 | ) | ||
| 53 | { | ||
| 54 | HRESULT hr = S_OK; | ||
| 55 | |||
| 56 | //this function checks for existance of app pool in IIS7 config | ||
| 57 | //at schedule time, we will defer this to execute time. | ||
| 58 | |||
| 59 | return hr; | ||
| 60 | } | ||
| 61 | |||
| 62 | |||
| 63 | HRESULT ScaAppPoolInstall7( | ||
| 64 | __in SCA_APPPOOL* psapList | ||
| 65 | ) | ||
| 66 | { | ||
| 67 | HRESULT hr = S_OK; | ||
| 68 | |||
| 69 | for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext) | ||
| 70 | { | ||
| 71 | // if we are installing the app pool | ||
| 72 | if (psap->fHasComponent && WcaIsInstalling(psap->isInstalled, psap->isAction)) | ||
| 73 | { | ||
| 74 | hr = ScaWriteAppPool7(psap); | ||
| 75 | ExitOnFailure(hr, "failed to write AppPool '%ls' to metabase", psap->wzAppPool); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | LExit: | ||
| 80 | return hr; | ||
| 81 | } | ||
| 82 | |||
| 83 | |||
| 84 | HRESULT ScaAppPoolUninstall7( | ||
| 85 | __in SCA_APPPOOL* psapList | ||
| 86 | ) | ||
| 87 | { | ||
| 88 | |||
| 89 | HRESULT hr = S_OK; | ||
| 90 | |||
| 91 | for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext) | ||
| 92 | { | ||
| 93 | // if we are uninstalling the app pool | ||
| 94 | if (psap->fHasComponent && WcaIsUninstalling(psap->isInstalled, psap->isAction)) | ||
| 95 | { | ||
| 96 | hr = ScaRemoveAppPool7(psap); | ||
| 97 | ExitOnFailure(hr, "Failed to remove AppPool '%ls' from metabase", psap->wzAppPool); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | LExit: | ||
| 102 | return hr; | ||
| 103 | } | ||
| 104 | |||
| 105 | |||
| 106 | HRESULT ScaWriteAppPool7( | ||
| 107 | __in const SCA_APPPOOL* psap | ||
| 108 | ) | ||
| 109 | { | ||
| 110 | Assert(psap); | ||
| 111 | |||
| 112 | HRESULT hr = S_OK; | ||
| 113 | DWORD dwIdentity = 0xFFFFFFFF; | ||
| 114 | LPWSTR pwzValue = NULL; | ||
| 115 | LPWSTR wz = NULL; | ||
| 116 | |||
| 117 | //create the app pool | ||
| 118 | hr = ScaWriteConfigID(IIS_APPPOOL); | ||
| 119 | ExitOnFailure(hr, "failed to write AppPool key."); | ||
| 120 | |||
| 121 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 122 | ExitOnFailure(hr, "failed to write AppPool create action."); | ||
| 123 | |||
| 124 | hr = ScaWriteConfigString(psap->wzName); | ||
| 125 | ExitOnFailure(hr, "failed to write AppPool name: %ls", psap->wzName); | ||
| 126 | |||
| 127 | // Now do all the optional stuff | ||
| 128 | |||
| 129 | // Set the AppPool Recycling Tab | ||
| 130 | if (MSI_NULL_INTEGER != psap->iRecycleMinutes) | ||
| 131 | { | ||
| 132 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_MIN); | ||
| 133 | ExitOnFailure(hr, "failed to set periodic restart time id"); | ||
| 134 | hr = ScaWriteConfigInteger(psap->iRecycleMinutes); | ||
| 135 | ExitOnFailure(hr, "failed to set periodic restart time"); | ||
| 136 | } | ||
| 137 | |||
| 138 | if (MSI_NULL_INTEGER != psap->iRecycleRequests) | ||
| 139 | { | ||
| 140 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_REQ); | ||
| 141 | ExitOnFailure(hr, "failed to set periodic restart request count id"); | ||
| 142 | hr = ScaWriteConfigInteger(psap->iRecycleRequests); | ||
| 143 | ExitOnFailure(hr, "failed to set periodic restart request count"); | ||
| 144 | } | ||
| 145 | |||
| 146 | if (*psap->wzRecycleTimes) | ||
| 147 | { | ||
| 148 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_TIMES); | ||
| 149 | ExitOnFailure(hr, "failed to set periodic restart schedule id"); | ||
| 150 | hr = ScaWriteConfigString(psap->wzRecycleTimes); | ||
| 151 | ExitOnFailure(hr, "failed to set periodic restart schedule"); | ||
| 152 | } | ||
| 153 | |||
| 154 | if (MSI_NULL_INTEGER != psap->iVirtualMemory) | ||
| 155 | { | ||
| 156 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_VIRMEM); | ||
| 157 | ExitOnFailure(hr, "failed to set periodic restart memory count id"); | ||
| 158 | hr = ScaWriteConfigInteger(psap->iVirtualMemory); | ||
| 159 | ExitOnFailure(hr, "failed to set periodic restart memory count"); | ||
| 160 | } | ||
| 161 | |||
| 162 | if (MSI_NULL_INTEGER != psap->iPrivateMemory) | ||
| 163 | { | ||
| 164 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_PRIVMEM); | ||
| 165 | ExitOnFailure(hr, "failed to set periodic restart private memory count id"); | ||
| 166 | hr = ScaWriteConfigInteger(psap->iPrivateMemory); | ||
| 167 | ExitOnFailure(hr, "failed to set periodic restart private memory count"); | ||
| 168 | } | ||
| 169 | |||
| 170 | // Set AppPool Performance Tab | ||
| 171 | if (MSI_NULL_INTEGER != psap->iIdleTimeout) | ||
| 172 | { | ||
| 173 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_IDLTIMEOUT); | ||
| 174 | ExitOnFailure(hr, "failed to set idle timeout value id"); | ||
| 175 | hr = ScaWriteConfigInteger(psap->iIdleTimeout); | ||
| 176 | ExitOnFailure(hr, "failed to set idle timeout value"); | ||
| 177 | } | ||
| 178 | |||
| 179 | if (MSI_NULL_INTEGER != psap->iQueueLimit) | ||
| 180 | { | ||
| 181 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_QUEUELIMIT); | ||
| 182 | ExitOnFailure(hr, "failed to set request queue limit value id"); | ||
| 183 | hr = ScaWriteConfigInteger(psap->iQueueLimit); | ||
| 184 | ExitOnFailure(hr, "failed to set request queue limit value"); | ||
| 185 | } | ||
| 186 | if (*psap->wzCpuMon) | ||
| 187 | { | ||
| 188 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 189 | hr = ::StrAllocString(&pwzValue, psap->wzCpuMon, 0); | ||
| 190 | ExitOnFailure(hr, "failed to allocate CPUMonitor string"); | ||
| 191 | |||
| 192 | DWORD dwPercent = 0; | ||
| 193 | DWORD dwRefreshMinutes = 0; | ||
| 194 | DWORD dwAction = 0; | ||
| 195 | |||
| 196 | dwPercent = wcstoul(pwzValue, &wz, 10); | ||
| 197 | if (100 < dwPercent) | ||
| 198 | { | ||
| 199 | ExitOnFailure(hr = E_INVALIDARG, "invalid maximum cpu percentage value: %d", dwPercent); | ||
| 200 | } | ||
| 201 | if (wz && L',' == *wz) | ||
| 202 | { | ||
| 203 | ++wz; | ||
| 204 | dwRefreshMinutes = wcstoul(wz, &wz, 10); | ||
| 205 | if (wz && L',' == *wz) | ||
| 206 | { | ||
| 207 | ++wz; | ||
| 208 | dwAction = wcstoul(wz, &wz, 10); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | if (dwPercent) | ||
| 212 | { | ||
| 213 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_CPU_PCT); | ||
| 214 | ExitOnFailure(hr, "failed to set recycle pct id"); | ||
| 215 | hr = ScaWriteConfigInteger(dwPercent); | ||
| 216 | ExitOnFailure(hr, "failed to set CPU percentage max"); | ||
| 217 | } | ||
| 218 | if (dwRefreshMinutes) | ||
| 219 | { | ||
| 220 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_CPU_REFRESH); | ||
| 221 | ExitOnFailure(hr, "failed to set recycle refresh id"); | ||
| 222 | hr = ScaWriteConfigInteger(dwRefreshMinutes); | ||
| 223 | ExitOnFailure(hr, "failed to set refresh CPU minutes"); | ||
| 224 | } | ||
| 225 | if (dwAction) | ||
| 226 | { | ||
| 227 | // 0 = No Action | ||
| 228 | // 1 = Shutdown | ||
| 229 | hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_CPU_ACTION); | ||
| 230 | ExitOnFailure(hr, "failed to set recycle refresh id"); | ||
| 231 | hr = ScaWriteConfigInteger(dwAction); | ||
| 232 | ExitOnFailure(hr, "failed to set CPU action"); | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | if (MSI_NULL_INTEGER != psap->iMaxProcesses) | ||
| 237 | { | ||
| 238 | hr = ScaWriteConfigID(IIS_APPPOOL_MAXPROCESS); | ||
| 239 | ExitOnFailure(hr, "Failed to write max processes config ID"); | ||
| 240 | |||
| 241 | hr = ScaWriteConfigInteger(psap->iMaxProcesses); | ||
| 242 | ExitOnFailure(hr, "failed to set web garden maximum worker processes"); | ||
| 243 | } | ||
| 244 | |||
| 245 | hr = ScaWriteConfigID(IIS_APPPOOL_32BIT); | ||
| 246 | ExitOnFailure(hr, "Failed to write 32 bit app pool config ID"); | ||
| 247 | hr = ScaWriteConfigInteger(psap->iCompAttributes & msidbComponentAttributes64bit ? 0 : 1); | ||
| 248 | ExitOnFailure(hr, "Failed to write 32 bit app pool config value"); | ||
| 249 | |||
| 250 | // | ||
| 251 | // Set the AppPool Identity tab | ||
| 252 | // | ||
| 253 | if (psap->iAttributes & APATTR_APPPOOLIDENTITY) | ||
| 254 | { | ||
| 255 | dwIdentity = 4; | ||
| 256 | } | ||
| 257 | else if (psap->iAttributes & APATTR_NETSERVICE) | ||
| 258 | { | ||
| 259 | dwIdentity = 2; | ||
| 260 | } | ||
| 261 | else if (psap->iAttributes & APATTR_LOCSERVICE) | ||
| 262 | { | ||
| 263 | dwIdentity = 1; | ||
| 264 | } | ||
| 265 | else if (psap->iAttributes & APATTR_LOCSYSTEM) | ||
| 266 | { | ||
| 267 | dwIdentity = 0; | ||
| 268 | } | ||
| 269 | else if (psap->iAttributes & APATTR_OTHERUSER) | ||
| 270 | { | ||
| 271 | if (!*psap->suUser.wzDomain || 0 == _wcsicmp(psap->suUser.wzDomain, L".")) | ||
| 272 | { | ||
| 273 | if (0 == _wcsicmp(psap->suUser.wzName, L"NetworkService")) | ||
| 274 | { | ||
| 275 | dwIdentity = 2; | ||
| 276 | } | ||
| 277 | else if (0 == _wcsicmp(psap->suUser.wzName, L"LocalService")) | ||
| 278 | { | ||
| 279 | dwIdentity = 1; | ||
| 280 | } | ||
| 281 | else if (0 == _wcsicmp(psap->suUser.wzName, L"LocalSystem")) | ||
| 282 | { | ||
| 283 | dwIdentity = 0; | ||
| 284 | } | ||
| 285 | else | ||
| 286 | { | ||
| 287 | dwIdentity = 3; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | else if (0 == _wcsicmp(psap->suUser.wzDomain, L"NT AUTHORITY")) | ||
| 291 | { | ||
| 292 | if (0 == _wcsicmp(psap->suUser.wzName, L"NETWORK SERVICE")) | ||
| 293 | { | ||
| 294 | dwIdentity = 2; | ||
| 295 | } | ||
| 296 | else if (0 == _wcsicmp(psap->suUser.wzName, L"SERVICE")) | ||
| 297 | { | ||
| 298 | dwIdentity = 1; | ||
| 299 | } | ||
| 300 | else if (0 == _wcsicmp(psap->suUser.wzName, L"SYSTEM")) | ||
| 301 | { | ||
| 302 | dwIdentity = 0; | ||
| 303 | } | ||
| 304 | else | ||
| 305 | { | ||
| 306 | dwIdentity = 3; | ||
| 307 | } | ||
| 308 | } | ||
| 309 | else | ||
| 310 | { | ||
| 311 | dwIdentity = 3; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | if (-1 != dwIdentity) | ||
| 316 | { | ||
| 317 | hr = ScaWriteConfigID(IIS_APPPOOL_IDENTITY); | ||
| 318 | ExitOnFailure(hr, "failed to set app pool identity id"); | ||
| 319 | hr = ScaWriteConfigInteger(dwIdentity); | ||
| 320 | ExitOnFailure(hr, "failed to set app pool identity"); | ||
| 321 | |||
| 322 | if (3 == dwIdentity) | ||
| 323 | { | ||
| 324 | if (*psap->suUser.wzDomain) | ||
| 325 | { | ||
| 326 | hr = StrAllocFormatted(&pwzValue, L"%s\\%s", psap->suUser.wzDomain, psap->suUser.wzName); | ||
| 327 | ExitOnFailure(hr, "failed to format user name: %ls domain: %ls", psap->suUser.wzName, psap->suUser.wzDomain); | ||
| 328 | } | ||
| 329 | else | ||
| 330 | { | ||
| 331 | hr = StrAllocFormatted(&pwzValue, L"%s", psap->suUser.wzName); | ||
| 332 | ExitOnFailure(hr, "failed to format user name: %ls", psap->suUser.wzName); | ||
| 333 | } | ||
| 334 | |||
| 335 | hr = ScaWriteConfigID(IIS_APPPOOL_USER); | ||
| 336 | ExitOnFailure(hr, "failed to set app pool identity name id"); | ||
| 337 | hr = ScaWriteConfigString(pwzValue); | ||
| 338 | ExitOnFailure(hr, "failed to set app pool identity name"); | ||
| 339 | |||
| 340 | hr = ScaWriteConfigID(IIS_APPPOOL_PWD); | ||
| 341 | ExitOnFailure(hr, "failed to set app pool identity password id"); | ||
| 342 | hr = ScaWriteConfigString(psap->suUser.wzPassword); | ||
| 343 | ExitOnFailure(hr, "failed to set app pool identity password"); | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | if (*psap->wzManagedPipelineMode) | ||
| 348 | { | ||
| 349 | hr = ScaWriteConfigID(IIS_APPPOOL_MANAGED_PIPELINE_MODE); | ||
| 350 | ExitOnFailure(hr, "failed to set app pool integrated mode"); | ||
| 351 | hr = ScaWriteConfigString(psap->wzManagedPipelineMode); | ||
| 352 | ExitOnFailure(hr, "failed to set app pool managed pipeline mode value"); | ||
| 353 | } | ||
| 354 | |||
| 355 | if (*psap->wzManagedRuntimeVersion) | ||
| 356 | { | ||
| 357 | hr = ScaWriteConfigID(IIS_APPPOOL_MANAGED_RUNTIME_VERSION); | ||
| 358 | ExitOnFailure(hr, "failed to set app pool managed runtime version mode"); | ||
| 359 | hr = ScaWriteConfigString(psap->wzManagedRuntimeVersion); | ||
| 360 | ExitOnFailure(hr, "failed to set app pool managed runtime version value"); | ||
| 361 | } | ||
| 362 | |||
| 363 | // | ||
| 364 | //The number of properties above is variable so we put an end tag in so the | ||
| 365 | //execute CA will know when to stop looking for AppPool properties | ||
| 366 | // | ||
| 367 | hr = ScaWriteConfigID(IIS_APPPOOL_END); | ||
| 368 | ExitOnFailure(hr, "failed to set app pool end of properties id"); | ||
| 369 | |||
| 370 | LExit: | ||
| 371 | ReleaseStr(pwzValue); | ||
| 372 | |||
| 373 | return hr; | ||
| 374 | } | ||
| 375 | |||
| 376 | |||
| 377 | HRESULT ScaRemoveAppPool7( | ||
| 378 | __in const SCA_APPPOOL* psap | ||
| 379 | ) | ||
| 380 | { | ||
| 381 | Assert(psap); | ||
| 382 | |||
| 383 | HRESULT hr = S_OK; | ||
| 384 | |||
| 385 | //do not delete the default App Pool | ||
| 386 | if (0 != _wcsicmp(psap->wzAppPool, L"DefaultAppPool")) | ||
| 387 | { | ||
| 388 | //delete the app pool | ||
| 389 | hr = ScaWriteConfigID(IIS_APPPOOL); | ||
| 390 | ExitOnFailure(hr, "failed to write AppPool key."); | ||
| 391 | |||
| 392 | hr = ScaWriteConfigID(IIS_DELETE); | ||
| 393 | ExitOnFailure(hr, "failed to write AppPool delete action."); | ||
| 394 | |||
| 395 | hr = ScaWriteConfigString(psap->wzName); | ||
| 396 | ExitOnFailure(hr, "failed to delete AppPool: %ls", psap->wzName); | ||
| 397 | } | ||
| 398 | |||
| 399 | LExit: | ||
| 400 | return hr; | ||
| 401 | } | ||
diff --git a/src/ext/Iis/ca/scaapppool7.h b/src/ext/Iis/ca/scaapppool7.h new file mode 100644 index 00000000..1f49d899 --- /dev/null +++ b/src/ext/Iis/ca/scaapppool7.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scauser.h" | ||
| 6 | |||
| 7 | // Identity | ||
| 8 | #define APATTR_NETSERVICE 0x0001 // Network Service | ||
| 9 | #define APATTR_LOCSERVICE 0x0002 // Local Service | ||
| 10 | #define APATTR_LOCSYSTEM 0x0004 // Local System | ||
| 11 | #define APATTR_OTHERUSER 0x0008 // Other User | ||
| 12 | #define APATTR_APPPOOLIDENTITY 0x0010 // ApplicationPoolIdentity | ||
| 13 | |||
| 14 | // prototypes | ||
| 15 | HRESULT ScaFindAppPool7( | ||
| 16 | __in LPCWSTR wzAppPool, | ||
| 17 | __out_ecount(cchName) LPWSTR wzName, | ||
| 18 | __in DWORD cchName, | ||
| 19 | __in SCA_APPPOOL *psapList | ||
| 20 | ); | ||
| 21 | |||
| 22 | HRESULT ScaAppPoolInstall7( | ||
| 23 | __in SCA_APPPOOL* psapList | ||
| 24 | ); | ||
| 25 | |||
| 26 | HRESULT ScaAppPoolUninstall7( | ||
| 27 | __in SCA_APPPOOL* psapList | ||
| 28 | ); | ||
| 29 | |||
| 30 | HRESULT ScaWriteAppPool7( | ||
| 31 | __in const SCA_APPPOOL* psap | ||
| 32 | ); | ||
| 33 | |||
| 34 | HRESULT ScaRemoveAppPool7( | ||
| 35 | __in const SCA_APPPOOL* psap | ||
| 36 | ); | ||
diff --git a/src/ext/Iis/ca/scacert.cpp b/src/ext/Iis/ca/scacert.cpp new file mode 100644 index 00000000..5eae905a --- /dev/null +++ b/src/ext/Iis/ca/scacert.cpp | |||
| @@ -0,0 +1,1482 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // prototypes | ||
| 6 | static HRESULT ConfigureCertificates( | ||
| 7 | __in SCA_ACTION saAction | ||
| 8 | ); | ||
| 9 | |||
| 10 | static LPCWSTR StoreMapping( | ||
| 11 | __in int iStore | ||
| 12 | ); | ||
| 13 | |||
| 14 | static HRESULT FindExistingCertificate( | ||
| 15 | __in LPCWSTR wzName, | ||
| 16 | __in DWORD dwStoreLocation, | ||
| 17 | __in LPCWSTR wzStore, | ||
| 18 | __out BYTE** prgbCertificate, | ||
| 19 | __out DWORD* pcbCertificate | ||
| 20 | ); | ||
| 21 | |||
| 22 | static HRESULT ResolveCertificate( | ||
| 23 | __in LPCWSTR wzId, | ||
| 24 | __in LPCWSTR wzName, | ||
| 25 | __in DWORD dwStoreLocation, | ||
| 26 | __in LPCWSTR wzStoreName, | ||
| 27 | __in DWORD dwAttributess, | ||
| 28 | __in LPCWSTR wzData, | ||
| 29 | __in LPCWSTR wzPFXPassword, | ||
| 30 | __out BYTE** ppbCertificate, | ||
| 31 | __out DWORD* pcbCertificate | ||
| 32 | ); | ||
| 33 | |||
| 34 | static HRESULT ReadCertificateFile( | ||
| 35 | __in LPCWSTR wzPath, | ||
| 36 | __out BYTE** prgbData, | ||
| 37 | __out DWORD* pcbData | ||
| 38 | ); | ||
| 39 | |||
| 40 | static HRESULT CertificateToHash( | ||
| 41 | __in BYTE* pbCertificate, | ||
| 42 | __in DWORD cbCertificate, | ||
| 43 | __in DWORD dwStoreLocation, | ||
| 44 | __in LPCWSTR wzPFXPassword, | ||
| 45 | __in BYTE rgbHash[], | ||
| 46 | __in DWORD cbHash | ||
| 47 | ); | ||
| 48 | |||
| 49 | /* | ||
| 50 | HRESULT ScaGetCertificateByPath(LPCWSTR pwzName, BOOL fIsInstalling, | ||
| 51 | BOOL fIsUninstalling, INT iStore, | ||
| 52 | INT iStoreLocation, LPCWSTR wzSslCertificate, | ||
| 53 | LPCWSTR wzPFXPassword, BSTR* pbstrCertificate, | ||
| 54 | DWORD* pcbCertificate, BYTE* pbaHashBuffer); | ||
| 55 | |||
| 56 | HRESULT ScaGetCertificateByRequest(LPCWSTR pwzName, BOOL fIsInstalling, | ||
| 57 | BOOL fIsUninstalling, INT iStore, | ||
| 58 | INT iStoreLocation, LPCWSTR wzDistinguishedName, | ||
| 59 | LPCWSTR wzCA, BSTR* pbstrCertificate, | ||
| 60 | DWORD* pcbCertificate, BYTE* pbaHashBuffer); | ||
| 61 | |||
| 62 | HRESULT ScaSslNewCertificate(LPCWSTR pwzName, INT iStore, | ||
| 63 | INT iStoreLocation, LPCWSTR wzComputerName, | ||
| 64 | LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthorityOrig, | ||
| 65 | BSTR* pbstrCertificate, DWORD* pcbCertificate, | ||
| 66 | BYTE* pbaHashBuffer); | ||
| 67 | |||
| 68 | HRESULT ScaSslExistingCertificateByName(LPCWSTR pwzName, INT iStore, | ||
| 69 | INT iStoreLocation, BSTR* pbstrCertificate, | ||
| 70 | DWORD* pcbCertificate, BYTE* pbaHashBuffer); | ||
| 71 | |||
| 72 | HRESULT ScaSslExistingCertificateByBinaryData(INT iStore, INT iStoreLocation, | ||
| 73 | BYTE* pwzData, DWORD cchData); | ||
| 74 | |||
| 75 | HRESULT CreateEnroll(ICEnroll2 **hEnroll, INT iStore, | ||
| 76 | INT iStoreLocation); | ||
| 77 | |||
| 78 | HRESULT RequestCertificate(LPCWSTR pwzName, INT iStore, | ||
| 79 | INT iStoreLocation, LPCWSTR wzComputerName, | ||
| 80 | LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthority, | ||
| 81 | BSTR *pbstrCertificate); | ||
| 82 | |||
| 83 | VOID ParseCertificateAuthority(__in LPCWSTR wzCertificateAuthorityOrig, __out LPWSTR *pwzBuffer, | ||
| 84 | __out LPWSTR **hwzCAArray, __out int *piCAArray); | ||
| 85 | */ | ||
| 86 | |||
| 87 | |||
| 88 | LPCWSTR vcsCertQuery = L"SELECT `Certificate`, `Name`, `Component_`, `StoreLocation`, `StoreName`, `Attributes`, `Binary_`, `CertificatePath`, `PFXPassword` FROM `Certificate`"; | ||
| 89 | enum eCertQuery { cqCertificate = 1, cqName, cqComponent, cqStoreLocation, cqStoreName, cqAttributes, cqCertificateBinary, cqCertificatePath, cqPFXPassword }; | ||
| 90 | |||
| 91 | |||
| 92 | /******************************************************************** | ||
| 93 | InstallCertificates - CUSTOM ACTION ENTRY POINT for installing | ||
| 94 | certificates | ||
| 95 | |||
| 96 | ********************************************************************/ | ||
| 97 | extern "C" UINT __stdcall InstallCertificates( | ||
| 98 | __in MSIHANDLE hInstall | ||
| 99 | ) | ||
| 100 | { | ||
| 101 | HRESULT hr = S_OK; | ||
| 102 | UINT er = ERROR_SUCCESS; | ||
| 103 | |||
| 104 | // initialize | ||
| 105 | hr = WcaInitialize(hInstall, "InstallCertificates"); | ||
| 106 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 107 | |||
| 108 | hr = ConfigureCertificates(SCA_ACTION_INSTALL); | ||
| 109 | |||
| 110 | LExit: | ||
| 111 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 112 | return WcaFinalize(er); | ||
| 113 | } | ||
| 114 | |||
| 115 | |||
| 116 | /******************************************************************** | ||
| 117 | UninstallCertificates - CUSTOM ACTION ENTRY POINT for uninstalling | ||
| 118 | certificates | ||
| 119 | |||
| 120 | ********************************************************************/ | ||
| 121 | extern "C" UINT __stdcall UninstallCertificates( | ||
| 122 | __in MSIHANDLE hInstall | ||
| 123 | ) | ||
| 124 | { | ||
| 125 | HRESULT hr = S_OK; | ||
| 126 | UINT er = ERROR_SUCCESS; | ||
| 127 | |||
| 128 | // initialize | ||
| 129 | hr = WcaInitialize(hInstall, "UninstallCertificates"); | ||
| 130 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 131 | |||
| 132 | hr = ConfigureCertificates(SCA_ACTION_UNINSTALL); | ||
| 133 | |||
| 134 | LExit: | ||
| 135 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 136 | return WcaFinalize(er); | ||
| 137 | } | ||
| 138 | |||
| 139 | |||
| 140 | static HRESULT ConfigureCertificates( | ||
| 141 | __in SCA_ACTION saAction | ||
| 142 | ) | ||
| 143 | { | ||
| 144 | //AssertSz(FALSE, "debug ConfigureCertificates()."); | ||
| 145 | |||
| 146 | HRESULT hr = S_OK; | ||
| 147 | DWORD er = ERROR_SUCCESS; | ||
| 148 | |||
| 149 | PMSIHANDLE hViewCertificate; | ||
| 150 | PMSIHANDLE hRecCertificate; | ||
| 151 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
| 152 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
| 153 | |||
| 154 | WCHAR* pwzId = NULL; | ||
| 155 | WCHAR* pwzName = NULL; | ||
| 156 | WCHAR* pwzComponent = NULL; | ||
| 157 | int iData = 0; | ||
| 158 | DWORD dwStoreLocation = 0; | ||
| 159 | LPWSTR pwzStoreName = 0; | ||
| 160 | DWORD dwAttributes = 0; | ||
| 161 | WCHAR* pwzData = NULL; | ||
| 162 | WCHAR* pwzPFXPassword = NULL; | ||
| 163 | WCHAR* pwzCaData = NULL; | ||
| 164 | WCHAR* pwzRollbackCaData = NULL; | ||
| 165 | |||
| 166 | BYTE* pbCertificate = NULL; | ||
| 167 | DWORD cbCertificate = 0; | ||
| 168 | DWORD_PTR cbPFXPassword = 0; | ||
| 169 | |||
| 170 | // Bail quickly if the Certificate table isn't around. | ||
| 171 | if (S_OK != WcaTableExists(L"Certificate")) | ||
| 172 | { | ||
| 173 | WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureCertificates() - required table not present."); | ||
| 174 | ExitFunction1(hr = S_FALSE); | ||
| 175 | } | ||
| 176 | |||
| 177 | // Process the Certificate table. | ||
| 178 | hr = WcaOpenExecuteView(vcsCertQuery, &hViewCertificate); | ||
| 179 | ExitOnFailure(hr, "failed to open view on Certificate table"); | ||
| 180 | |||
| 181 | while (SUCCEEDED(hr = WcaFetchRecord(hViewCertificate, &hRecCertificate))) | ||
| 182 | { | ||
| 183 | hr = WcaGetRecordString(hRecCertificate, cqCertificate, &pwzId); // the id is just useful to have up front | ||
| 184 | ExitOnFailure(hr, "failed to get Certificate.Certificate"); | ||
| 185 | |||
| 186 | hr = WcaGetRecordString(hRecCertificate, cqComponent, &pwzComponent); | ||
| 187 | ExitOnFailure(hr, "failed to get Certificate.Component_"); | ||
| 188 | |||
| 189 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction); | ||
| 190 | hr = HRESULT_FROM_WIN32(er); | ||
| 191 | ExitOnFailure(hr, "failed to get state for component: %ls", pwzComponent); | ||
| 192 | |||
| 193 | if (!(WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL == saAction) && | ||
| 194 | !(WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL == saAction) && | ||
| 195 | !(WcaIsReInstalling(isInstalled, isAction))) | ||
| 196 | { | ||
| 197 | WcaLog(LOGMSG_VERBOSE, "Skipping non-action certificate: %ls", pwzId); | ||
| 198 | continue; | ||
| 199 | } | ||
| 200 | |||
| 201 | // extract the rest of the data from the Certificate table | ||
| 202 | hr = WcaGetRecordFormattedString(hRecCertificate, cqName, &pwzName); | ||
| 203 | ExitOnFailure(hr, "failed to get Certificate.Name"); | ||
| 204 | |||
| 205 | hr = WcaGetRecordInteger(hRecCertificate, cqStoreLocation, &iData); | ||
| 206 | ExitOnFailure(hr, "failed to get Certificate.StoreLocation"); | ||
| 207 | |||
| 208 | switch (iData) | ||
| 209 | { | ||
| 210 | case SCA_CERTSYSTEMSTORE_CURRENTUSER: | ||
| 211 | dwStoreLocation = CERT_SYSTEM_STORE_CURRENT_USER; | ||
| 212 | break; | ||
| 213 | case SCA_CERTSYSTEMSTORE_LOCALMACHINE: | ||
| 214 | dwStoreLocation = CERT_SYSTEM_STORE_LOCAL_MACHINE; | ||
| 215 | break; | ||
| 216 | default: | ||
| 217 | hr = E_INVALIDARG; | ||
| 218 | ExitOnFailure(hr, "Invalid store location value: %d", iData); | ||
| 219 | } | ||
| 220 | |||
| 221 | hr = WcaGetRecordString(hRecCertificate, cqStoreName, &pwzStoreName); | ||
| 222 | ExitOnFailure(hr, "failed to get Certificate.StoreName"); | ||
| 223 | |||
| 224 | hr = WcaGetRecordInteger(hRecCertificate, cqAttributes, reinterpret_cast<int*>(&dwAttributes)); | ||
| 225 | ExitOnFailure(hr, "failed to get Certificate.Attributes"); | ||
| 226 | |||
| 227 | if (dwAttributes & SCA_CERT_ATTRIBUTE_BINARYDATA) | ||
| 228 | { | ||
| 229 | hr = WcaGetRecordString(hRecCertificate, cqCertificateBinary, &pwzData); | ||
| 230 | ExitOnFailure(hr, "failed to get Certificate.Binary_"); | ||
| 231 | } | ||
| 232 | else | ||
| 233 | { | ||
| 234 | hr = WcaGetRecordFormattedString(hRecCertificate, cqCertificatePath, &pwzData); | ||
| 235 | ExitOnFailure(hr, "failed to get Certificate.CertificatePath"); | ||
| 236 | } | ||
| 237 | |||
| 238 | hr = WcaGetRecordFormattedString(hRecCertificate, cqPFXPassword, &pwzPFXPassword); | ||
| 239 | ExitOnFailure(hr, "failed to get Certificate.PFXPassword"); | ||
| 240 | |||
| 241 | // Write the common data (for both install and uninstall) to the CustomActionData | ||
| 242 | // to pass data to the deferred CustomAction. | ||
| 243 | hr = StrAllocString(&pwzCaData, pwzName, 0); | ||
| 244 | ExitOnFailure(hr, "Failed to pass Certificate.Certificate to deferred CustomAction."); | ||
| 245 | hr = WcaWriteStringToCaData(pwzStoreName, &pwzCaData); | ||
| 246 | ExitOnFailure(hr, "Failed to pass Certificate.StoreName to deferred CustomAction."); | ||
| 247 | hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCaData); | ||
| 248 | ExitOnFailure(hr, "Failed to pass Certificate.Attributes to deferred CustomAction."); | ||
| 249 | |||
| 250 | // Copy the rollback data from the deferred data because it's the same up to this point. | ||
| 251 | hr = StrAllocString(&pwzRollbackCaData, pwzCaData, 0); | ||
| 252 | ExitOnFailure(hr, "Failed to allocate string for rollback CustomAction."); | ||
| 253 | |||
| 254 | // Finally, schedule the correct deferred CustomAction to actually do work. | ||
| 255 | LPCWSTR wzAction = NULL; | ||
| 256 | LPCWSTR wzRollbackAction = NULL; | ||
| 257 | DWORD dwCost = 0; | ||
| 258 | if (SCA_ACTION_UNINSTALL == saAction) | ||
| 259 | { | ||
| 260 | // Find an existing certificate one (if there is one) to so we have it for rollback. | ||
| 261 | hr = FindExistingCertificate(pwzName, dwStoreLocation, pwzStoreName, &pbCertificate, &cbCertificate); | ||
| 262 | ExitOnFailure(hr, "Failed to search for existing certificate with friendly name: %ls", pwzName); | ||
| 263 | |||
| 264 | if (pbCertificate) | ||
| 265 | { | ||
| 266 | hr = WcaWriteStreamToCaData(pbCertificate, cbCertificate, &pwzRollbackCaData); | ||
| 267 | ExitOnFailure(hr, "Failed to pass Certificate.Data to rollback CustomAction."); | ||
| 268 | |||
| 269 | hr = WcaWriteStringToCaData(pwzPFXPassword, &pwzRollbackCaData); | ||
| 270 | ExitOnFailure(hr, "Failed to pass Certificate.PFXPassword to rollback CustomAction."); | ||
| 271 | |||
| 272 | hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCaData); | ||
| 273 | ExitOnFailure(hr, "Failed to pass Certificate.Attributes to deferred CustomAction."); | ||
| 274 | } | ||
| 275 | |||
| 276 | // Pick the right action to run based on what store we're uninstalling from. | ||
| 277 | if (CERT_SYSTEM_STORE_LOCAL_MACHINE == dwStoreLocation) | ||
| 278 | { | ||
| 279 | wzAction = CUSTOM_ACTION_DECORATION(L"DeleteMachineCertificate"); | ||
| 280 | if (pbCertificate) | ||
| 281 | { | ||
| 282 | wzRollbackAction = L"RollbackDeleteMachineCertificate"; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | else | ||
| 286 | { | ||
| 287 | wzAction = CUSTOM_ACTION_DECORATION(L"DeleteUserCertificate"); | ||
| 288 | if (pbCertificate) | ||
| 289 | { | ||
| 290 | wzRollbackAction = L"RollbackDeleteUserCertificate"; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | dwCost = COST_CERT_DELETE; | ||
| 294 | } | ||
| 295 | else | ||
| 296 | { | ||
| 297 | // Actually get the certificate, resolve it to a blob, and get the blob's hash. | ||
| 298 | hr = ResolveCertificate(pwzId, pwzName, dwStoreLocation, pwzStoreName, dwAttributes, pwzData, pwzPFXPassword, &pbCertificate, &cbCertificate); | ||
| 299 | ExitOnFailure(hr, "Failed to resolve certificate: %ls", pwzId); | ||
| 300 | |||
| 301 | hr = WcaWriteStreamToCaData(pbCertificate, cbCertificate, &pwzCaData); | ||
| 302 | ExitOnFailure(hr, "Failed to pass Certificate.Data to deferred CustomAction."); | ||
| 303 | |||
| 304 | hr = WcaWriteStringToCaData(pwzPFXPassword, &pwzCaData); | ||
| 305 | ExitOnFailure(hr, "Failed to pass Certificate.PFXPassword to deferred CustomAction."); | ||
| 306 | |||
| 307 | // Pick the right action to run based on what store we're installing into. | ||
| 308 | if (CERT_SYSTEM_STORE_LOCAL_MACHINE == dwStoreLocation) | ||
| 309 | { | ||
| 310 | wzAction = CUSTOM_ACTION_DECORATION(L"AddMachineCertificate"); | ||
| 311 | wzRollbackAction = CUSTOM_ACTION_DECORATION(L"RollbackAddMachineCertificate"); | ||
| 312 | } | ||
| 313 | else | ||
| 314 | { | ||
| 315 | wzAction = CUSTOM_ACTION_DECORATION(L"AddUserCertificate"); | ||
| 316 | wzRollbackAction = CUSTOM_ACTION_DECORATION(L"RollbackAddUserCertificate"); | ||
| 317 | } | ||
| 318 | dwCost = COST_CERT_ADD; | ||
| 319 | } | ||
| 320 | |||
| 321 | if (wzRollbackAction) | ||
| 322 | { | ||
| 323 | hr = WcaDoDeferredAction(wzRollbackAction, pwzRollbackCaData, dwCost); | ||
| 324 | ExitOnFailure(hr, "Failed to schedule rollback certificate action '%ls' for: %ls", wzRollbackAction, pwzId); | ||
| 325 | } | ||
| 326 | |||
| 327 | hr = WcaDoDeferredAction(wzAction, pwzCaData, dwCost); | ||
| 328 | ExitOnFailure(hr, "Failed to schedule certificate action '%ls' for: %ls", wzAction, pwzId); | ||
| 329 | |||
| 330 | // Clean up for the next certificate. | ||
| 331 | ReleaseNullMem(pbCertificate); | ||
| 332 | } | ||
| 333 | |||
| 334 | if (E_NOMOREITEMS == hr) | ||
| 335 | { | ||
| 336 | hr = S_OK; | ||
| 337 | } | ||
| 338 | |||
| 339 | LExit: | ||
| 340 | if (NULL != pwzPFXPassword && SUCCEEDED(StrSize(pwzPFXPassword, &cbPFXPassword))) | ||
| 341 | { | ||
| 342 | SecureZeroMemory(pwzPFXPassword, cbPFXPassword); | ||
| 343 | } | ||
| 344 | |||
| 345 | ReleaseMem(pbCertificate); | ||
| 346 | ReleaseStr(pwzCaData); | ||
| 347 | ReleaseStr(pwzPFXPassword); | ||
| 348 | ReleaseStr(pwzData); | ||
| 349 | ReleaseStr(pwzName); | ||
| 350 | ReleaseStr(pwzStoreName); | ||
| 351 | ReleaseStr(pwzComponent); | ||
| 352 | ReleaseStr(pwzId); | ||
| 353 | |||
| 354 | return hr; | ||
| 355 | } | ||
| 356 | |||
| 357 | |||
| 358 | static HRESULT ResolveCertificate( | ||
| 359 | __in LPCWSTR wzId, | ||
| 360 | __in LPCWSTR /*wzName*/, | ||
| 361 | __in DWORD dwStoreLocation, | ||
| 362 | __in LPCWSTR /*wzStoreName*/, | ||
| 363 | __in DWORD dwAttributes, | ||
| 364 | __in LPCWSTR wzData, | ||
| 365 | __in LPCWSTR wzPFXPassword, | ||
| 366 | __out BYTE** ppbCertificate, | ||
| 367 | __out DWORD* pcbCertificate | ||
| 368 | ) | ||
| 369 | { | ||
| 370 | HRESULT hr = S_OK; | ||
| 371 | |||
| 372 | LPWSTR pwzSql = NULL; | ||
| 373 | PMSIHANDLE hView; | ||
| 374 | PMSIHANDLE hRec; | ||
| 375 | MSIHANDLE hCertificateHashView = NULL; | ||
| 376 | MSIHANDLE hCertificateHashColumns = NULL; | ||
| 377 | |||
| 378 | BYTE rgbCertificateHash[CB_CERTIFICATE_HASH] = { 0 }; | ||
| 379 | WCHAR wzEncodedCertificateHash[CB_CERTIFICATE_HASH * 2 + 1] = { 0 }; | ||
| 380 | |||
| 381 | PMSIHANDLE hViewCertificateRequest, hRecCertificateRequest; | ||
| 382 | |||
| 383 | WCHAR* pwzDistinguishedName = NULL; | ||
| 384 | WCHAR* pwzCA = NULL; | ||
| 385 | |||
| 386 | BYTE* pbData = NULL; | ||
| 387 | DWORD cbData = 0; | ||
| 388 | |||
| 389 | if (dwAttributes & SCA_CERT_ATTRIBUTE_REQUEST) | ||
| 390 | { | ||
| 391 | hr = E_NOTIMPL; | ||
| 392 | ExitOnFailure(hr, "Installing certificates by requesting them from a certificate authority is not currently supported"); | ||
| 393 | //if (dwAttributes & SCA_CERT_ATTRIBUTE_OVERWRITE) | ||
| 394 | //{ | ||
| 395 | // // try to overwrite with the patch to a cert file | ||
| 396 | // WcaLog(LOGMSG_VERBOSE, "ConfigureCertificates - Overwrite with SSLCERTIFICATE"); | ||
| 397 | // hr = ScaGetCertificateByPath(pwzName, fIsInstalling, fIsUninstalling, | ||
| 398 | // iStore, iStoreLocation, pwzData, wzPFXPassword, pbstrCertificate, pcbCertificate, pbaHashBuffer); | ||
| 399 | //} | ||
| 400 | //if (hr != S_OK) | ||
| 401 | //{ | ||
| 402 | // if (fIsUninstalling && !fIsInstalling) | ||
| 403 | // { | ||
| 404 | // // for uninstall, we just want to find the existing certificate | ||
| 405 | // hr = ScaSslExistingCertificateByName(pwzName, iStore, iStoreLocation, pbstrCertificate, pcbCertificate, pbaHashBuffer); | ||
| 406 | // ExitOnFailure(hr, "Failed Retrieving existing certificate during uninstall"); | ||
| 407 | // // ok if no existing cert | ||
| 408 | // if (S_OK != hr) | ||
| 409 | // hr = S_OK; | ||
| 410 | // } | ||
| 411 | // else | ||
| 412 | // { | ||
| 413 | // // still no certificate | ||
| 414 | // // user has request this certificate, try to locate DistinguishedName and CA | ||
| 415 | // hr = WcaTableExists(L"CertificateRequest"); | ||
| 416 | // ExitOnFailure(hr, "CertificateRequest is referenced but not found"); | ||
| 417 | // WcaLog(LOGMSG_VERBOSE, "ConfigureCertificates - CertificateRequest table present"); | ||
| 418 | // cchSQLView = 255 + lstrlenW(pwzName); | ||
| 419 | // pwzSQLView = new WCHAR[cchSQLView]; | ||
| 420 | // if (pwzSQLView) | ||
| 421 | // { | ||
| 422 | // hr = ::StringCchPrintfW(pwzSQLView, cchSQLView, L"SELECT `DistinguishedName`, `CA` FROM `CertificateRequest` WHERE `Certificate_`=\'%s\'", pwzName); | ||
| 423 | // ExitOnFailure(hr, "::StringCchPrintfW failed"); | ||
| 424 | // hr = WcaOpenExecuteView(pwzSQLView, &hViewCertificateRequest); | ||
| 425 | // ExitOnFailure(hr, "failed to open view on CertificateRequest table"); | ||
| 426 | // hr = WcaFetchSingleRecord(hViewCertificateRequest, &hRecCertificateRequest); | ||
| 427 | // ExitOnFailure(hr, "failed to retrieve request from CertificateRequest table"); | ||
| 428 | // hr = WcaGetRecordString(hRecCertificateRequest, 1, &pwzDistinguishedName); | ||
| 429 | // ExitOnFailure(hr, "failed to get DistinguishedName"); | ||
| 430 | // hr = WcaGetRecordString(hRecCertificateRequest, 2, &pwzCA); | ||
| 431 | // ExitOnFailure(hr, "failed to get CA"); | ||
| 432 | // if (pwzDistinguishedName && pwzCA && *pwzDistinguishedName && *pwzCA) | ||
| 433 | // { | ||
| 434 | // hr = ScaGetCertificateByRequest(pwzName, fIsInstalling, fIsUninstalling, iStore, iStoreLocation, pwzDistinguishedName, pwzCA, pbstrCertificate, pcbCertificate, pbaHashBuffer); | ||
| 435 | // } | ||
| 436 | // else | ||
| 437 | // { | ||
| 438 | // hr = E_FAIL; | ||
| 439 | // ExitOnFailure(hr, "CertificateRequest entry is empty"); | ||
| 440 | // } | ||
| 441 | // } | ||
| 442 | // else | ||
| 443 | // { | ||
| 444 | // hr = E_FAIL; | ||
| 445 | // ExitOnFailure(hr, "Out of memory"); | ||
| 446 | // } | ||
| 447 | // } | ||
| 448 | //} | ||
| 449 | } | ||
| 450 | else if (dwAttributes & SCA_CERT_ATTRIBUTE_BINARYDATA) | ||
| 451 | { | ||
| 452 | // get the binary stream in Binary | ||
| 453 | hr = WcaTableExists(L"Binary"); | ||
| 454 | if (S_OK != hr) | ||
| 455 | { | ||
| 456 | if (SUCCEEDED(hr)) | ||
| 457 | { | ||
| 458 | hr = E_UNEXPECTED; | ||
| 459 | } | ||
| 460 | ExitOnFailure(hr, "Binary was referenced but there is no Binary table."); | ||
| 461 | } | ||
| 462 | |||
| 463 | hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzData); | ||
| 464 | ExitOnFailure(hr, "Failed to allocate Binary table query."); | ||
| 465 | |||
| 466 | hr = WcaOpenExecuteView(pwzSql, &hView); | ||
| 467 | ExitOnFailure(hr, "Failed to open view on Binary table"); | ||
| 468 | |||
| 469 | hr = WcaFetchSingleRecord(hView, &hRec); | ||
| 470 | ExitOnFailure(hr, "Failed to retrieve request from Binary table"); | ||
| 471 | |||
| 472 | hr = WcaGetRecordStream(hRec, 1, &pbData, &cbData); | ||
| 473 | ExitOnFailure(hr, "Failed to ready Binary.Data for certificate."); | ||
| 474 | } | ||
| 475 | else if (dwAttributes == SCA_CERT_ATTRIBUTE_DEFAULT) | ||
| 476 | { | ||
| 477 | hr = ReadCertificateFile(wzData, &pbData, &cbData); | ||
| 478 | ExitOnFailure(hr, "Failed to read certificate from file path."); | ||
| 479 | } | ||
| 480 | else | ||
| 481 | { | ||
| 482 | hr = E_INVALIDARG; | ||
| 483 | ExitOnFailure(hr, "Invalid Certificate.Attributes."); | ||
| 484 | } | ||
| 485 | |||
| 486 | // If we have loaded a certificate, update the Certificate.Hash column. | ||
| 487 | if (pbData) | ||
| 488 | { | ||
| 489 | hr = CertificateToHash(pbData, cbData, dwStoreLocation, wzPFXPassword, rgbCertificateHash, countof(rgbCertificateHash)); | ||
| 490 | ExitOnFailure(hr, "Failed to get SHA1 hash of certificate."); | ||
| 491 | |||
| 492 | hr = StrHexEncode(rgbCertificateHash, countof(rgbCertificateHash), wzEncodedCertificateHash, countof(wzEncodedCertificateHash)); | ||
| 493 | ExitOnFailure(hr, "Failed to hex encode SHA1 hash of certificate."); | ||
| 494 | |||
| 495 | // Update the CertificateHash table. | ||
| 496 | hr = WcaAddTempRecord(&hCertificateHashView, &hCertificateHashColumns, L"CertificateHash", NULL, 0, 2, wzId, wzEncodedCertificateHash); | ||
| 497 | ExitOnFailure(hr, "Failed to add encoded has for certificate: %ls", wzId); | ||
| 498 | } | ||
| 499 | |||
| 500 | *ppbCertificate = pbData; | ||
| 501 | *pcbCertificate = cbData; | ||
| 502 | pbData = NULL; | ||
| 503 | |||
| 504 | LExit: | ||
| 505 | if (hCertificateHashColumns) | ||
| 506 | { | ||
| 507 | ::MsiCloseHandle(hCertificateHashColumns); | ||
| 508 | } | ||
| 509 | |||
| 510 | if (hCertificateHashView) | ||
| 511 | { | ||
| 512 | ::MsiCloseHandle(hCertificateHashView); | ||
| 513 | } | ||
| 514 | |||
| 515 | ReleaseStr(pwzDistinguishedName); | ||
| 516 | ReleaseStr(pwzCA); | ||
| 517 | ReleaseMem(pbData); | ||
| 518 | ReleaseStr(pwzSql); | ||
| 519 | |||
| 520 | return hr; | ||
| 521 | } | ||
| 522 | |||
| 523 | |||
| 524 | static HRESULT ReadCertificateFile( | ||
| 525 | __in LPCWSTR wzPath, | ||
| 526 | __out BYTE** prgbData, | ||
| 527 | __out DWORD* pcbData | ||
| 528 | ) | ||
| 529 | { | ||
| 530 | HRESULT hr = S_OK; | ||
| 531 | |||
| 532 | PCCERT_CONTEXT pCertContext = NULL; | ||
| 533 | DWORD dwContentType; | ||
| 534 | BYTE* pbData = NULL; | ||
| 535 | DWORD cbData = 0; | ||
| 536 | |||
| 537 | if (!::CryptQueryObject(CERT_QUERY_OBJECT_FILE, reinterpret_cast<LPCVOID>(wzPath), CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &dwContentType, NULL, NULL, NULL, (LPCVOID*)&pCertContext)) | ||
| 538 | { | ||
| 539 | ExitOnFailure(hr, "Failed to read certificate from file: %ls", wzPath); | ||
| 540 | } | ||
| 541 | |||
| 542 | if (pCertContext) | ||
| 543 | { | ||
| 544 | cbData = pCertContext->cbCertEncoded; | ||
| 545 | pbData = static_cast<BYTE*>(MemAlloc(cbData, FALSE)); | ||
| 546 | ExitOnNull(pbData, hr, E_OUTOFMEMORY, "Failed to allocate memory to read certificate from file: %ls", wzPath); | ||
| 547 | |||
| 548 | CopyMemory(pbData, pCertContext->pbCertEncoded, pCertContext->cbCertEncoded); | ||
| 549 | } | ||
| 550 | else | ||
| 551 | { | ||
| 552 | // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX. | ||
| 553 | if (dwContentType & CERT_QUERY_CONTENT_PFX) | ||
| 554 | { | ||
| 555 | hr = FileRead(&pbData, &cbData, wzPath); | ||
| 556 | ExitOnFailure(hr, "Failed to read PFX file: %ls", wzPath); | ||
| 557 | } | ||
| 558 | else | ||
| 559 | { | ||
| 560 | hr = E_UNEXPECTED; | ||
| 561 | ExitOnFailure(hr, "Unexpected certificate type read from disk."); | ||
| 562 | } | ||
| 563 | } | ||
| 564 | |||
| 565 | *pcbData = cbData; | ||
| 566 | *prgbData = pbData; | ||
| 567 | pbData = NULL; | ||
| 568 | |||
| 569 | LExit: | ||
| 570 | ReleaseMem(pbData); | ||
| 571 | return hr; | ||
| 572 | } | ||
| 573 | |||
| 574 | |||
| 575 | static HRESULT CertificateToHash( | ||
| 576 | __in BYTE* pbCertificate, | ||
| 577 | __in DWORD cbCertificate, | ||
| 578 | __in DWORD dwStoreLocation, | ||
| 579 | __in LPCWSTR wzPFXPassword, | ||
| 580 | __in BYTE rgbHash[], | ||
| 581 | __in DWORD cbHash | ||
| 582 | ) | ||
| 583 | { | ||
| 584 | HRESULT hr = S_OK; | ||
| 585 | |||
| 586 | HCERTSTORE hPfxCertStore = NULL; | ||
| 587 | PCCERT_CONTEXT pCertContext = NULL; | ||
| 588 | PCCERT_CONTEXT pCertContextEnum = NULL; | ||
| 589 | CRYPT_DATA_BLOB blob = { 0 }; | ||
| 590 | CRYPT_KEY_PROV_INFO* pPfxInfo = NULL; | ||
| 591 | DWORD dwKeyset = (CERT_SYSTEM_STORE_CURRENT_USER == dwStoreLocation) ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET; | ||
| 592 | DWORD dwEncodingType; | ||
| 593 | DWORD dwContentType; | ||
| 594 | DWORD dwFormatType; | ||
| 595 | |||
| 596 | blob.pbData = pbCertificate; | ||
| 597 | blob.cbData = cbCertificate; | ||
| 598 | |||
| 599 | if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertContext)) | ||
| 600 | { | ||
| 601 | ExitWithLastError(hr, "Failed to process certificate as a valid certificate."); | ||
| 602 | } | ||
| 603 | |||
| 604 | if (!pCertContext) | ||
| 605 | { | ||
| 606 | // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX. | ||
| 607 | if (dwContentType & CERT_QUERY_CONTENT_PFX) | ||
| 608 | { | ||
| 609 | // If we fail and our password is blank, also try passing in NULL for the password (according to the docs) | ||
| 610 | hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, dwKeyset); | ||
| 611 | if (NULL == hPfxCertStore && !*wzPFXPassword) | ||
| 612 | { | ||
| 613 | hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, NULL, dwKeyset); | ||
| 614 | } | ||
| 615 | ExitOnNullWithLastError(hPfxCertStore, hr, "Failed to open PFX file."); | ||
| 616 | |||
| 617 | // Find the first cert with a private key, or just use the last one | ||
| 618 | for (pCertContextEnum = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContextEnum); | ||
| 619 | pCertContextEnum; | ||
| 620 | pCertContextEnum = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContextEnum)) | ||
| 621 | { | ||
| 622 | pCertContext = pCertContextEnum; | ||
| 623 | |||
| 624 | if (pCertContext && CertHasPrivateKey(pCertContext, NULL)) | ||
| 625 | { | ||
| 626 | break; | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 630 | ExitOnNullWithLastError(pCertContext, hr, "Failed to read first certificate out of PFX file."); | ||
| 631 | |||
| 632 | // Ignore failures, the worst that happens is some parts of the PFX get left behind. | ||
| 633 | CertReadProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, &pPfxInfo, NULL); | ||
| 634 | } | ||
| 635 | else | ||
| 636 | { | ||
| 637 | hr = E_UNEXPECTED; | ||
| 638 | ExitOnFailure(hr, "Unexpected certificate type processed."); | ||
| 639 | } | ||
| 640 | } | ||
| 641 | |||
| 642 | DWORD cb = cbHash; | ||
| 643 | if (!::CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, static_cast<LPVOID>(rgbHash), &cb)) | ||
| 644 | { | ||
| 645 | ExitWithLastError(hr, "Failed to get certificate SHA1 hash property."); | ||
| 646 | } | ||
| 647 | AssertSz(cb == cbHash, "Did not correctly read certificate SHA1 hash."); | ||
| 648 | |||
| 649 | LExit: | ||
| 650 | if (pCertContext) | ||
| 651 | { | ||
| 652 | ::CertFreeCertificateContext(pCertContext); | ||
| 653 | } | ||
| 654 | |||
| 655 | if (hPfxCertStore) | ||
| 656 | { | ||
| 657 | ::CertCloseStore(hPfxCertStore, 0); | ||
| 658 | } | ||
| 659 | |||
| 660 | if (pPfxInfo) | ||
| 661 | { | ||
| 662 | HCRYPTPROV hProvIgnored = NULL; // ignored on deletes. | ||
| 663 | ::CryptAcquireContextW(&hProvIgnored, pPfxInfo->pwszContainerName, pPfxInfo->pwszProvName, pPfxInfo->dwProvType, dwKeyset | CRYPT_DELETEKEYSET | CRYPT_SILENT); | ||
| 664 | |||
| 665 | MemFree(pPfxInfo); | ||
| 666 | } | ||
| 667 | |||
| 668 | return hr; | ||
| 669 | } | ||
| 670 | |||
| 671 | |||
| 672 | static HRESULT FindExistingCertificate( | ||
| 673 | __in LPCWSTR wzName, | ||
| 674 | __in DWORD dwStoreLocation, | ||
| 675 | __in LPCWSTR wzStore, | ||
| 676 | __out BYTE** prgbCertificate, | ||
| 677 | __out DWORD* pcbCertificate | ||
| 678 | ) | ||
| 679 | { | ||
| 680 | HRESULT hr = S_OK; | ||
| 681 | HCERTSTORE hCertStore = NULL; | ||
| 682 | PCCERT_CONTEXT pCertContext = NULL; | ||
| 683 | BYTE* pbCertificate = NULL; | ||
| 684 | DWORD cbCertificate = 0; | ||
| 685 | |||
| 686 | hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwStoreLocation | CERT_STORE_READONLY_FLAG, wzStore); | ||
| 687 | MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "Failed to open certificate store."); | ||
| 688 | |||
| 689 | // Loop through the certificate, looking for certificates that match our friendly name. | ||
| 690 | pCertContext = CertFindCertificateInStore(hCertStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); | ||
| 691 | while (pCertContext) | ||
| 692 | { | ||
| 693 | WCHAR wzFriendlyName[256] = { 0 }; | ||
| 694 | DWORD cbFriendlyName = sizeof(wzFriendlyName); | ||
| 695 | |||
| 696 | if (::CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, reinterpret_cast<BYTE*>(wzFriendlyName), &cbFriendlyName) && | ||
| 697 | CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, wzName, -1, wzFriendlyName, -1)) | ||
| 698 | { | ||
| 699 | // If the certificate with matching friendly name is valid, let's use that. | ||
| 700 | long lVerify = ::CertVerifyTimeValidity(NULL, pCertContext->pCertInfo); | ||
| 701 | if (0 == lVerify) | ||
| 702 | { | ||
| 703 | cbCertificate = pCertContext->cbCertEncoded; | ||
| 704 | pbCertificate = static_cast<BYTE*>(MemAlloc(cbCertificate, FALSE)); | ||
| 705 | ExitOnNull(pbCertificate, hr, E_OUTOFMEMORY, "Failed to allocate memory to copy out exist certificate."); | ||
| 706 | |||
| 707 | CopyMemory(pbCertificate, pCertContext->pbCertEncoded, cbCertificate); | ||
| 708 | break; // found a matching certificate, no more searching necessary | ||
| 709 | } | ||
| 710 | } | ||
| 711 | |||
| 712 | // Next certificate in the store. | ||
| 713 | PCCERT_CONTEXT pNext = ::CertFindCertificateInStore(hCertStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pCertContext); | ||
| 714 | // old pCertContext is freed by CertFindCertificateInStore | ||
| 715 | pCertContext = pNext; | ||
| 716 | } | ||
| 717 | |||
| 718 | *prgbCertificate = pbCertificate; | ||
| 719 | *pcbCertificate = cbCertificate; | ||
| 720 | pbCertificate = NULL; | ||
| 721 | |||
| 722 | LExit: | ||
| 723 | ReleaseMem(pbCertificate); | ||
| 724 | |||
| 725 | if (pCertContext) | ||
| 726 | { | ||
| 727 | ::CertFreeCertificateContext(pCertContext); | ||
| 728 | } | ||
| 729 | |||
| 730 | if (hCertStore) | ||
| 731 | { | ||
| 732 | ::CertCloseStore(hCertStore, 0); | ||
| 733 | } | ||
| 734 | |||
| 735 | return hr; | ||
| 736 | } | ||
| 737 | |||
| 738 | /* | ||
| 739 | HRESULT CreateEnroll(ICEnroll2 **hEnroll, INT iStore, INT iStoreLocation) | ||
| 740 | { | ||
| 741 | ICEnroll2 *pEnroll = NULL; | ||
| 742 | HRESULT hr = S_OK; | ||
| 743 | LONG lFlags; | ||
| 744 | DWORD dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT; | ||
| 745 | |||
| 746 | // create IEntroll | ||
| 747 | hr = CoCreateInstance( CLSID_CEnroll, NULL, CLSCTX_INPROC_SERVER, IID_ICEnroll2, (void **)&pEnroll ); | ||
| 748 | if (FAILED(hr)) | ||
| 749 | return hr; | ||
| 750 | |||
| 751 | switch (iStore) | ||
| 752 | { | ||
| 753 | case SCA_CERT_STORENAME_MY: | ||
| 754 | pEnroll->get_MyStoreFlags(&lFlags); | ||
| 755 | lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK; | ||
| 756 | lFlags |= dwFlags; | ||
| 757 | // following call will change Request store flags also | ||
| 758 | pEnroll->put_MyStoreFlags(lFlags); | ||
| 759 | break; | ||
| 760 | case SCA_CERT_STORENAME_CA: | ||
| 761 | pEnroll->get_CAStoreFlags(&lFlags); | ||
| 762 | lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK; | ||
| 763 | lFlags |= dwFlags; | ||
| 764 | // following call will change Request store flags also | ||
| 765 | pEnroll->put_CAStoreFlags(lFlags); | ||
| 766 | break; | ||
| 767 | case SCA_CERT_STORENAME_REQUEST: | ||
| 768 | pEnroll->get_RequestStoreFlags(&lFlags); | ||
| 769 | lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK; | ||
| 770 | lFlags |= dwFlags; | ||
| 771 | // following call will change Request store flags also | ||
| 772 | pEnroll->put_RequestStoreFlags(lFlags); | ||
| 773 | break; | ||
| 774 | case SCA_CERT_STORENAME_ROOT: | ||
| 775 | pEnroll->get_RootStoreFlags(&lFlags); | ||
| 776 | lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK; | ||
| 777 | lFlags |= dwFlags; | ||
| 778 | // following call will change Request store flags also | ||
| 779 | pEnroll->put_RootStoreFlags(lFlags); | ||
| 780 | break; | ||
| 781 | default: | ||
| 782 | hr = E_FAIL; | ||
| 783 | return hr; | ||
| 784 | } | ||
| 785 | |||
| 786 | pEnroll->get_GenKeyFlags(&lFlags); | ||
| 787 | lFlags |= CRYPT_EXPORTABLE; | ||
| 788 | pEnroll->put_GenKeyFlags(lFlags); | ||
| 789 | |||
| 790 | pEnroll->put_KeySpec(AT_KEYEXCHANGE); | ||
| 791 | pEnroll->put_ProviderType(PROV_RSA_SCHANNEL); | ||
| 792 | pEnroll->put_DeleteRequestCert(TRUE); | ||
| 793 | |||
| 794 | *hEnroll = pEnroll; | ||
| 795 | return hr; | ||
| 796 | } | ||
| 797 | |||
| 798 | |||
| 799 | HRESULT RequestCertificate(LPCWSTR pwzName, INT iStore, INT iStoreLocation, | ||
| 800 | LPCWSTR wzComputerName, LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthority, | ||
| 801 | BSTR *pbstrCertificate) | ||
| 802 | { | ||
| 803 | if (pbstrCertificate == NULL) | ||
| 804 | return E_INVALIDARG; | ||
| 805 | |||
| 806 | HRESULT hr; | ||
| 807 | ICEnroll2 *pEnroll = NULL; | ||
| 808 | ICertRequest *pCertRequest = NULL; | ||
| 809 | BSTR bstrRequest = NULL; | ||
| 810 | LONG nDisposition; | ||
| 811 | |||
| 812 | BSTR bstrCertificateUsage = NULL; | ||
| 813 | BSTR bstrCertificateAttributes = NULL; | ||
| 814 | BSTR bstrCertificateAuthority = NULL; | ||
| 815 | |||
| 816 | // equivalent to: sprintf(bstrDistinguishedName, L"%s,CN=%s", wzDistinguishedName, wzComputerName); | ||
| 817 | DWORD cchComputerName = lstrlenW(wzComputerName); | ||
| 818 | DWORD cchDistinguishedName = lstrlenW(wzDistinguishedName); | ||
| 819 | CONST DWORD cchbstrDistinguishedName = 5 + cchComputerName + cchDistinguishedName; | ||
| 820 | BSTR bstrDistinguishedName = SysAllocStringLen(NULL, cchbstrDistinguishedName); | ||
| 821 | ExitOnNull(bstrDistinguishedName, hr, E_OUTOFMEMORY, "Failed to allocate space for distinguished name."); | ||
| 822 | ::StringCchCopyW((WCHAR*) bstrDistinguishedName, cchbstrDistinguishedName, wzDistinguishedName); | ||
| 823 | ::StringCchCatW((WCHAR*) bstrDistinguishedName, cchbstrDistinguishedName, L",CN="); | ||
| 824 | ::StringCchCatW((WCHAR*) bstrDistinguishedName, cchbstrDistinguishedName, wzComputerName); | ||
| 825 | |||
| 826 | bstrCertificateUsage = SysAllocString(WIDE(szOID_PKIX_KP_SERVER_AUTH)); | ||
| 827 | ExitOnNull(bstrCertificateUsage, hr, E_OUTOFMEMORY, "Failed to allocate space for Certificate Usage."); | ||
| 828 | bstrCertificateAttributes = SysAllocString(L"CertificateTemplate:WebServer"); | ||
| 829 | bstrCertificateAuthority = SysAllocString(wzCertificateAuthority); | ||
| 830 | ExitOnNull(bstrCertificateAuthority, hr, E_OUTOFMEMORY, "Failed to allocate space for Certificate Authority."); | ||
| 831 | |||
| 832 | hr = CreateEnroll(&pEnroll, iStore, iStoreLocation); | ||
| 833 | ExitOnFailure(hr, "failed CoCreateInstance IEnroll"); | ||
| 834 | |||
| 835 | hr = pEnroll->createPKCS10(bstrDistinguishedName, bstrCertificateUsage, &bstrRequest); | ||
| 836 | ExitOnFailure(hr, "failed createPKCS10"); | ||
| 837 | |||
| 838 | hr = CoCreateInstance(CLSID_CCertRequest, NULL, CLSCTX_INPROC_SERVER, IID_ICertRequest, (void **)&pCertRequest); | ||
| 839 | ExitOnFailure(hr, "failed CoCreateInstance ICertRequest"); | ||
| 840 | |||
| 841 | hr = pCertRequest->Submit(CR_IN_BASE64 | CR_IN_PKCS10, bstrRequest, bstrCertificateAttributes, bstrCertificateAuthority, &nDisposition); | ||
| 842 | ExitOnFailure(hr, "failed ICertRequest.Submit"); | ||
| 843 | |||
| 844 | hr = (nDisposition == CR_DISP_ISSUED) ? S_OK : E_FAIL; | ||
| 845 | ExitOnFailure(hr, "failed CR_DISP_ISSUED"); | ||
| 846 | |||
| 847 | hr = pCertRequest->GetCertificate(CR_OUT_BASE64, pbstrCertificate); | ||
| 848 | ExitOnFailure(hr, "failed ICertRequest.GetCertificate"); | ||
| 849 | |||
| 850 | // save the certificate in place, cannot be passed to a deferred custom action | ||
| 851 | hr = pEnroll->acceptPKCS7(*pbstrCertificate); | ||
| 852 | ExitOnFailure(hr, "failed accept certificate into MY store"); | ||
| 853 | |||
| 854 | LExit: | ||
| 855 | ReleaseObject(pCertRequest); | ||
| 856 | ReleaseBSTR(bstrRequest); | ||
| 857 | ReleaseObject(pEnroll); | ||
| 858 | ReleaseBSTR(bstrCertificateAuthority); | ||
| 859 | ReleaseBSTR(bstrCertificateAttributes); | ||
| 860 | ReleaseBSTR(bstrDistinguishedName); | ||
| 861 | |||
| 862 | return hr; | ||
| 863 | } | ||
| 864 | |||
| 865 | |||
| 866 | VOID ParseCertificateAuthority(__in LPCWSTR wzCertificateAuthorityOrig, __out LPWSTR *pwzBuffer, __out LPWSTR **hwzCAArray, __out int *piCAArray) | ||
| 867 | { | ||
| 868 | // @asAuthorities = split /;/, $sAuthority; | ||
| 869 | CONST WCHAR wchDelimiter = L';'; | ||
| 870 | |||
| 871 | // copy constant into a buffer | ||
| 872 | Assert(wzCertificateAuthorityOrig); | ||
| 873 | |||
| 874 | INT cchCA = lstrlenW(wzCertificateAuthorityOrig) + 1; | ||
| 875 | WCHAR* wzBuffer = new WCHAR[cchCA]; | ||
| 876 | if (!wzBuffer) | ||
| 877 | return; | ||
| 878 | |||
| 879 | ::StringCchCopyW(wzBuffer, cchCA, wzCertificateAuthorityOrig); | ||
| 880 | |||
| 881 | // determine the number of strings in the field | ||
| 882 | int iCAArray = 1; | ||
| 883 | int i; | ||
| 884 | for (i = 0; i < cchCA; ++i) | ||
| 885 | { | ||
| 886 | if (wzBuffer[i] == wchDelimiter) | ||
| 887 | ++iCAArray; | ||
| 888 | } | ||
| 889 | LPWSTR *pwzCAArray = (LPWSTR*) new BYTE[iCAArray * sizeof(LPWSTR)]; | ||
| 890 | if (!pwzCAArray) | ||
| 891 | { | ||
| 892 | return; | ||
| 893 | } | ||
| 894 | |||
| 895 | pwzCAArray[0] = wzBuffer; | ||
| 896 | iCAArray = 0; | ||
| 897 | for (i = 0; i < cchCA; ++i) | ||
| 898 | { | ||
| 899 | if (wzBuffer[i] != wchDelimiter) | ||
| 900 | continue; | ||
| 901 | wzBuffer[i] = 0; // convert buffer into MULTISZ | ||
| 902 | pwzCAArray[iCAArray] = &wzBuffer[i+1]; | ||
| 903 | ++iCAArray; | ||
| 904 | } | ||
| 905 | |||
| 906 | *pwzBuffer = wzBuffer; | ||
| 907 | *hwzCAArray = pwzCAArray; | ||
| 908 | *piCAArray = iCAArray; | ||
| 909 | } | ||
| 910 | |||
| 911 | |||
| 912 | HRESULT ScaSslExistingCertificateByBinaryData(INT iStore, INT iStoreLocation, BYTE* pwzData, DWORD cchData) | ||
| 913 | { | ||
| 914 | HRESULT hr = S_FALSE; | ||
| 915 | HCERTSTORE hCertStore = NULL; | ||
| 916 | PCCERT_CONTEXT pCertCtx = NULL, pCertCtxExisting = NULL; | ||
| 917 | DWORD dwFlags = 0; | ||
| 918 | LPCWSTR wzStore = StoreMapping(iStore); | ||
| 919 | CERT_BLOB blob; | ||
| 920 | |||
| 921 | dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT; | ||
| 922 | hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwFlags, wzStore); | ||
| 923 | MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "failed to open certificate store, OK on uninstall"); | ||
| 924 | |||
| 925 | blob.pbData = pwzData; | ||
| 926 | blob.cbData = cchData; | ||
| 927 | |||
| 928 | if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, | ||
| 929 | 0, NULL, NULL, NULL, NULL, NULL, (LPCVOID*)&pCertCtx)) | ||
| 930 | ExitOnLastError(hr, "failed to parse the certificate blob, OK on uninstall"); | ||
| 931 | |||
| 932 | pCertCtxExisting = CertFindCertificateInStore( | ||
| 933 | hCertStore, | ||
| 934 | PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, | ||
| 935 | 0, | ||
| 936 | CERT_FIND_EXISTING, | ||
| 937 | pCertCtx, | ||
| 938 | NULL); | ||
| 939 | |||
| 940 | if (pCertCtxExisting) | ||
| 941 | { | ||
| 942 | hr = S_OK; | ||
| 943 | } | ||
| 944 | |||
| 945 | LExit: | ||
| 946 | if (pCertCtx) | ||
| 947 | { | ||
| 948 | CertFreeCertificateContext(pCertCtx); | ||
| 949 | pCertCtx = NULL; | ||
| 950 | } | ||
| 951 | if (pCertCtxExisting) | ||
| 952 | { | ||
| 953 | CertFreeCertificateContext(pCertCtxExisting); | ||
| 954 | pCertCtxExisting = NULL; | ||
| 955 | } | ||
| 956 | if (hCertStore) | ||
| 957 | { | ||
| 958 | CertCloseStore(hCertStore, 0); | ||
| 959 | hCertStore = NULL; | ||
| 960 | } | ||
| 961 | |||
| 962 | return hr; | ||
| 963 | } | ||
| 964 | |||
| 965 | |||
| 966 | HRESULT ScaSslExistingCertificateByName(LPCWSTR pwzName, INT iStore, INT iStoreLocation, | ||
| 967 | BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer) | ||
| 968 | { | ||
| 969 | HRESULT hr = S_FALSE; | ||
| 970 | HCERTSTORE hSystemStore = NULL; | ||
| 971 | PCCERT_CONTEXT pTargetCert = NULL; | ||
| 972 | WCHAR wzFriendlyName[MAX_PATH] = {0}; | ||
| 973 | DWORD dwFriendlyNameLen = sizeof(wzFriendlyName); | ||
| 974 | |||
| 975 | // Call CertOpenStore to open the CA store. | ||
| 976 | hSystemStore = CertOpenStore( | ||
| 977 | CERT_STORE_PROV_SYSTEM_REGISTRY, | ||
| 978 | 0, | ||
| 979 | NULL, | ||
| 980 | (iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT) | CERT_STORE_OPEN_EXISTING_FLAG, | ||
| 981 | StoreMapping(iStore)); | ||
| 982 | if (hSystemStore == NULL) | ||
| 983 | ExitFunction(); | ||
| 984 | |||
| 985 | // Get a particular certificate using CertFindCertificateInStore. | ||
| 986 | pTargetCert = CertFindCertificateInStore( | ||
| 987 | hSystemStore, | ||
| 988 | PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, | ||
| 989 | 0, | ||
| 990 | CERT_FIND_ANY, | ||
| 991 | NULL, | ||
| 992 | NULL); | ||
| 993 | while (pTargetCert != NULL) | ||
| 994 | { | ||
| 995 | if ((CertGetCertificateContextProperty(pTargetCert, CERT_FRIENDLY_NAME_PROP_ID, | ||
| 996 | (BYTE*)wzFriendlyName, &dwFriendlyNameLen)) && | ||
| 997 | lstrcmpW(wzFriendlyName, pwzName) == 0) | ||
| 998 | { | ||
| 999 | // pTargetCert is a pointer to the desired certificate. | ||
| 1000 | // Check the certificate's validity. | ||
| 1001 | switch (CertVerifyTimeValidity( | ||
| 1002 | NULL, | ||
| 1003 | pTargetCert->pCertInfo)) | ||
| 1004 | { | ||
| 1005 | case 1: | ||
| 1006 | // Certificate is expired | ||
| 1007 | WcaLog(LOGMSG_STANDARD, "The SSL certificate has expired"); | ||
| 1008 | // always remove it | ||
| 1009 | { | ||
| 1010 | PCCERT_CONTEXT pDupCertContext = CertDuplicateCertificateContext(pTargetCert); | ||
| 1011 | if (pDupCertContext && CertDeleteCertificateFromStore(pDupCertContext)) | ||
| 1012 | { | ||
| 1013 | WcaLog(LOGMSG_STANDARD, "A SSL certificate has removed"); | ||
| 1014 | } | ||
| 1015 | } | ||
| 1016 | break; | ||
| 1017 | case 0: | ||
| 1018 | // Certificate is valid | ||
| 1019 | WcaLog(LOGMSG_STANDARD, "The SSL certificate is valid"); | ||
| 1020 | hr = S_OK; | ||
| 1021 | if (pbaHashBuffer) | ||
| 1022 | { | ||
| 1023 | // if the certificate already exists and is valid, use that one | ||
| 1024 | DWORD dwHashSize = CB_CERTIFICATE_HASH; | ||
| 1025 | hr = CertGetCertificateContextProperty(pTargetCert, CERT_SHA1_HASH_PROP_ID, (VOID*)pbaHashBuffer, &dwHashSize) | ||
| 1026 | ? S_OK : E_FAIL; | ||
| 1027 | ExitOnFailure(hr, "failed CertGetCertificateContextProperty CERT_SHA1_HASH_PROP_ID"); | ||
| 1028 | Assert(pbstrCertificate); | ||
| 1029 | Assert(pcbCertificate); | ||
| 1030 | ReleaseBSTR(*pbstrCertificate); | ||
| 1031 | |||
| 1032 | *pbstrCertificate = SysAllocStringByteLen((LPCSTR)(pTargetCert->pbCertEncoded), pTargetCert->cbCertEncoded); | ||
| 1033 | *pcbCertificate = pTargetCert->cbCertEncoded; | ||
| 1034 | } | ||
| 1035 | ExitFunction(); | ||
| 1036 | break; | ||
| 1037 | default: | ||
| 1038 | // Certificate not valid yet, ignore it | ||
| 1039 | WcaLog(LOGMSG_STANDARD, "The SSL certificate is not valid"); | ||
| 1040 | break; | ||
| 1041 | } | ||
| 1042 | } | ||
| 1043 | pTargetCert = CertFindCertificateInStore( | ||
| 1044 | hSystemStore, | ||
| 1045 | PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, | ||
| 1046 | 0, | ||
| 1047 | CERT_FIND_ANY, | ||
| 1048 | NULL, | ||
| 1049 | pTargetCert); | ||
| 1050 | wzFriendlyName[0] = 0; | ||
| 1051 | dwFriendlyNameLen = sizeof(wzFriendlyName); | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | LExit: | ||
| 1055 | // Clean up memory and quit. | ||
| 1056 | if (pTargetCert) | ||
| 1057 | { | ||
| 1058 | CertFreeCertificateContext(pTargetCert); | ||
| 1059 | pTargetCert = NULL; | ||
| 1060 | } | ||
| 1061 | if (hSystemStore) | ||
| 1062 | { | ||
| 1063 | CertCloseStore(hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG); | ||
| 1064 | hSystemStore = NULL; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | return hr; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | |||
| 1071 | HRESULT ScaSslNewCertificate(LPCWSTR pwzName, INT iStore, INT iStoreLocation, LPCWSTR wzComputerName, LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthorityOrig, | ||
| 1072 | BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer) | ||
| 1073 | { | ||
| 1074 | |||
| 1075 | if (pbstrCertificate == NULL) | ||
| 1076 | return E_INVALIDARG; | ||
| 1077 | |||
| 1078 | HRESULT hr = S_OK; | ||
| 1079 | LPWSTR wzCABuffer = NULL; | ||
| 1080 | LPWSTR *wzCAArray = NULL; | ||
| 1081 | int iCAArray = 0; | ||
| 1082 | |||
| 1083 | // otherwise call the CA for one | ||
| 1084 | ParseCertificateAuthority(wzCertificateAuthorityOrig, &wzCABuffer, &wzCAArray, &iCAArray); | ||
| 1085 | |||
| 1086 | // try each authority three times | ||
| 1087 | for (int i = 0; i < 3 * iCAArray; ++i) | ||
| 1088 | { | ||
| 1089 | LPCWSTR wzCA = wzCAArray[i % iCAArray]; | ||
| 1090 | if (NULL == wzCA || NULL == wzCA[0]) continue; | ||
| 1091 | WcaLog(LOGMSG_STANDARD, "Requesting SSL certificate from %ls", wzCA); | ||
| 1092 | hr = RequestCertificate(pwzName, iStore, iStoreLocation, wzComputerName, wzDistinguishedName, wzCA, pbstrCertificate); | ||
| 1093 | if (hr == S_OK && pbstrCertificate) | ||
| 1094 | { | ||
| 1095 | // set the friendly name | ||
| 1096 | CRYPT_HASH_BLOB hblob; | ||
| 1097 | CERT_BLOB blob; | ||
| 1098 | HCERTSTORE hCertStore = NULL; | ||
| 1099 | PCCERT_CONTEXT pCertCtxExisting = NULL; | ||
| 1100 | |||
| 1101 | blob.pbData = (BYTE*)pwzName; | ||
| 1102 | blob.cbData = (lstrlenW(pwzName) + 1) * sizeof(pwzName[0]); // including terminating null | ||
| 1103 | |||
| 1104 | *pcbCertificate = SysStringByteLen(*pbstrCertificate); | ||
| 1105 | hr = CertificateToHash(*pbstrCertificate, pbaHashBuffer); | ||
| 1106 | ExitOnFailure(hr, "failed to CertificateToHash for an existing certificate"); | ||
| 1107 | |||
| 1108 | hblob.pbData = pbaHashBuffer; | ||
| 1109 | hblob.cbData = CB_CERTIFICATE_HASH; | ||
| 1110 | |||
| 1111 | hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, (iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT), StoreMapping(iStore)); | ||
| 1112 | MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "failed to open certificate store"); | ||
| 1113 | |||
| 1114 | pCertCtxExisting = CertFindCertificateInStore( | ||
| 1115 | hCertStore, | ||
| 1116 | PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, | ||
| 1117 | 0, | ||
| 1118 | CERT_FIND_HASH, | ||
| 1119 | &hblob, | ||
| 1120 | NULL); | ||
| 1121 | |||
| 1122 | if (pCertCtxExisting) | ||
| 1123 | { | ||
| 1124 | CertSetCertificateContextProperty( | ||
| 1125 | pCertCtxExisting, | ||
| 1126 | CERT_FRIENDLY_NAME_PROP_ID, | ||
| 1127 | 0, | ||
| 1128 | &blob); | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | if (pCertCtxExisting) | ||
| 1132 | { | ||
| 1133 | CertFreeCertificateContext(pCertCtxExisting); | ||
| 1134 | pCertCtxExisting = NULL; | ||
| 1135 | } | ||
| 1136 | if (hCertStore) | ||
| 1137 | { | ||
| 1138 | CertCloseStore(hCertStore, 0); | ||
| 1139 | hCertStore = NULL; | ||
| 1140 | } | ||
| 1141 | ExitFunction(); | ||
| 1142 | } | ||
| 1143 | if (pbstrCertificate && *pbstrCertificate) | ||
| 1144 | { | ||
| 1145 | SysFreeString(*pbstrCertificate); | ||
| 1146 | pbstrCertificate = NULL; | ||
| 1147 | } | ||
| 1148 | } | ||
| 1149 | hr = E_FAIL; | ||
| 1150 | ExitOnFailure(hr, "failed to RequestCertificate"); | ||
| 1151 | |||
| 1152 | LExit: | ||
| 1153 | if (wzCABuffer) | ||
| 1154 | { | ||
| 1155 | delete wzCABuffer; | ||
| 1156 | } | ||
| 1157 | if (wzCAArray) | ||
| 1158 | { | ||
| 1159 | delete wzCAArray; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | return hr; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | |||
| 1166 | HRESULT ScaGetCertificateByRequest(LPCWSTR pwzName, BOOL fIsInstalling, BOOL fIsUninstalling, | ||
| 1167 | INT iStore, INT iStoreLocation, | ||
| 1168 | LPCWSTR wzDistinguishedName, LPCWSTR wzCA, | ||
| 1169 | BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer) | ||
| 1170 | { | ||
| 1171 | HRESULT hr = S_OK; | ||
| 1172 | WCHAR wzComputerName[MAX_COMPUTER_NAME] = {0}; | ||
| 1173 | WCHAR* pwzData = NULL; | ||
| 1174 | DWORD cchData = 0; | ||
| 1175 | |||
| 1176 | // override %COMPUTERNAME% with DOMAINNAME property | ||
| 1177 | hr = WcaGetProperty( L"DOMAINNAME", &pwzData); | ||
| 1178 | ExitOnFailure(hr, "Failed to get Property DOMAINNAME"); | ||
| 1179 | if (*pwzData) | ||
| 1180 | { | ||
| 1181 | // if DOMAINNAME is set, use it | ||
| 1182 | ::StringCchCopyW(wzComputerName, MAX_COMPUTER_NAME, pwzData); | ||
| 1183 | } | ||
| 1184 | else | ||
| 1185 | { | ||
| 1186 | // otherwise get the intranet name given by %COMPUTERNAME% | ||
| 1187 | GetEnvironmentVariableW(L"COMPUTERNAME", wzComputerName, MAX_COMPUTER_NAME); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | hr = ScaSslExistingCertificateByName(pwzName, iStore, iStoreLocation, pbstrCertificate, pcbCertificate, pbaHashBuffer); | ||
| 1191 | ExitOnFailure(hr, "Failed ScaSslExistingCertificateByName"); | ||
| 1192 | if (S_OK != hr) | ||
| 1193 | { | ||
| 1194 | if (!fIsUninstalling && fIsInstalling) | ||
| 1195 | { | ||
| 1196 | // if no existing cert and not on uninstall, hit the authority | ||
| 1197 | WcaLog(LOGMSG_STANDARD, "Adding certificate: requested, %ls", wzDistinguishedName); | ||
| 1198 | hr = ScaSslNewCertificate(pwzName, iStore, iStoreLocation, wzComputerName, wzDistinguishedName, wzCA, | ||
| 1199 | pbstrCertificate, pcbCertificate, pbaHashBuffer); | ||
| 1200 | ExitOnFailure(hr, "Failed ScaSslNewCertificate"); | ||
| 1201 | } | ||
| 1202 | else | ||
| 1203 | { | ||
| 1204 | // if no existing cert and uninstall | ||
| 1205 | hr = S_OK; | ||
| 1206 | } | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | LExit: | ||
| 1210 | ReleaseStr(pwzData); | ||
| 1211 | |||
| 1212 | return hr; | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | |||
| 1216 | HRESULT ScaInstallCertificateByContext(LPCWSTR pwzName, INT iStore, INT iStoreLocation, | ||
| 1217 | PCCERT_CONTEXT pCertContext) | ||
| 1218 | { | ||
| 1219 | HRESULT hr = S_OK; | ||
| 1220 | HCERTSTORE hCertStore = NULL; | ||
| 1221 | DWORD dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT; | ||
| 1222 | CERT_BLOB blob; | ||
| 1223 | |||
| 1224 | hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwFlags, StoreMapping(iStore)); | ||
| 1225 | if (hCertStore == NULL) | ||
| 1226 | MessageExitOnLastError(hr, msierrCERTFailedOpen, "failed to open certificate store"); | ||
| 1227 | |||
| 1228 | blob.pbData = (BYTE*)pwzName; | ||
| 1229 | blob.cbData = (lstrlenW(pwzName) + 1) * sizeof(pwzName[0]); // including terminating null | ||
| 1230 | CertSetCertificateContextProperty( | ||
| 1231 | pCertContext, | ||
| 1232 | CERT_FRIENDLY_NAME_PROP_ID, | ||
| 1233 | 0, | ||
| 1234 | &blob); | ||
| 1235 | |||
| 1236 | if (!CertAddCertificateContextToStore( | ||
| 1237 | hCertStore, | ||
| 1238 | pCertContext, | ||
| 1239 | CERT_STORE_ADD_REPLACE_EXISTING, | ||
| 1240 | NULL)) | ||
| 1241 | { | ||
| 1242 | hr = E_FAIL; | ||
| 1243 | MessageExitOnLastError(hr, msierrCERTFailedAdd, "failed to add certificate to the store"); | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | LExit: | ||
| 1247 | if (hCertStore) | ||
| 1248 | { | ||
| 1249 | CertCloseStore(hCertStore, 0); | ||
| 1250 | hCertStore = NULL; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | return hr; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | |||
| 1257 | HRESULT ScaGetCertificateByPath(LPCWSTR pwzName, BOOL fIsInstalling, BOOL fIsUninstalling, | ||
| 1258 | INT iStore, INT iStoreLocation, LPCWSTR wzSslCertificate, LPCWSTR wzPFXPassword, | ||
| 1259 | BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer) | ||
| 1260 | { | ||
| 1261 | Assert(wzSslCertificate); | ||
| 1262 | HRESULT hr = S_OK; | ||
| 1263 | PCCERT_CONTEXT pCertContext = NULL; | ||
| 1264 | DWORD dwEncodingType = 0; | ||
| 1265 | DWORD dwContentType = 0; | ||
| 1266 | DWORD dwFormatType = 0; | ||
| 1267 | DWORD dwHashSize = CB_CERTIFICATE_HASH; | ||
| 1268 | HANDLE hPfxFile = INVALID_HANDLE_VALUE; | ||
| 1269 | CRYPT_DATA_BLOB blob; | ||
| 1270 | |||
| 1271 | blob.pbData = NULL; | ||
| 1272 | blob.cbData = 0; | ||
| 1273 | |||
| 1274 | if (wzSslCertificate && wzSslCertificate[0] != 0) | ||
| 1275 | { | ||
| 1276 | if (!::CryptQueryObject(CERT_QUERY_OBJECT_FILE, (LPVOID)wzSslCertificate, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, | ||
| 1277 | 0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertContext)) | ||
| 1278 | hr = fIsUninstalling ? S_FALSE : HRESULT_FROM_WIN32(::GetLastError()); // don't fail on uninstall | ||
| 1279 | ExitOnFailure(hr, "failed CryptQueryObject"); | ||
| 1280 | } | ||
| 1281 | else | ||
| 1282 | { | ||
| 1283 | hr = S_FALSE; | ||
| 1284 | ExitFunction(); | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | if (!pCertContext) | ||
| 1288 | { | ||
| 1289 | // this is a pfx? | ||
| 1290 | // make sure to exit this block of code properly for clean up blob.pbData | ||
| 1291 | if (dwContentType & CERT_QUERY_CONTENT_PFX) | ||
| 1292 | { | ||
| 1293 | DWORD iSize = 0, iReadSize = 0; | ||
| 1294 | HCERTSTORE hPfxCertStore = NULL; | ||
| 1295 | |||
| 1296 | hPfxFile = ::CreateFileW(wzSslCertificate, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||
| 1297 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | ||
| 1298 | hr = (hPfxFile != INVALID_HANDLE_VALUE) ? S_OK : E_FAIL; | ||
| 1299 | ExitOnFailure(hr, "failed CryptQueryObject, file handle is null"); | ||
| 1300 | iSize = ::GetFileSize(hPfxFile, NULL); | ||
| 1301 | hr = (iSize > 0) ? S_OK : E_FAIL; | ||
| 1302 | ExitOnFailure(hr, "failed CryptQueryObject, file size is 0"); | ||
| 1303 | blob.pbData = new BYTE[iSize]; | ||
| 1304 | blob.cbData = iSize; | ||
| 1305 | hr = (blob.pbData) ? S_OK : E_FAIL; | ||
| 1306 | ExitOnFailure(hr, "out of memory for blob"); | ||
| 1307 | |||
| 1308 | if (::ReadFile(hPfxFile, (LPVOID)blob.pbData, iSize, &iReadSize, NULL)) | ||
| 1309 | { | ||
| 1310 | hPfxCertStore = PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, | ||
| 1311 | (iStoreLocation == SCA_CERTSYSTEMSTORE_CURRENTUSER) ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET); | ||
| 1312 | if (hPfxCertStore) | ||
| 1313 | { | ||
| 1314 | pCertContext = CertEnumCertificatesInStore(hPfxCertStore, NULL); | ||
| 1315 | // work only with the first certificate in pfx | ||
| 1316 | if (pCertContext) | ||
| 1317 | { | ||
| 1318 | hr = CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, (VOID*)pbaHashBuffer, &dwHashSize) | ||
| 1319 | ? S_OK : E_FAIL; | ||
| 1320 | ExitOnFailure(hr, "failed CertGetCertificateContextProperty CERT_SHA1_HASH_PROP_ID"); | ||
| 1321 | ReleaseBSTR(*pbstrCertificate); | ||
| 1322 | |||
| 1323 | *pbstrCertificate = SysAllocStringByteLen((LPCSTR)(pCertContext->pbCertEncoded), pCertContext->cbCertEncoded); | ||
| 1324 | *pcbCertificate = pCertContext->cbCertEncoded; | ||
| 1325 | if (fIsInstalling) | ||
| 1326 | { | ||
| 1327 | // install the certificate, cannot defer because the data required cannot be passed | ||
| 1328 | hr = ScaInstallCertificateByContext(pwzName, iStore, iStoreLocation, pCertContext); | ||
| 1329 | } | ||
| 1330 | } | ||
| 1331 | else | ||
| 1332 | hr = E_FAIL; | ||
| 1333 | } | ||
| 1334 | else | ||
| 1335 | hr = E_FAIL; | ||
| 1336 | } | ||
| 1337 | else | ||
| 1338 | hr = E_FAIL; | ||
| 1339 | } | ||
| 1340 | else | ||
| 1341 | { | ||
| 1342 | ExitOnFailure(hr = E_FAIL, "failed CryptQueryObject, unknown data"); | ||
| 1343 | } | ||
| 1344 | } | ||
| 1345 | else | ||
| 1346 | { | ||
| 1347 | // return cert and its hash | ||
| 1348 | hr = CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, (VOID*)pbaHashBuffer, &dwHashSize) | ||
| 1349 | ? S_OK : E_FAIL; | ||
| 1350 | ExitOnFailure(hr, "failed CertGetCertificateContextProperty CERT_SHA1_HASH_PROP_ID"); | ||
| 1351 | ReleaseBSTR(*pbstrCertificate); | ||
| 1352 | |||
| 1353 | *pbstrCertificate = SysAllocStringByteLen((LPCSTR)(pCertContext->pbCertEncoded), pCertContext->cbCertEncoded); | ||
| 1354 | *pcbCertificate = pCertContext->cbCertEncoded; | ||
| 1355 | if (fIsInstalling) | ||
| 1356 | { | ||
| 1357 | // install the certificate, cannot defer because the data required cannot be passed | ||
| 1358 | hr = ScaInstallCertificateByContext(pwzName, iStore, iStoreLocation, pCertContext); | ||
| 1359 | } | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | LExit: | ||
| 1363 | if (pCertContext) | ||
| 1364 | { | ||
| 1365 | CertFreeCertificateContext(pCertContext); | ||
| 1366 | pCertContext = NULL; | ||
| 1367 | } | ||
| 1368 | if (hPfxFile != INVALID_HANDLE_VALUE) | ||
| 1369 | { | ||
| 1370 | CloseHandle(hPfxFile); | ||
| 1371 | hPfxFile = INVALID_HANDLE_VALUE; | ||
| 1372 | } | ||
| 1373 | if (blob.pbData) | ||
| 1374 | { | ||
| 1375 | delete [] blob.pbData; | ||
| 1376 | blob.pbData = NULL; | ||
| 1377 | blob.cbData = 0; | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | return hr; | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | |||
| 1384 | HRESULT ScaInstallCertificateByBinaryData(BOOL fAddCert, INT iStore, INT iStoreLocation, LPCWSTR wzName, BYTE* pwzData, DWORD cchData, | ||
| 1385 | LPCWSTR wzPFXPassword) | ||
| 1386 | { | ||
| 1387 | Assert(wzName); | ||
| 1388 | Assert(pwzData); | ||
| 1389 | Assert(cchData); | ||
| 1390 | HRESULT hr = S_OK; | ||
| 1391 | HCERTSTORE hCertStore = NULL, hPfxCertStore = NULL; | ||
| 1392 | PCCERT_CONTEXT pCertCtx = NULL, pCertCtxExisting = NULL; | ||
| 1393 | DWORD dwFlags, dwEncodingType, dwContentType, dwFormatType; | ||
| 1394 | CERT_BLOB blob; | ||
| 1395 | LPCWSTR wzStore = StoreMapping(iStore); | ||
| 1396 | |||
| 1397 | dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT; | ||
| 1398 | hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwFlags, wzStore); | ||
| 1399 | MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "failed to open certificate store"); | ||
| 1400 | |||
| 1401 | blob.pbData = pwzData; | ||
| 1402 | blob.cbData = cchData; | ||
| 1403 | |||
| 1404 | if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, | ||
| 1405 | 0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertCtx)) | ||
| 1406 | ExitOnLastError(hr, "failed to parse the certificate blob"); | ||
| 1407 | ExitOnNull(pCertCtx, hr, E_UNEXPECTED, "failed to parse the certificate blob"); | ||
| 1408 | |||
| 1409 | blob.pbData = (BYTE*)wzName; | ||
| 1410 | blob.cbData = (lstrlenW(wzName) + 1) * sizeof(wzName[0]); // including terminating null | ||
| 1411 | |||
| 1412 | CertSetCertificateContextProperty( | ||
| 1413 | pCertCtx, | ||
| 1414 | CERT_FRIENDLY_NAME_PROP_ID, | ||
| 1415 | 0, | ||
| 1416 | &blob); | ||
| 1417 | |||
| 1418 | if (fAddCert) | ||
| 1419 | { | ||
| 1420 | // Add | ||
| 1421 | WcaLog(LOGMSG_STANDARD, "Adding certificate: binary name, %ls", wzName); | ||
| 1422 | if (!CertAddCertificateContextToStore( | ||
| 1423 | hCertStore, | ||
| 1424 | pCertCtx, | ||
| 1425 | CERT_STORE_ADD_REPLACE_EXISTING, | ||
| 1426 | NULL)) | ||
| 1427 | { | ||
| 1428 | hr = E_FAIL; | ||
| 1429 | MessageExitOnLastError(hr, msierrCERTFailedAdd, "failed to add certificate to the store"); | ||
| 1430 | } | ||
| 1431 | } | ||
| 1432 | else | ||
| 1433 | { | ||
| 1434 | // Delete | ||
| 1435 | WcaLog(LOGMSG_STANDARD, "Deleting certificate provided: binary name, %ls", wzName); | ||
| 1436 | pCertCtxExisting = CertFindCertificateInStore( | ||
| 1437 | hCertStore, | ||
| 1438 | PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, | ||
| 1439 | 0, | ||
| 1440 | CERT_FIND_EXISTING, | ||
| 1441 | pCertCtx, | ||
| 1442 | NULL); | ||
| 1443 | |||
| 1444 | if (pCertCtxExisting) | ||
| 1445 | { | ||
| 1446 | if (!CertDeleteCertificateFromStore(pCertCtxExisting)) | ||
| 1447 | { | ||
| 1448 | ExitOnLastError(hr, "failed to delete certificate"); | ||
| 1449 | } | ||
| 1450 | else | ||
| 1451 | { | ||
| 1452 | pCertCtxExisting = NULL; | ||
| 1453 | } | ||
| 1454 | } | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | LExit: | ||
| 1458 | if (pCertCtx) | ||
| 1459 | { | ||
| 1460 | CertFreeCertificateContext(pCertCtx); | ||
| 1461 | pCertCtx = NULL; | ||
| 1462 | } | ||
| 1463 | if (pCertCtxExisting) | ||
| 1464 | { | ||
| 1465 | CertFreeCertificateContext(pCertCtxExisting); | ||
| 1466 | pCertCtxExisting = NULL; | ||
| 1467 | } | ||
| 1468 | // order is important for store | ||
| 1469 | if (hCertStore) | ||
| 1470 | { | ||
| 1471 | CertCloseStore(hCertStore, 0); | ||
| 1472 | hCertStore = NULL; | ||
| 1473 | } | ||
| 1474 | if (hPfxCertStore) | ||
| 1475 | { | ||
| 1476 | CertCloseStore(hPfxCertStore, 0); | ||
| 1477 | hPfxCertStore = NULL; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | return hr; | ||
| 1481 | } | ||
| 1482 | */ | ||
diff --git a/src/ext/Iis/ca/scacert.h b/src/ext/Iis/ca/scacert.h new file mode 100644 index 00000000..39b00d3d --- /dev/null +++ b/src/ext/Iis/ca/scacert.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #define CB_CERTIFICATE_HASH 20 | ||
| 6 | |||
| 7 | // Certificate.Attribute | ||
| 8 | enum SCA_CERT_ATTRIBUTES | ||
| 9 | { | ||
| 10 | SCA_CERT_ATTRIBUTE_DEFAULT = 0, | ||
| 11 | SCA_CERT_ATTRIBUTE_REQUEST = 1, | ||
| 12 | SCA_CERT_ATTRIBUTE_BINARYDATA = 2, | ||
| 13 | SCA_CERT_ATTRIBUTE_OVERWRITE = 4, | ||
| 14 | SCA_CERT_ATTRIBUTE_VITAL = 8, | ||
| 15 | }; | ||
| 16 | |||
| 17 | |||
| 18 | // Certificate.StoreLocation | ||
| 19 | enum SCA_CERTSYSTEMSTORE | ||
| 20 | { | ||
| 21 | SCA_CERTSYSTEMSTORE_CURRENTUSER = 1, | ||
| 22 | SCA_CERTSYSTEMSTORE_LOCALMACHINE = 2, | ||
| 23 | }; | ||
diff --git a/src/ext/Iis/ca/scacertexec.cpp b/src/ext/Iis/ca/scacertexec.cpp new file mode 100644 index 00000000..95870c79 --- /dev/null +++ b/src/ext/Iis/ca/scacertexec.cpp | |||
| @@ -0,0 +1,431 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | #define SIXTY_FOUR_MEG 64 * 1024 * 1024 | ||
| 6 | |||
| 7 | // prototypes | ||
| 8 | static HRESULT ExecuteCertificateOperation( | ||
| 9 | __in MSIHANDLE hInstall, | ||
| 10 | __in SCA_ACTION saAction, | ||
| 11 | __in DWORD dwStoreRoot | ||
| 12 | ); | ||
| 13 | |||
| 14 | static HRESULT ReadCertificateFile( | ||
| 15 | __in LPCWSTR wzPath, | ||
| 16 | __out BYTE** prgbData, | ||
| 17 | __out DWORD* pcbData | ||
| 18 | ); | ||
| 19 | |||
| 20 | static HRESULT InstallCertificatePackage( | ||
| 21 | __in HCERTSTORE hStore, | ||
| 22 | __in BOOL fUserCertificateStore, | ||
| 23 | __in LPCWSTR wzName, | ||
| 24 | __in_opt BYTE* rgbData, | ||
| 25 | __in DWORD cbData, | ||
| 26 | __in BOOL fVital, | ||
| 27 | __in_opt LPCWSTR wzPFXPassword | ||
| 28 | ); | ||
| 29 | |||
| 30 | static HRESULT UninstallCertificatePackage( | ||
| 31 | __in HCERTSTORE hStore, | ||
| 32 | __in BOOL fUserCertificateStore, | ||
| 33 | __in LPCWSTR wzName | ||
| 34 | ); | ||
| 35 | |||
| 36 | static HRESULT AddCertificate( | ||
| 37 | __in HCERTSTORE hStore, | ||
| 38 | __in PCCERT_CONTEXT pCertContext, | ||
| 39 | __in LPCWSTR wzCertificateUniqueName, | ||
| 40 | __in BOOL fVital | ||
| 41 | ); | ||
| 42 | |||
| 43 | /* **************************************************************** | ||
| 44 | AddUserCertificate - CUSTOM ACTION ENTRY POINT for adding per-user | ||
| 45 | certificates | ||
| 46 | |||
| 47 | * ***************************************************************/ | ||
| 48 | extern "C" UINT __stdcall AddUserCertificate( | ||
| 49 | __in MSIHANDLE hInstall | ||
| 50 | ) | ||
| 51 | { | ||
| 52 | HRESULT hr = S_OK; | ||
| 53 | DWORD er = ERROR_SUCCESS; | ||
| 54 | |||
| 55 | hr = WcaInitialize(hInstall, "AddUserCertificate"); | ||
| 56 | ExitOnFailure(hr, "Failed to initialize AddUserCertificate."); | ||
| 57 | |||
| 58 | hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_INSTALL, CERT_SYSTEM_STORE_CURRENT_USER); | ||
| 59 | ExitOnFailure(hr, "Failed to install per-user certificate."); | ||
| 60 | |||
| 61 | LExit: | ||
| 62 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 63 | return WcaFinalize(er); | ||
| 64 | } | ||
| 65 | |||
| 66 | |||
| 67 | /* **************************************************************** | ||
| 68 | AddMachineCertificate - CUSTOM ACTION ENTRY POINT for adding | ||
| 69 | per-machine certificates | ||
| 70 | |||
| 71 | * ***************************************************************/ | ||
| 72 | extern "C" UINT __stdcall AddMachineCertificate( | ||
| 73 | __in MSIHANDLE hInstall | ||
| 74 | ) | ||
| 75 | { | ||
| 76 | HRESULT hr = S_OK; | ||
| 77 | DWORD er = ERROR_SUCCESS; | ||
| 78 | |||
| 79 | hr = WcaInitialize(hInstall, "AddMachineCertificate"); | ||
| 80 | ExitOnFailure(hr, "Failed to initialize AddMachineCertificate."); | ||
| 81 | |||
| 82 | hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_INSTALL, CERT_SYSTEM_STORE_LOCAL_MACHINE); | ||
| 83 | ExitOnFailure(hr, "Failed to install per-machine certificate."); | ||
| 84 | |||
| 85 | LExit: | ||
| 86 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 87 | return WcaFinalize(er); | ||
| 88 | } | ||
| 89 | |||
| 90 | |||
| 91 | /* **************************************************************** | ||
| 92 | DeleteUserCertificate - CUSTOM ACTION ENTRY POINT for deleting | ||
| 93 | per-user certificates | ||
| 94 | |||
| 95 | * ***************************************************************/ | ||
| 96 | extern "C" UINT __stdcall DeleteUserCertificate( | ||
| 97 | __in MSIHANDLE hInstall | ||
| 98 | ) | ||
| 99 | { | ||
| 100 | HRESULT hr = S_OK; | ||
| 101 | DWORD er = ERROR_SUCCESS; | ||
| 102 | |||
| 103 | hr = WcaInitialize(hInstall, "DeleteUserCertificate"); | ||
| 104 | ExitOnFailure(hr, "Failed to initialize DeleteUserCertificate."); | ||
| 105 | |||
| 106 | hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_UNINSTALL, CERT_SYSTEM_STORE_CURRENT_USER); | ||
| 107 | ExitOnFailure(hr, "Failed to uninstall per-user certificate."); | ||
| 108 | |||
| 109 | LExit: | ||
| 110 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 111 | return WcaFinalize(er); | ||
| 112 | } | ||
| 113 | |||
| 114 | |||
| 115 | /* **************************************************************** | ||
| 116 | DeleteMachineCertificate - CUSTOM ACTION ENTRY POINT for deleting | ||
| 117 | per-machine certificates | ||
| 118 | |||
| 119 | * ***************************************************************/ | ||
| 120 | extern "C" UINT __stdcall DeleteMachineCertificate( | ||
| 121 | __in MSIHANDLE hInstall | ||
| 122 | ) | ||
| 123 | { | ||
| 124 | HRESULT hr = S_OK; | ||
| 125 | DWORD er = ERROR_SUCCESS; | ||
| 126 | |||
| 127 | hr = WcaInitialize(hInstall, "DeleteMachineCertificate"); | ||
| 128 | ExitOnFailure(hr, "Failed to initialize DeleteMachineCertificate."); | ||
| 129 | |||
| 130 | hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_UNINSTALL, CERT_SYSTEM_STORE_LOCAL_MACHINE); | ||
| 131 | ExitOnFailure(hr, "Failed to uninstall per-machine certificate."); | ||
| 132 | |||
| 133 | LExit: | ||
| 134 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 135 | return WcaFinalize(er); | ||
| 136 | } | ||
| 137 | |||
| 138 | |||
| 139 | static HRESULT ExecuteCertificateOperation( | ||
| 140 | __in MSIHANDLE /*hInstall*/, | ||
| 141 | __in SCA_ACTION saAction, | ||
| 142 | __in DWORD dwStoreLocation | ||
| 143 | ) | ||
| 144 | { | ||
| 145 | //AssertSz(FALSE, "Debug ExecuteCertificateOperation() here."); | ||
| 146 | Assert(saAction & SCA_ACTION_INSTALL || saAction & SCA_ACTION_UNINSTALL); | ||
| 147 | |||
| 148 | HRESULT hr = S_OK; | ||
| 149 | LPWSTR pwzCaData = NULL; | ||
| 150 | LPWSTR pwz; | ||
| 151 | LPWSTR pwzName = NULL; | ||
| 152 | LPWSTR pwzStore = NULL; | ||
| 153 | int iAttributes = 0; | ||
| 154 | LPWSTR pwzPFXPassword = NULL; | ||
| 155 | LPWSTR pwzFilePath = NULL; | ||
| 156 | BYTE* pbData = NULL; | ||
| 157 | DWORD cbData = 0; | ||
| 158 | DWORD_PTR cbPFXPassword = 0; | ||
| 159 | |||
| 160 | BOOL fUserStoreLocation = (CERT_SYSTEM_STORE_CURRENT_USER == dwStoreLocation); | ||
| 161 | HCERTSTORE hCertStore = NULL; | ||
| 162 | |||
| 163 | hr = WcaGetProperty(L"CustomActionData", &pwzCaData); | ||
| 164 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
| 165 | |||
| 166 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCaData); | ||
| 167 | |||
| 168 | pwz = pwzCaData; | ||
| 169 | hr = WcaReadStringFromCaData(&pwz, &pwzName); | ||
| 170 | ExitOnFailure(hr, "Failed to parse certificate name."); | ||
| 171 | hr = WcaReadStringFromCaData(&pwz, &pwzStore); | ||
| 172 | ExitOnFailure(hr, "Failed to parse CustomActionData, StoreName"); | ||
| 173 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); | ||
| 174 | ExitOnFailure(hr, "Failed to parse certificate attribute"); | ||
| 175 | if (SCA_ACTION_INSTALL == saAction) // install operations need more data | ||
| 176 | { | ||
| 177 | hr = WcaReadStreamFromCaData(&pwz, &pbData, (DWORD_PTR*)&cbData); | ||
| 178 | ExitOnFailure(hr, "Failed to parse certificate stream."); | ||
| 179 | |||
| 180 | hr = WcaReadStringFromCaData(&pwz, &pwzPFXPassword); | ||
| 181 | ExitOnFailure(hr, "Failed to parse certificate password."); | ||
| 182 | } | ||
| 183 | |||
| 184 | // Open the right store. | ||
| 185 | hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwStoreLocation | CERT_STORE_MAXIMUM_ALLOWED_FLAG, pwzStore); | ||
| 186 | MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "Failed to open certificate store: %ls", pwzStore); | ||
| 187 | |||
| 188 | if (SCA_ACTION_INSTALL == saAction) // install operations need more data | ||
| 189 | { | ||
| 190 | // Uninstall existing versions of this package. Ignore any failures | ||
| 191 | // This is needed to clean up the private key of a cert when we replace an existing cert | ||
| 192 | // CertAddCertificateContextToStore(CERT_STORE_ADD_REPLACE_EXISTING) does not remove the private key if the cert is replaced | ||
| 193 | UninstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName); | ||
| 194 | |||
| 195 | hr = InstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName, pbData, cbData, iAttributes & SCA_CERT_ATTRIBUTE_VITAL, pwzPFXPassword); | ||
| 196 | ExitOnFailure(hr, "Failed to install certificate."); | ||
| 197 | } | ||
| 198 | else | ||
| 199 | { | ||
| 200 | Assert(SCA_ACTION_UNINSTALL == saAction); | ||
| 201 | |||
| 202 | hr = UninstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName); | ||
| 203 | ExitOnFailure(hr, "Failed to uninstall certificate."); | ||
| 204 | } | ||
| 205 | |||
| 206 | LExit: | ||
| 207 | if (NULL != pwzPFXPassword && SUCCEEDED(StrSize(pwzPFXPassword, &cbPFXPassword))) | ||
| 208 | { | ||
| 209 | SecureZeroMemory(pwzPFXPassword, cbPFXPassword); | ||
| 210 | } | ||
| 211 | |||
| 212 | if (hCertStore) | ||
| 213 | { | ||
| 214 | if (!::CertCloseStore(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG)) | ||
| 215 | { | ||
| 216 | WcaLog(LOGMSG_VERBOSE, "Cert store was closed but not all resources were freed. Error 0x%x", GetLastError()); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | ReleaseMem(pbData); | ||
| 221 | ReleaseStr(pwzFilePath); | ||
| 222 | ReleaseStr(pwzPFXPassword); | ||
| 223 | ReleaseStr(pwzStore); | ||
| 224 | ReleaseStr(pwzName); | ||
| 225 | ReleaseStr(pwzCaData); | ||
| 226 | return hr; | ||
| 227 | } | ||
| 228 | |||
| 229 | |||
| 230 | static HRESULT InstallCertificatePackage( | ||
| 231 | __in HCERTSTORE hStore, | ||
| 232 | __in BOOL fUserCertificateStore, | ||
| 233 | __in LPCWSTR wzName, | ||
| 234 | __in_opt BYTE* rgbData, | ||
| 235 | __in DWORD cbData, | ||
| 236 | __in BOOL fVital, | ||
| 237 | __in_opt LPCWSTR wzPFXPassword | ||
| 238 | ) | ||
| 239 | { | ||
| 240 | HRESULT hr = S_OK; | ||
| 241 | |||
| 242 | HCERTSTORE hPfxCertStore = NULL; | ||
| 243 | PCCERT_CONTEXT pCertContext = NULL; | ||
| 244 | CERT_BLOB blob = { 0 }; | ||
| 245 | DWORD dwKeyset = fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET; | ||
| 246 | DWORD dwEncodingType; | ||
| 247 | DWORD dwContentType; | ||
| 248 | DWORD dwFormatType; | ||
| 249 | LPWSTR pwzUniqueName = NULL; | ||
| 250 | int iUniqueId = 0; | ||
| 251 | |||
| 252 | // Figure out what type of blob (certificate or PFX) we're dealing with here. | ||
| 253 | blob.pbData = rgbData; | ||
| 254 | blob.cbData = cbData; | ||
| 255 | |||
| 256 | if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertContext)) | ||
| 257 | { | ||
| 258 | ExitWithLastError(hr, "Failed to parse the certificate blob: %ls", wzName); | ||
| 259 | } | ||
| 260 | |||
| 261 | hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId); | ||
| 262 | ExitOnFailure(hr, "Failed to format unique name"); | ||
| 263 | |||
| 264 | if (!pCertContext) | ||
| 265 | { | ||
| 266 | // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX. | ||
| 267 | if (dwContentType & CERT_QUERY_CONTENT_PFX) | ||
| 268 | { | ||
| 269 | ExitOnNull(wzPFXPassword, hr, E_INVALIDARG, "Failed to import PFX blob because no password was provided"); | ||
| 270 | |||
| 271 | // If we fail and our password is blank, also try passing in NULL for the password (according to the docs) | ||
| 272 | hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, dwKeyset); | ||
| 273 | if (NULL == hPfxCertStore && !*wzPFXPassword) | ||
| 274 | { | ||
| 275 | hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, NULL, dwKeyset); | ||
| 276 | } | ||
| 277 | ExitOnNullWithLastError(hPfxCertStore, hr, "Failed to open PFX file."); | ||
| 278 | |||
| 279 | // Install all certificates in the PFX | ||
| 280 | for (pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext); | ||
| 281 | pCertContext; | ||
| 282 | pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext)) | ||
| 283 | { | ||
| 284 | hr = AddCertificate(hStore, pCertContext, pwzUniqueName, fVital); | ||
| 285 | MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store."); | ||
| 286 | |||
| 287 | hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId); | ||
| 288 | ExitOnFailure(hr, "Failed to format unique name"); | ||
| 289 | } | ||
| 290 | } | ||
| 291 | else | ||
| 292 | { | ||
| 293 | hr = E_UNEXPECTED; | ||
| 294 | ExitOnFailure(hr, "Unexpected certificate type processed."); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | else | ||
| 298 | { | ||
| 299 | hr = AddCertificate(hStore, pCertContext, pwzUniqueName, fVital); | ||
| 300 | MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store."); | ||
| 301 | } | ||
| 302 | |||
| 303 | hr = WcaProgressMessage(COST_CERT_ADD, FALSE); | ||
| 304 | ExitOnFailure(hr, "Failed to send install progress message."); | ||
| 305 | |||
| 306 | LExit: | ||
| 307 | ReleaseStr(pwzUniqueName); | ||
| 308 | |||
| 309 | if (pCertContext) | ||
| 310 | { | ||
| 311 | ::CertFreeCertificateContext(pCertContext); | ||
| 312 | } | ||
| 313 | |||
| 314 | // Close the stores after the context's are released. | ||
| 315 | if (hPfxCertStore) | ||
| 316 | { | ||
| 317 | if (!::CertCloseStore(hPfxCertStore, CERT_CLOSE_STORE_CHECK_FLAG)) | ||
| 318 | { | ||
| 319 | WcaLog(LOGMSG_VERBOSE, "PFX cert store was closed but not all resources were freed. Error 0x%x", GetLastError()); | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | return hr; | ||
| 324 | } | ||
| 325 | |||
| 326 | |||
| 327 | static HRESULT UninstallCertificatePackage( | ||
| 328 | __in HCERTSTORE hStore, | ||
| 329 | __in BOOL fUserCertificateStore, | ||
| 330 | __in LPCWSTR wzName | ||
| 331 | ) | ||
| 332 | { | ||
| 333 | HRESULT hr = S_OK; | ||
| 334 | DWORD er = ERROR_SUCCESS; | ||
| 335 | PCCERT_CONTEXT pCertContext = NULL; | ||
| 336 | CRYPT_KEY_PROV_INFO* pPrivateKeyInfo = NULL; | ||
| 337 | LPWSTR pwzUniquePrefix = NULL; | ||
| 338 | int ccUniquePrefix = 0; | ||
| 339 | |||
| 340 | hr = StrAllocFormatted(&pwzUniquePrefix, L"%s_wixCert_", wzName); | ||
| 341 | ExitOnFailure(hr, "Failed to format unique name"); | ||
| 342 | ccUniquePrefix = ::lstrlenW(pwzUniquePrefix); | ||
| 343 | |||
| 344 | WcaLog(LOGMSG_STANDARD, "Deleting certificate that begin with friendly name: %ls", pwzUniquePrefix); | ||
| 345 | |||
| 346 | // Loop through all certificates in the store, deleting the ones that begin with our prefix. | ||
| 347 | while (NULL != (pCertContext = ::CertFindCertificateInStore(hStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pCertContext))) | ||
| 348 | { | ||
| 349 | WCHAR wzFriendlyName[256] = { 0 }; | ||
| 350 | DWORD cbFriendlyName = sizeof(wzFriendlyName); | ||
| 351 | |||
| 352 | if (::CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, reinterpret_cast<BYTE*>(wzFriendlyName), &cbFriendlyName) && | ||
| 353 | lstrlenW(wzFriendlyName) >= ccUniquePrefix && | ||
| 354 | CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, pwzUniquePrefix, ccUniquePrefix, wzFriendlyName, ccUniquePrefix)) | ||
| 355 | { | ||
| 356 | PCCERT_CONTEXT pCertContextDelete = ::CertDuplicateCertificateContext(pCertContext); // duplicate the context so we can delete it with out disrupting the looping | ||
| 357 | if(pCertContextDelete) | ||
| 358 | { | ||
| 359 | // Delete the certificate and if successful delete the matching private key as well. | ||
| 360 | if (::CertDeleteCertificateFromStore(pCertContextDelete)) | ||
| 361 | { | ||
| 362 | // If we found private key info, delete it. | ||
| 363 | hr = CertReadProperty(pCertContextDelete, CERT_KEY_PROV_INFO_PROP_ID, &pPrivateKeyInfo, NULL); | ||
| 364 | if (SUCCEEDED(hr)) | ||
| 365 | { | ||
| 366 | HCRYPTPROV hProvIgnored = NULL; // ignored on deletes. | ||
| 367 | DWORD dwKeyset = fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET; | ||
| 368 | |||
| 369 | if (!::CryptAcquireContextW(&hProvIgnored, pPrivateKeyInfo->pwszContainerName, pPrivateKeyInfo->pwszProvName, pPrivateKeyInfo->dwProvType, dwKeyset | CRYPT_DELETEKEYSET | CRYPT_SILENT)) | ||
| 370 | { | ||
| 371 | er = ::GetLastError(); | ||
| 372 | hr = HRESULT_FROM_WIN32(er); | ||
| 373 | } | ||
| 374 | |||
| 375 | ReleaseNullMem(pPrivateKeyInfo); | ||
| 376 | } | ||
| 377 | else // don't worry about failures to delete private keys. | ||
| 378 | { | ||
| 379 | hr = S_OK; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | else | ||
| 383 | { | ||
| 384 | er = ::GetLastError(); | ||
| 385 | hr = HRESULT_FROM_WIN32(er); | ||
| 386 | } | ||
| 387 | |||
| 388 | if (FAILED(hr)) | ||
| 389 | { | ||
| 390 | WcaLog(LOGMSG_STANDARD, "Failed to delete certificate with friendly name: %ls, continuing anyway. Error: 0x%x", wzFriendlyName, hr); | ||
| 391 | } | ||
| 392 | |||
| 393 | pCertContextDelete = NULL; | ||
| 394 | } | ||
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | hr = WcaProgressMessage(COST_CERT_DELETE, FALSE); | ||
| 399 | ExitOnFailure(hr, "Failed to send uninstall progress message."); | ||
| 400 | |||
| 401 | LExit: | ||
| 402 | ReleaseStr(pwzUniquePrefix); | ||
| 403 | ReleaseMem(pPrivateKeyInfo); | ||
| 404 | if(pCertContext) | ||
| 405 | { | ||
| 406 | ::CertFreeCertificateContext(pCertContext); | ||
| 407 | } | ||
| 408 | |||
| 409 | return hr; | ||
| 410 | } | ||
| 411 | |||
| 412 | static HRESULT AddCertificate( | ||
| 413 | __in HCERTSTORE hStore, | ||
| 414 | __in PCCERT_CONTEXT pCertContext, | ||
| 415 | __in LPCWSTR wzCertificateUniqueName, | ||
| 416 | __in BOOL fVital | ||
| 417 | ) | ||
| 418 | { | ||
| 419 | HRESULT hr = S_OK; | ||
| 420 | |||
| 421 | WcaLog(LOGMSG_STANDARD, "Adding certificate: %ls", wzCertificateUniqueName); | ||
| 422 | |||
| 423 | hr = CertInstallSingleCertificate(hStore, pCertContext, wzCertificateUniqueName); | ||
| 424 | if (FAILED(hr) && !fVital) | ||
| 425 | { | ||
| 426 | WcaLog(LOGMSG_STANDARD, "Could not add non-vital certificate: %ls due to error: 0x%x, continuing...", wzCertificateUniqueName, hr); | ||
| 427 | hr = S_FALSE; | ||
| 428 | } | ||
| 429 | |||
| 430 | return hr; | ||
| 431 | } | ||
diff --git a/src/ext/Iis/ca/scacost.h b/src/ext/Iis/ca/scacost.h new file mode 100644 index 00000000..be92cf26 --- /dev/null +++ b/src/ext/Iis/ca/scacost.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | const UINT COST_IIS_TRANSACTIONS = 10000; | ||
| 6 | |||
| 7 | const UINT COST_IIS_CREATEKEY = 5000; | ||
| 8 | const UINT COST_IIS_DELETEKEY = 5000; | ||
| 9 | const UINT COST_IIS_WRITEVALUE = 5000; | ||
| 10 | const UINT COST_IIS_DELETEVALUE = 5000; | ||
| 11 | const UINT COST_IIS_CREATEAPP = 5000; | ||
| 12 | const UINT COST_IIS_DELETEAPP = 5000; | ||
| 13 | |||
| 14 | const UINT COST_CERT_ADD = 5000; | ||
| 15 | const UINT COST_CERT_DELETE = 5000; | ||
diff --git a/src/ext/Iis/ca/scaexec.cpp b/src/ext/Iis/ca/scaexec.cpp new file mode 100644 index 00000000..df25e8db --- /dev/null +++ b/src/ext/Iis/ca/scaexec.cpp | |||
| @@ -0,0 +1,1184 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | /******************************************************************** | ||
| 7 | StartMetabaseTransaction - CUSTOM ACTION ENTRY POINT for backing up metabase | ||
| 8 | |||
| 9 | Input: deferred CustomActionData - BackupName | ||
| 10 | ********************************************************************/ | ||
| 11 | extern "C" UINT __stdcall StartMetabaseTransaction(MSIHANDLE hInstall) | ||
| 12 | { | ||
| 13 | //AssertSz(FALSE, "debug StartMetabaseTransaction here"); | ||
| 14 | HRESULT hr = S_OK; | ||
| 15 | UINT er = ERROR_SUCCESS; | ||
| 16 | |||
| 17 | IMSAdminBase* piMetabase = NULL; | ||
| 18 | LPWSTR pwzData = NULL; | ||
| 19 | BOOL fInitializedCom = FALSE; | ||
| 20 | |||
| 21 | // initialize | ||
| 22 | hr = WcaInitialize(hInstall, "StartMetabaseTransaction"); | ||
| 23 | ExitOnFailure(hr, "failed to initialize StartMetabaseTransaction"); | ||
| 24 | |||
| 25 | hr = ::CoInitialize(NULL); | ||
| 26 | ExitOnFailure(hr, "failed to initialize COM"); | ||
| 27 | fInitializedCom = TRUE; | ||
| 28 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase)); | ||
| 29 | if (hr == REGDB_E_CLASSNOTREG) | ||
| 30 | { | ||
| 31 | WcaLog(LOGMSG_STANDARD, "Failed to get IIMSAdminBase to backup - continuing"); | ||
| 32 | hr = S_OK; | ||
| 33 | } | ||
| 34 | else | ||
| 35 | { | ||
| 36 | MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object"); | ||
| 37 | |||
| 38 | hr = WcaGetProperty(L"CustomActionData", &pwzData); | ||
| 39 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 40 | |||
| 41 | // back up the metabase | ||
| 42 | Assert(lstrlenW(pwzData) < MD_BACKUP_MAX_LEN); | ||
| 43 | |||
| 44 | // MD_BACKUP_OVERWRITE = Overwrite if a backup of the same name and version exists in the backup location | ||
| 45 | hr = piMetabase->Backup(pwzData, MD_BACKUP_NEXT_VERSION, MD_BACKUP_OVERWRITE | MD_BACKUP_FORCE_BACKUP | MD_BACKUP_SAVE_FIRST); | ||
| 46 | if (MD_WARNING_SAVE_FAILED == hr) | ||
| 47 | { | ||
| 48 | WcaLog(LOGMSG_STANDARD, "Failed to save metabase before backing up - continuing"); | ||
| 49 | hr = S_OK; | ||
| 50 | } | ||
| 51 | MessageExitOnFailure(hr, msierrIISFailedStartTransaction, "failed to begin metabase transaction: '%ls'", pwzData); | ||
| 52 | } | ||
| 53 | hr = WcaProgressMessage(COST_IIS_TRANSACTIONS, FALSE); | ||
| 54 | LExit: | ||
| 55 | ReleaseStr(pwzData); | ||
| 56 | ReleaseObject(piMetabase); | ||
| 57 | |||
| 58 | if (fInitializedCom) | ||
| 59 | { | ||
| 60 | ::CoUninitialize(); | ||
| 61 | } | ||
| 62 | |||
| 63 | if (FAILED(hr)) | ||
| 64 | er = ERROR_INSTALL_FAILURE; | ||
| 65 | return WcaFinalize(er); | ||
| 66 | } | ||
| 67 | |||
| 68 | |||
| 69 | /******************************************************************** | ||
| 70 | RollbackMetabaseTransaction - CUSTOM ACTION ENTRY POINT for unbacking up metabase | ||
| 71 | |||
| 72 | Input: deferred CustomActionData - BackupName | ||
| 73 | ********************************************************************/ | ||
| 74 | extern "C" UINT __stdcall RollbackMetabaseTransaction(MSIHANDLE hInstall) | ||
| 75 | { | ||
| 76 | //AssertSz(FALSE, "debug RollbackMetabaseTransaction here"); | ||
| 77 | HRESULT hr = S_OK; | ||
| 78 | UINT er = ERROR_SUCCESS; | ||
| 79 | |||
| 80 | IMSAdminBase* piMetabase = NULL; | ||
| 81 | LPWSTR pwzData = NULL; | ||
| 82 | BOOL fInitializedCom = FALSE; | ||
| 83 | |||
| 84 | hr = WcaInitialize(hInstall, "RollbackMetabaseTransaction"); | ||
| 85 | ExitOnFailure(hr, "failed to initialize"); | ||
| 86 | |||
| 87 | hr = ::CoInitialize(NULL); | ||
| 88 | ExitOnFailure(hr, "failed to initialize COM"); | ||
| 89 | fInitializedCom = TRUE; | ||
| 90 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase)); | ||
| 91 | if (hr == REGDB_E_CLASSNOTREG) | ||
| 92 | { | ||
| 93 | WcaLog(LOGMSG_STANDARD, "Failed to get IIMSAdminBase to rollback - continuing"); | ||
| 94 | hr = S_OK; | ||
| 95 | ExitFunction(); | ||
| 96 | } | ||
| 97 | ExitOnFailure(hr, "failed to get IID_IIMSAdminBase object"); | ||
| 98 | |||
| 99 | |||
| 100 | hr = WcaGetProperty( L"CustomActionData", &pwzData); | ||
| 101 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 102 | |||
| 103 | hr = piMetabase->Restore(pwzData, MD_BACKUP_HIGHEST_VERSION, 0); | ||
| 104 | ExitOnFailure(hr, "failed to rollback metabase transaction: '%ls'", pwzData); | ||
| 105 | |||
| 106 | hr = piMetabase->DeleteBackup(pwzData, MD_BACKUP_HIGHEST_VERSION); | ||
| 107 | ExitOnFailure(hr, "failed to cleanup metabase transaction '%ls', continuing", pwzData); | ||
| 108 | |||
| 109 | LExit: | ||
| 110 | ReleaseStr(pwzData); | ||
| 111 | ReleaseObject(piMetabase); | ||
| 112 | |||
| 113 | if (fInitializedCom) | ||
| 114 | { | ||
| 115 | ::CoUninitialize(); | ||
| 116 | } | ||
| 117 | |||
| 118 | if (FAILED(hr)) | ||
| 119 | { | ||
| 120 | er = ERROR_INSTALL_FAILURE; | ||
| 121 | } | ||
| 122 | return WcaFinalize(er); | ||
| 123 | } | ||
| 124 | |||
| 125 | |||
| 126 | /******************************************************************** | ||
| 127 | CommitMetabaseTransaction - CUSTOM ACTION ENTRY POINT for unbacking up metabase | ||
| 128 | |||
| 129 | Input: deferred CustomActionData - BackupName | ||
| 130 | * *****************************************************************/ | ||
| 131 | extern "C" UINT __stdcall CommitMetabaseTransaction(MSIHANDLE hInstall) | ||
| 132 | { | ||
| 133 | HRESULT hr = S_OK; | ||
| 134 | UINT er = ERROR_SUCCESS; | ||
| 135 | |||
| 136 | IMSAdminBase* piMetabase = NULL; | ||
| 137 | LPWSTR pwzData = NULL; | ||
| 138 | BOOL fInitializedCom = FALSE; | ||
| 139 | |||
| 140 | hr = WcaInitialize(hInstall, "CommitMetabaseTransaction"); | ||
| 141 | ExitOnFailure(hr, "failed to initialize"); | ||
| 142 | |||
| 143 | hr = ::CoInitialize(NULL); | ||
| 144 | ExitOnFailure(hr, "failed to initialize COM"); | ||
| 145 | fInitializedCom = TRUE; | ||
| 146 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase)); | ||
| 147 | if (hr == REGDB_E_CLASSNOTREG) | ||
| 148 | { | ||
| 149 | WcaLog(LOGMSG_STANDARD, "Failed to get IIMSAdminBase to commit - continuing"); | ||
| 150 | hr = S_OK; | ||
| 151 | ExitFunction(); | ||
| 152 | } | ||
| 153 | ExitOnFailure(hr, "failed to get IID_IIMSAdminBase object"); | ||
| 154 | |||
| 155 | hr = WcaGetProperty( L"CustomActionData", &pwzData); | ||
| 156 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 157 | |||
| 158 | hr = piMetabase->DeleteBackup(pwzData, MD_BACKUP_HIGHEST_VERSION); | ||
| 159 | ExitOnFailure(hr, "failed to cleanup metabase transaction: '%ls'", pwzData); | ||
| 160 | |||
| 161 | LExit: | ||
| 162 | ReleaseStr(pwzData); | ||
| 163 | ReleaseObject(piMetabase); | ||
| 164 | |||
| 165 | if (fInitializedCom) | ||
| 166 | { | ||
| 167 | ::CoUninitialize(); | ||
| 168 | } | ||
| 169 | |||
| 170 | if (FAILED(hr)) | ||
| 171 | { | ||
| 172 | er = ERROR_INSTALL_FAILURE; | ||
| 173 | } | ||
| 174 | return WcaFinalize(er); | ||
| 175 | } | ||
| 176 | |||
| 177 | |||
| 178 | /******************************************************************** | ||
| 179 | CreateMetabaseKey - Installs metabase keys | ||
| 180 | |||
| 181 | Input: deferred CustomActionData - Key | ||
| 182 | * *****************************************************************/ | ||
| 183 | static HRESULT CreateMetabaseKey(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase) | ||
| 184 | { | ||
| 185 | //AssertSz(FALSE, "debug CreateMetabaseKey here"); | ||
| 186 | HRESULT hr = S_OK; | ||
| 187 | METADATA_HANDLE mhRoot = 0; | ||
| 188 | LPWSTR pwzData = NULL; | ||
| 189 | LPCWSTR pwzKey; | ||
| 190 | |||
| 191 | int i; | ||
| 192 | |||
| 193 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 194 | ExitOnFailure(hr, "failed to read key from custom action data"); | ||
| 195 | |||
| 196 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot); | ||
| 197 | for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--) | ||
| 198 | { | ||
| 199 | ::Sleep(1000); | ||
| 200 | WcaLog(LOGMSG_STANDARD, "failed to open root key, retrying %d time(s)...", i); | ||
| 201 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot); | ||
| 202 | } | ||
| 203 | MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", L"/LM"); | ||
| 204 | |||
| 205 | pwzKey = pwzData + 3; | ||
| 206 | |||
| 207 | WcaLog(LOGMSG_VERBOSE, "Creating Metabase Key: %ls", pwzKey); | ||
| 208 | |||
| 209 | hr = piMetabase->AddKey(mhRoot, pwzKey); | ||
| 210 | if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr) | ||
| 211 | { | ||
| 212 | WcaLog(LOGMSG_VERBOSE, "Key `%ls` already existed, continuing.", pwzData); | ||
| 213 | hr = S_OK; | ||
| 214 | } | ||
| 215 | MessageExitOnFailure(hr, msierrIISFailedCreateKey, "failed to create metabase key: %ls", pwzKey); | ||
| 216 | |||
| 217 | hr = WcaProgressMessage(COST_IIS_CREATEKEY, FALSE); | ||
| 218 | |||
| 219 | LExit: | ||
| 220 | if (mhRoot) | ||
| 221 | { | ||
| 222 | piMetabase->CloseKey(mhRoot); | ||
| 223 | } | ||
| 224 | |||
| 225 | return hr; | ||
| 226 | } | ||
| 227 | |||
| 228 | |||
| 229 | /******************************************************************** | ||
| 230 | WriteMetabaseValue -Installs metabase values | ||
| 231 | |||
| 232 | Input: deferred CustomActionData - Key\tIdentifier\tAttributes\tUserType\tDataType\tData | ||
| 233 | * *****************************************************************/ | ||
| 234 | static HRESULT WriteMetabaseValue(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase) | ||
| 235 | { | ||
| 236 | //AssertSz(FALSE, "debug WriteMetabaseValue here"); | ||
| 237 | HRESULT hr = S_OK; | ||
| 238 | |||
| 239 | METADATA_HANDLE mhKey = 0; | ||
| 240 | |||
| 241 | LPWSTR pwzKey = NULL; | ||
| 242 | LPWSTR pwzTemp = NULL; | ||
| 243 | DWORD dwData = 0; | ||
| 244 | DWORD dwTemp = 0; | ||
| 245 | BOOL fFreeData = FALSE; | ||
| 246 | METADATA_RECORD mr; | ||
| 247 | ::ZeroMemory((LPVOID)&mr, sizeof(mr)); | ||
| 248 | METADATA_RECORD mrGet; | ||
| 249 | ::ZeroMemory((LPVOID)&mrGet, sizeof(mrGet)); | ||
| 250 | |||
| 251 | int i; | ||
| 252 | |||
| 253 | // get the key first | ||
| 254 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzKey); | ||
| 255 | ExitOnFailure(hr, "failed to read key"); | ||
| 256 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDIdentifier)); | ||
| 257 | ExitOnFailure(hr, "failed to read identifier"); | ||
| 258 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDAttributes)); | ||
| 259 | ExitOnFailure(hr, "failed to read attributes"); | ||
| 260 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDUserType)); | ||
| 261 | ExitOnFailure(hr, "failed to read user type"); | ||
| 262 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDDataType)); | ||
| 263 | ExitOnFailure(hr, "failed to read data type"); | ||
| 264 | |||
| 265 | switch (mr.dwMDDataType) // data | ||
| 266 | { | ||
| 267 | case DWORD_METADATA: | ||
| 268 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&dwData)); | ||
| 269 | mr.dwMDDataLen = sizeof(dwData); | ||
| 270 | mr.pbMDData = reinterpret_cast<BYTE*>(&dwData); | ||
| 271 | break; | ||
| 272 | case STRING_METADATA: | ||
| 273 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzTemp); | ||
| 274 | mr.dwMDDataLen = (lstrlenW(pwzTemp) + 1) * sizeof(WCHAR); | ||
| 275 | mr.pbMDData = reinterpret_cast<BYTE*>(pwzTemp); | ||
| 276 | break; | ||
| 277 | case MULTISZ_METADATA: | ||
| 278 | { | ||
| 279 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzTemp); | ||
| 280 | mr.dwMDDataLen = (lstrlenW(pwzTemp) + 1) * sizeof(WCHAR); | ||
| 281 | for (LPWSTR pwzT = pwzTemp; *pwzT; ++pwzT) | ||
| 282 | { | ||
| 283 | if (MAGIC_MULTISZ_CHAR == *pwzT) | ||
| 284 | { | ||
| 285 | *pwzT = L'\0'; | ||
| 286 | } | ||
| 287 | } | ||
| 288 | mr.pbMDData = reinterpret_cast<BYTE*>(pwzTemp); | ||
| 289 | } | ||
| 290 | break; | ||
| 291 | case BINARY_METADATA: | ||
| 292 | hr = WcaReadStreamFromCaData(ppwzCustomActionData, &mr.pbMDData, reinterpret_cast<DWORD_PTR *>(&mr.dwMDDataLen)); | ||
| 293 | fFreeData = TRUE; | ||
| 294 | break; | ||
| 295 | default: | ||
| 296 | hr = E_UNEXPECTED; | ||
| 297 | break; | ||
| 298 | } | ||
| 299 | ExitOnFailure(hr, "failed to parse CustomActionData into metabase record"); | ||
| 300 | |||
| 301 | WcaLog(LOGMSG_VERBOSE, "Writing Metabase Value Under Key: %ls ID: %d", pwzKey, mr.dwMDIdentifier); | ||
| 302 | |||
| 303 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey); | ||
| 304 | for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--) | ||
| 305 | { | ||
| 306 | ::Sleep(1000); | ||
| 307 | WcaLog(LOGMSG_STANDARD, "failed to open '%ls' key, retrying %d time(s)...", pwzKey, i); | ||
| 308 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey); | ||
| 309 | } | ||
| 310 | MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", pwzKey); | ||
| 311 | |||
| 312 | if (lstrlenW(pwzKey) < 3) | ||
| 313 | { | ||
| 314 | ExitOnFailure(hr = E_INVALIDARG, "Key didn't begin with \"/LM\" as expected - key value: %ls", pwzKey); | ||
| 315 | } | ||
| 316 | |||
| 317 | hr = piMetabase->SetData(mhKey, pwzKey + 3, &mr); // pwzKey + 3 to skip "/LM" that was used to open the key. | ||
| 318 | |||
| 319 | // This means we're trying to write to a secure key without the secure flag set - let's try again with the secure flag set | ||
| 320 | if (MD_ERROR_CANNOT_REMOVE_SECURE_ATTRIBUTE == hr) | ||
| 321 | { | ||
| 322 | mr.dwMDAttributes |= METADATA_SECURE; | ||
| 323 | hr = piMetabase->SetData(mhKey, pwzKey + 3, &mr); | ||
| 324 | } | ||
| 325 | |||
| 326 | // If IIS6 returned failure, let's check if the correct value exists in the metabase before actually failing the CA | ||
| 327 | if (FAILED(hr)) | ||
| 328 | { | ||
| 329 | // Backup the original failure error, so we can log it below if necessary | ||
| 330 | HRESULT hrOldValue = hr; | ||
| 331 | |||
| 332 | mrGet.dwMDIdentifier = mr.dwMDIdentifier; | ||
| 333 | mrGet.dwMDAttributes = METADATA_NO_ATTRIBUTES; | ||
| 334 | mrGet.dwMDUserType = mr.dwMDUserType; | ||
| 335 | mrGet.dwMDDataType = mr.dwMDDataType; | ||
| 336 | mrGet.dwMDDataLen = mr.dwMDDataLen; | ||
| 337 | mrGet.pbMDData = static_cast<BYTE*>(MemAlloc(mr.dwMDDataLen, TRUE)); | ||
| 338 | |||
| 339 | hr = piMetabase->GetData(mhKey, pwzKey + 3, &mrGet, &dwTemp); | ||
| 340 | if (SUCCEEDED(hr)) | ||
| 341 | { | ||
| 342 | if (mrGet.dwMDDataType == mr.dwMDDataType && mrGet.dwMDDataLen == mr.dwMDDataLen && 0 == memcmp(mrGet.pbMDData, mr.pbMDData, mr.dwMDDataLen)) | ||
| 343 | { | ||
| 344 | WcaLog(LOGMSG_VERBOSE, "Received error while writing metabase value under key: %ls ID: %d with error 0x%x, but the correct value is in the metabase - continuing", pwzKey, mr.dwMDIdentifier, hrOldValue); | ||
| 345 | hr = S_OK; | ||
| 346 | } | ||
| 347 | else | ||
| 348 | { | ||
| 349 | WcaLog(LOGMSG_VERBOSE, "Succeeded in checking metabase value after write value, but the values didn't match"); | ||
| 350 | hr = hrOldValue; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | else | ||
| 354 | { | ||
| 355 | WcaLog(LOGMSG_VERBOSE, "Failed to check value after metabase write failure (error code 0x%x)", hr); | ||
| 356 | hr = hrOldValue; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | MessageExitOnFailure(hr, msierrIISFailedWriteData, "failed to write data to metabase key: %ls", pwzKey); | ||
| 360 | |||
| 361 | hr = WcaProgressMessage(COST_IIS_WRITEVALUE, FALSE); | ||
| 362 | |||
| 363 | LExit: | ||
| 364 | ReleaseStr(pwzTemp); | ||
| 365 | ReleaseStr(pwzKey); | ||
| 366 | |||
| 367 | if (mhKey) | ||
| 368 | { | ||
| 369 | piMetabase->CloseKey(mhKey); | ||
| 370 | } | ||
| 371 | |||
| 372 | if (fFreeData && mr.pbMDData) | ||
| 373 | { | ||
| 374 | MemFree(mr.pbMDData); | ||
| 375 | } | ||
| 376 | |||
| 377 | return hr; | ||
| 378 | } | ||
| 379 | |||
| 380 | |||
| 381 | /******************************************************************** | ||
| 382 | DeleteMetabaseValue -Installs metabase values | ||
| 383 | |||
| 384 | Input: deferred CustomActionData - Key\tIdentifier\tAttributes\tUserType\tDataType\tData | ||
| 385 | * *****************************************************************/ | ||
| 386 | static HRESULT DeleteMetabaseValue(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase) | ||
| 387 | { | ||
| 388 | //AssertSz(FALSE, "debug DeleteMetabaseValue here"); | ||
| 389 | HRESULT hr = S_OK; | ||
| 390 | |||
| 391 | METADATA_HANDLE mhKey = 0; | ||
| 392 | |||
| 393 | LPWSTR pwzKey = NULL; | ||
| 394 | DWORD dwIdentifier = 0; | ||
| 395 | DWORD dwDataType = 0; | ||
| 396 | |||
| 397 | int i; | ||
| 398 | |||
| 399 | // get the key first | ||
| 400 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzKey); | ||
| 401 | ExitOnFailure(hr, "failed to read key"); | ||
| 402 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&dwIdentifier)); | ||
| 403 | ExitOnFailure(hr, "failed to read identifier"); | ||
| 404 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&dwDataType)); | ||
| 405 | ExitOnFailure(hr, "failed to read data type"); | ||
| 406 | |||
| 407 | WcaLog(LOGMSG_VERBOSE, "Deleting Metabase Value Under Key: %ls ID: %d", pwzKey, dwIdentifier); | ||
| 408 | |||
| 409 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey); | ||
| 410 | for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--) | ||
| 411 | { | ||
| 412 | ::Sleep(1000); | ||
| 413 | WcaLog(LOGMSG_STANDARD, "failed to open '%ls' key, retrying %d time(s)...", pwzKey, i); | ||
| 414 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey); | ||
| 415 | } | ||
| 416 | MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", pwzKey); | ||
| 417 | |||
| 418 | if (lstrlenW(pwzKey) < 3) | ||
| 419 | { | ||
| 420 | ExitOnFailure(hr = E_INVALIDARG, "Key didn't begin with \"/LM\" as expected - key value: %ls", pwzKey); | ||
| 421 | } | ||
| 422 | |||
| 423 | hr = piMetabase->DeleteData(mhKey, pwzKey + 3, dwIdentifier, dwDataType); // pwzKey + 3 to skip "/LM" that was used to open the key. | ||
| 424 | if (MD_ERROR_DATA_NOT_FOUND == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) | ||
| 425 | { | ||
| 426 | hr = S_OK; | ||
| 427 | } | ||
| 428 | MessageExitOnFailure(hr, msierrIISFailedDeleteValue, "failed to delete value %d from metabase key: %ls", dwIdentifier, pwzKey); | ||
| 429 | |||
| 430 | hr = WcaProgressMessage(COST_IIS_DELETEVALUE, FALSE); | ||
| 431 | LExit: | ||
| 432 | ReleaseStr(pwzKey); | ||
| 433 | |||
| 434 | if (mhKey) | ||
| 435 | piMetabase->CloseKey(mhKey); | ||
| 436 | |||
| 437 | return hr; | ||
| 438 | } | ||
| 439 | |||
| 440 | |||
| 441 | /******************************************************************** | ||
| 442 | DeleteAspApp - Deletes applications in IIS | ||
| 443 | |||
| 444 | Input: deferred CustomActionData - MetabaseRoot\tRecursive | ||
| 445 | * *****************************************************************/ | ||
| 446 | static HRESULT DeleteAspApp(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase, __in ICatalogCollection* pApplicationCollection, __in IWamAdmin* piWam) | ||
| 447 | { | ||
| 448 | const int BUFFER_BYTES = 512; | ||
| 449 | const BSTR bstrPropName = SysAllocString(L"Deleteable"); | ||
| 450 | |||
| 451 | HRESULT hr = S_OK; | ||
| 452 | ICatalogObject* pApplication = NULL; | ||
| 453 | |||
| 454 | LPWSTR pwzRoot = NULL; | ||
| 455 | DWORD dwActualBufferSize = 0; | ||
| 456 | long lSize = 0; | ||
| 457 | long lIndex = 0; | ||
| 458 | long lChanges = 0; | ||
| 459 | |||
| 460 | VARIANT keyValue; | ||
| 461 | ::VariantInit(&keyValue); | ||
| 462 | VARIANT propValue; | ||
| 463 | propValue.vt = VT_BOOL; | ||
| 464 | propValue.boolVal = TRUE; | ||
| 465 | |||
| 466 | METADATA_RECORD mr; | ||
| 467 | // Get current set of web service extensions. | ||
| 468 | ::ZeroMemory(&mr, sizeof(mr)); | ||
| 469 | mr.dwMDIdentifier = MD_APP_PACKAGE_ID; | ||
| 470 | mr.dwMDAttributes = 0; | ||
| 471 | mr.dwMDUserType = ASP_MD_UT_APP; | ||
| 472 | mr.dwMDDataType = STRING_METADATA; | ||
| 473 | mr.pbMDData = new unsigned char[BUFFER_BYTES]; | ||
| 474 | mr.dwMDDataLen = BUFFER_BYTES; | ||
| 475 | |||
| 476 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzRoot); // MetabaseRoot | ||
| 477 | ExitOnFailure(hr, "failed to get metabase root"); | ||
| 478 | |||
| 479 | hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, pwzRoot, &mr, &dwActualBufferSize); | ||
| 480 | if (HRESULT_FROM_WIN32(MD_ERROR_DATA_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
| 481 | { | ||
| 482 | // This one doesn't have an independent app GUID associated with it - it may have been already partially deleted, or a low isolation app | ||
| 483 | WcaLog(LOGMSG_VERBOSE, "No independent COM+ application found associated with %ls. It either doesn't exist, or was already removed - continuing", pwzRoot); | ||
| 484 | ExitFunction1(hr = S_OK); | ||
| 485 | } | ||
| 486 | MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get GUID for application at path: %ls", pwzRoot); | ||
| 487 | |||
| 488 | WcaLog(LOGMSG_VERBOSE, "Deleting ASP App (used query: %ls) with GUID: %ls", pwzRoot, (LPWSTR)(mr.pbMDData)); | ||
| 489 | |||
| 490 | // Delete the application association from IIS's point of view before it's obliterated from the application collection | ||
| 491 | hr = piWam->AppDelete(pwzRoot, FALSE); | ||
| 492 | if (FAILED(hr)) | ||
| 493 | { | ||
| 494 | // This isn't necessarily an error if we fail here, but let's log a failure if it happens | ||
| 495 | WcaLog(LOGMSG_VERBOSE, "error 0x%x: failed to call IWamAdmin::AppDelete() while removing web application - continuing"); | ||
| 496 | hr = S_OK; | ||
| 497 | } | ||
| 498 | |||
| 499 | if (!pApplicationCollection) | ||
| 500 | { | ||
| 501 | WcaLog(LOGMSG_STANDARD, "Could not remove application with GUID %ls because the application collection could not be found", (LPWSTR)(mr.pbMDData)); | ||
| 502 | ExitFunction1(hr = S_OK); | ||
| 503 | } | ||
| 504 | |||
| 505 | hr = pApplicationCollection->Populate(); | ||
| 506 | MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to populate Application collection"); | ||
| 507 | |||
| 508 | hr = pApplicationCollection->get_Count(&lSize); | ||
| 509 | MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get size of Application collection"); | ||
| 510 | WcaLog(LOGMSG_TRACEONLY, "Found %u items in application collection", lSize); | ||
| 511 | |||
| 512 | // No need to check this too early, as we may not even need this to have successfully allocated | ||
| 513 | ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "failed to allocate memory for \"Deleteable\" string"); | ||
| 514 | |||
| 515 | for (lIndex = 0; lIndex < lSize; ++lIndex) | ||
| 516 | { | ||
| 517 | hr = pApplicationCollection->get_Item(lIndex, reinterpret_cast<IDispatch**>(&pApplication)); | ||
| 518 | MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get COM+ application while enumerating through COM+ applications"); | ||
| 519 | |||
| 520 | hr = pApplication->get_Key(&keyValue); | ||
| 521 | MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get key of COM+ application while enumerating through COM+ applications"); | ||
| 522 | |||
| 523 | WcaLog(LOGMSG_TRACEONLY, "While enumerating through COM+ applications, found an application with GUID: %ls", (LPWSTR)keyValue.bstrVal); | ||
| 524 | |||
| 525 | if (VT_BSTR == keyValue.vt && 0 == lstrcmpW((LPWSTR)keyValue.bstrVal, (LPWSTR)(mr.pbMDData))) | ||
| 526 | { | ||
| 527 | hr = pApplication->put_Value(bstrPropName, propValue); | ||
| 528 | if (FAILED(hr)) | ||
| 529 | { | ||
| 530 | // This isn't necessarily a critical error unless we fail to actually delete it in the next step | ||
| 531 | WcaLog(LOGMSG_VERBOSE, "error 0x%x: failed to ensure COM+ application with guid %ls is deletable - continuing", hr, (LPWSTR)(mr.pbMDData)); | ||
| 532 | } | ||
| 533 | |||
| 534 | hr = pApplicationCollection->SaveChanges(&lChanges); | ||
| 535 | if (FAILED(hr)) | ||
| 536 | { | ||
| 537 | // This isn't necessarily a critical error unless we fail to actually delete it in the next step | ||
| 538 | WcaLog(LOGMSG_VERBOSE, "error 0x%x: failed to save changes while ensuring COM+ application with guid %ls is deletable - continuing", hr, (LPWSTR)(mr.pbMDData)); | ||
| 539 | } | ||
| 540 | |||
| 541 | hr = pApplicationCollection->Remove(lIndex); | ||
| 542 | if (FAILED(hr)) | ||
| 543 | { | ||
| 544 | WcaLog(LOGMSG_STANDARD, "error 0x%x: failed to remove COM+ application with guid %ls. The COM application will not be removed", hr, (LPWSTR)(mr.pbMDData)); | ||
| 545 | } | ||
| 546 | else | ||
| 547 | { | ||
| 548 | hr = pApplicationCollection->SaveChanges(&lChanges); | ||
| 549 | if (FAILED(hr)) | ||
| 550 | { | ||
| 551 | WcaLog(LOGMSG_STANDARD, "error 0x%x: failed to save changes when removing COM+ application with guid %ls. The COM application will not be removed - continuing", hr, (LPWSTR)(mr.pbMDData)); | ||
| 552 | } | ||
| 553 | else | ||
| 554 | { | ||
| 555 | WcaLog(LOGMSG_VERBOSE, "Found and removed application with GUID %ls", (LPWSTR)(mr.pbMDData)); | ||
| 556 | } | ||
| 557 | } | ||
| 558 | |||
| 559 | // We've found the right key and successfully deleted the app - let's exit the loop now | ||
| 560 | lIndex = lSize; | ||
| 561 | } | ||
| 562 | } | ||
| 563 | // If we didn't find it, it isn't an error, because the application we want to delete doesn't seem to exist! | ||
| 564 | |||
| 565 | hr = WcaProgressMessage(COST_IIS_DELETEAPP, FALSE); | ||
| 566 | LExit: | ||
| 567 | ReleaseBSTR(bstrPropName); | ||
| 568 | |||
| 569 | ReleaseStr(pwzRoot); | ||
| 570 | // Don't release pApplication, because it points to an object within the collection | ||
| 571 | |||
| 572 | delete [] mr.pbMDData; | ||
| 573 | |||
| 574 | return hr; | ||
| 575 | } | ||
| 576 | |||
| 577 | |||
| 578 | /******************************************************************** | ||
| 579 | CreateAspApp - Creates applications in IIS | ||
| 580 | |||
| 581 | Input: deferred CustomActionData - MetabaseRoot\tInProc | ||
| 582 | * ****************************************************************/ | ||
| 583 | static HRESULT CreateAspApp(__in LPWSTR* ppwzCustomActionData, __in IWamAdmin* piWam) | ||
| 584 | { | ||
| 585 | HRESULT hr = S_OK; | ||
| 586 | |||
| 587 | LPWSTR pwzRoot = NULL; | ||
| 588 | BOOL fInProc; | ||
| 589 | |||
| 590 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzRoot); // MetabaseRoot | ||
| 591 | ExitOnFailure(hr, "failed to get metabase root"); | ||
| 592 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&fInProc)); // InProc | ||
| 593 | ExitOnFailure(hr, "failed to get in proc flag"); | ||
| 594 | |||
| 595 | WcaLog(LOGMSG_VERBOSE, "Creating ASP App: %ls", pwzRoot); | ||
| 596 | |||
| 597 | hr = piWam->AppCreate(pwzRoot, fInProc); | ||
| 598 | MessageExitOnFailure(hr, msierrIISFailedCreateApp, "failed to create web application: %ls", pwzRoot); | ||
| 599 | |||
| 600 | hr = WcaProgressMessage(COST_IIS_CREATEAPP, FALSE); | ||
| 601 | LExit: | ||
| 602 | return hr; | ||
| 603 | } | ||
| 604 | |||
| 605 | |||
| 606 | /******************************************************************** | ||
| 607 | DeleteMetabaseKey - Deletes metabase keys | ||
| 608 | |||
| 609 | Input: deferred CustomActionData - Key | ||
| 610 | ******************************************************************/ | ||
| 611 | static HRESULT DeleteMetabaseKey(__in LPWSTR *ppwzCustomActionData, __in IMSAdminBase* piMetabase) | ||
| 612 | { | ||
| 613 | HRESULT hr = S_OK; | ||
| 614 | |||
| 615 | METADATA_HANDLE mhRoot = 0; | ||
| 616 | |||
| 617 | LPWSTR pwzData = NULL; | ||
| 618 | |||
| 619 | LPCWSTR pwzKey; | ||
| 620 | int i; | ||
| 621 | |||
| 622 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 623 | ExitOnFailure(hr, "failed to read key to be deleted"); | ||
| 624 | |||
| 625 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot); | ||
| 626 | for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--) | ||
| 627 | { | ||
| 628 | ::Sleep(1000); | ||
| 629 | WcaLog(LOGMSG_STANDARD, "failed to open root key, retrying %d time(s)...", i); | ||
| 630 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot); | ||
| 631 | } | ||
| 632 | MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", L"/LM"); | ||
| 633 | |||
| 634 | pwzKey = pwzData + 3; | ||
| 635 | |||
| 636 | WcaLog(LOGMSG_VERBOSE, "Deleting Metabase Key: %ls", pwzKey); | ||
| 637 | |||
| 638 | hr = piMetabase->DeleteKey(mhRoot, pwzKey); | ||
| 639 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) | ||
| 640 | { | ||
| 641 | WcaLog(LOGMSG_STANDARD, "Key `%ls` did not exist, continuing.", pwzData); | ||
| 642 | hr = S_OK; | ||
| 643 | } | ||
| 644 | MessageExitOnFailure(hr, msierrIISFailedDeleteKey, "failed to delete metabase key: %ls", pwzData); | ||
| 645 | |||
| 646 | hr = WcaProgressMessage(COST_IIS_DELETEKEY, FALSE); | ||
| 647 | LExit: | ||
| 648 | if (mhRoot) | ||
| 649 | { | ||
| 650 | piMetabase->CloseKey(mhRoot); | ||
| 651 | } | ||
| 652 | |||
| 653 | return hr; | ||
| 654 | } | ||
| 655 | |||
| 656 | |||
| 657 | /******************************************************************** | ||
| 658 | WriteMetabaseChanges - CUSTOM ACTION ENTRY POINT for IIS Metabase changes | ||
| 659 | |||
| 660 | *******************************************************************/ | ||
| 661 | extern "C" UINT __stdcall WriteMetabaseChanges(MSIHANDLE hInstall) | ||
| 662 | { | ||
| 663 | //AssertSz(FALSE, "debug WriteMetabaseChanges here"); | ||
| 664 | HRESULT hr = S_OK; | ||
| 665 | UINT er = ERROR_SUCCESS; | ||
| 666 | IMSAdminBase* piMetabase = NULL; | ||
| 667 | IWamAdmin* piWam = NULL; | ||
| 668 | ICOMAdminCatalog* pCatalog = NULL; | ||
| 669 | ICatalogCollection* pApplicationCollection = NULL; | ||
| 670 | WCA_CASCRIPT_HANDLE hWriteMetabaseScript = NULL; | ||
| 671 | BSTR bstrApplications = SysAllocString(L"Applications"); | ||
| 672 | BOOL fInitializedCom = FALSE; | ||
| 673 | |||
| 674 | LPWSTR pwzData = NULL; | ||
| 675 | LPWSTR pwz = NULL; | ||
| 676 | LPWSTR pwzScriptKey = NULL; | ||
| 677 | METABASE_ACTION maAction = MBA_UNKNOWNACTION; | ||
| 678 | |||
| 679 | hr = WcaInitialize(hInstall, "WriteMetabaseChanges"); | ||
| 680 | ExitOnFailure(hr, "failed to initialize"); | ||
| 681 | |||
| 682 | hr = ::CoInitialize(NULL); | ||
| 683 | ExitOnFailure(hr, "failed to initialize COM"); | ||
| 684 | fInitializedCom = TRUE; | ||
| 685 | |||
| 686 | hr = WcaGetProperty( L"CustomActionData", &pwzData); | ||
| 687 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 688 | |||
| 689 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | ||
| 690 | |||
| 691 | // Get the CaScript key | ||
| 692 | hr = WcaReadStringFromCaData(&pwzData, &pwzScriptKey); | ||
| 693 | ExitOnFailure(hr, "Failed to get CaScript key from custom action data"); | ||
| 694 | |||
| 695 | hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzScriptKey, &hWriteMetabaseScript); | ||
| 696 | ExitOnFailure(hr, "Failed to open CaScript file"); | ||
| 697 | |||
| 698 | // The rest of our existing custom action data string should be empty - go ahead and overwrite it | ||
| 699 | ReleaseNullStr(pwzData); | ||
| 700 | hr = WcaCaScriptReadAsCustomActionData(hWriteMetabaseScript, &pwzData); | ||
| 701 | ExitOnFailure(hr, "Failed to read script into CustomAction data."); | ||
| 702 | |||
| 703 | pwz = pwzData; | ||
| 704 | |||
| 705 | while (S_OK == (hr = WcaReadIntegerFromCaData(&pwz, (int *)&maAction))) | ||
| 706 | { | ||
| 707 | switch (maAction) | ||
| 708 | { | ||
| 709 | case MBA_CREATEAPP: | ||
| 710 | if (NULL == piWam) | ||
| 711 | { | ||
| 712 | hr = ::CoCreateInstance(CLSID_WamAdmin, NULL, CLSCTX_ALL, IID_IWamAdmin, reinterpret_cast<void**>(&piWam)); | ||
| 713 | MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IWamAdmin object"); | ||
| 714 | } | ||
| 715 | |||
| 716 | hr = CreateAspApp(&pwz, piWam); | ||
| 717 | ExitOnFailure(hr, "failed to create ASP App"); | ||
| 718 | break; | ||
| 719 | case MBA_DELETEAPP: | ||
| 720 | if (NULL == piMetabase) | ||
| 721 | { | ||
| 722 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase)); | ||
| 723 | MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object"); | ||
| 724 | } | ||
| 725 | |||
| 726 | if (NULL == pCatalog) | ||
| 727 | { | ||
| 728 | hr = CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pCatalog); | ||
| 729 | MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_ICOMAdmin object"); | ||
| 730 | |||
| 731 | hr = pCatalog->GetCollection(bstrApplications, reinterpret_cast<IDispatch**>(&pApplicationCollection)); | ||
| 732 | if (FAILED(hr)) | ||
| 733 | { | ||
| 734 | hr = S_OK; | ||
| 735 | WcaLog(LOGMSG_STANDARD, "error 0x%x: failed to get ApplicationCollection object for list of COM+ applications - COM+ applications will not be able to be uninstalled - continuing", hr); | ||
| 736 | } | ||
| 737 | } | ||
| 738 | |||
| 739 | if (NULL == piWam) | ||
| 740 | { | ||
| 741 | hr = ::CoCreateInstance(CLSID_WamAdmin, NULL, CLSCTX_ALL, IID_IWamAdmin, reinterpret_cast<void**>(&piWam)); | ||
| 742 | MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IWamAdmin object"); | ||
| 743 | } | ||
| 744 | |||
| 745 | hr = DeleteAspApp(&pwz, piMetabase, pApplicationCollection, piWam); | ||
| 746 | ExitOnFailure(hr, "failed to delete ASP App"); | ||
| 747 | break; | ||
| 748 | case MBA_CREATEKEY: | ||
| 749 | if (NULL == piMetabase) | ||
| 750 | { | ||
| 751 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase)); | ||
| 752 | MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object"); | ||
| 753 | } | ||
| 754 | |||
| 755 | hr = CreateMetabaseKey(&pwz, piMetabase); | ||
| 756 | ExitOnFailure(hr, "failed to create metabase key"); | ||
| 757 | break; | ||
| 758 | case MBA_DELETEKEY: | ||
| 759 | if (NULL == piMetabase) | ||
| 760 | { | ||
| 761 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase)); | ||
| 762 | MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object"); | ||
| 763 | } | ||
| 764 | |||
| 765 | hr = DeleteMetabaseKey(&pwz, piMetabase); | ||
| 766 | ExitOnFailure(hr, "failed to delete metabase key"); | ||
| 767 | break; | ||
| 768 | case MBA_WRITEVALUE: | ||
| 769 | if (NULL == piMetabase) | ||
| 770 | { | ||
| 771 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase)); | ||
| 772 | MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object"); | ||
| 773 | } | ||
| 774 | |||
| 775 | hr = WriteMetabaseValue(&pwz, piMetabase); | ||
| 776 | ExitOnFailure(hr, "failed to write metabase value"); | ||
| 777 | break; | ||
| 778 | case MBA_DELETEVALUE: | ||
| 779 | if (NULL == piMetabase) | ||
| 780 | { | ||
| 781 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase)); | ||
| 782 | MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object"); | ||
| 783 | } | ||
| 784 | |||
| 785 | hr = DeleteMetabaseValue(&pwz, piMetabase); | ||
| 786 | ExitOnFailure(hr, "failed to delete metabase value"); | ||
| 787 | break; | ||
| 788 | default: | ||
| 789 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected metabase action specified: %d", maAction); | ||
| 790 | break; | ||
| 791 | } | ||
| 792 | } | ||
| 793 | if (E_NOMOREITEMS == hr) // If there are no more items, all is well | ||
| 794 | { | ||
| 795 | if (NULL != piMetabase) | ||
| 796 | { | ||
| 797 | hr = piMetabase->SaveData(); | ||
| 798 | for (int i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--) | ||
| 799 | { | ||
| 800 | ::Sleep(1000); | ||
| 801 | WcaLog(LOGMSG_VERBOSE, "Failed to force save of metabase data, retrying %d time(s)...", i); | ||
| 802 | hr = piMetabase->SaveData(); | ||
| 803 | } | ||
| 804 | if (FAILED(hr)) | ||
| 805 | { | ||
| 806 | WcaLog(LOGMSG_VERBOSE, "Failed to force save of metabase data: 0x%x - continuing", hr); | ||
| 807 | } | ||
| 808 | hr = S_OK; | ||
| 809 | } | ||
| 810 | else | ||
| 811 | { | ||
| 812 | hr = S_OK; | ||
| 813 | } | ||
| 814 | } | ||
| 815 | |||
| 816 | LExit: | ||
| 817 | WcaCaScriptClose(hWriteMetabaseScript, WCA_CASCRIPT_CLOSE_DELETE); | ||
| 818 | |||
| 819 | ReleaseBSTR(bstrApplications); | ||
| 820 | ReleaseStr(pwzScriptKey); | ||
| 821 | ReleaseStr(pwzData); | ||
| 822 | ReleaseObject(piMetabase); | ||
| 823 | ReleaseObject(piWam); | ||
| 824 | ReleaseObject(pCatalog); | ||
| 825 | ReleaseObject(pApplicationCollection); | ||
| 826 | |||
| 827 | if (fInitializedCom) | ||
| 828 | { | ||
| 829 | ::CoUninitialize(); | ||
| 830 | } | ||
| 831 | |||
| 832 | if (FAILED(hr)) | ||
| 833 | { | ||
| 834 | er = ERROR_INSTALL_FAILURE; | ||
| 835 | } | ||
| 836 | return WcaFinalize(er); | ||
| 837 | } | ||
| 838 | /******************************************************************** | ||
| 839 | WriteIIS7ConfigChanges - CUSTOM ACTION ENTRY POINT for IIS7 config changes | ||
| 840 | |||
| 841 | *******************************************************************/ | ||
| 842 | extern "C" UINT __stdcall WriteIIS7ConfigChanges(MSIHANDLE hInstall) | ||
| 843 | { | ||
| 844 | //AssertSz(FALSE, "debug WriteIIS7ConfigChanges here"); | ||
| 845 | HRESULT hr = S_OK; | ||
| 846 | UINT er = ERROR_SUCCESS; | ||
| 847 | LPWSTR pwzData = NULL; | ||
| 848 | LPWSTR pwzScriptKey = NULL; | ||
| 849 | LPWSTR pwzHashString = NULL; | ||
| 850 | BYTE rgbActualHash[SHA1_HASH_LEN] = { }; | ||
| 851 | DWORD dwHashedBytes = SHA1_HASH_LEN; | ||
| 852 | |||
| 853 | WCA_CASCRIPT_HANDLE hWriteIis7Script = NULL; | ||
| 854 | |||
| 855 | hr = WcaInitialize(hInstall, "WriteIIS7ConfigChanges"); | ||
| 856 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 857 | |||
| 858 | hr = WcaGetProperty( L"CustomActionData", &pwzScriptKey); | ||
| 859 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
| 860 | WcaLog(LOGMSG_TRACEONLY, "Script WriteIIS7ConfigChanges: %ls", pwzScriptKey); | ||
| 861 | |||
| 862 | hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzScriptKey, &hWriteIis7Script); | ||
| 863 | ExitOnFailure(hr, "Failed to open CaScript file"); | ||
| 864 | |||
| 865 | hr = WcaCaScriptReadAsCustomActionData(hWriteIis7Script, &pwzData); | ||
| 866 | ExitOnFailure(hr, "Failed to read script into CustomAction data."); | ||
| 867 | |||
| 868 | hr = CrypHashBuffer((BYTE*)pwzData, sizeof(pwzData) * sizeof(WCHAR), PROV_RSA_AES, CALG_SHA1, rgbActualHash, dwHashedBytes); | ||
| 869 | ExitOnFailure(hr, "Failed to calculate hash of CustomAction data."); | ||
| 870 | |||
| 871 | hr = StrAlloc(&pwzHashString, ((dwHashedBytes * 2) + 1)); | ||
| 872 | ExitOnFailure(hr, "Failed to allocate string for script hash"); | ||
| 873 | |||
| 874 | hr = StrHexEncode(rgbActualHash, dwHashedBytes, pwzHashString, ((dwHashedBytes * 2) + 1)); | ||
| 875 | ExitOnFailure(hr, "Failed to convert hash bytes to string."); | ||
| 876 | |||
| 877 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData WriteIIS7ConfigChanges: %ls", pwzData); | ||
| 878 | WcaLog(LOGMSG_VERBOSE, "Custom action data hash: %ls", pwzHashString); | ||
| 879 | WcaLog(LOGMSG_VERBOSE, "CustomActionData WriteIIS7ConfigChanges length: %d", wcslen(pwzData)); | ||
| 880 | |||
| 881 | hr = IIS7ConfigChanges(hInstall, pwzData); | ||
| 882 | ExitOnFailure(hr, "WriteIIS7ConfigChanges Failed."); | ||
| 883 | |||
| 884 | LExit: | ||
| 885 | WcaCaScriptClose(hWriteIis7Script, WCA_CASCRIPT_CLOSE_DELETE); | ||
| 886 | ReleaseStr(pwzScriptKey); | ||
| 887 | ReleaseStr(pwzData); | ||
| 888 | ReleaseStr(pwzHashString); | ||
| 889 | |||
| 890 | if (FAILED(hr)) | ||
| 891 | { | ||
| 892 | er = ERROR_INSTALL_FAILURE; | ||
| 893 | } | ||
| 894 | |||
| 895 | return WcaFinalize(er); | ||
| 896 | } | ||
| 897 | |||
| 898 | |||
| 899 | /******************************************************************** | ||
| 900 | CommitIIS7ConfigTransaction - CUSTOM ACTION ENTRY POINT for unbacking up config | ||
| 901 | |||
| 902 | Input: deferred CustomActionData - BackupName | ||
| 903 | * *****************************************************************/ | ||
| 904 | extern "C" UINT __stdcall CommitIIS7ConfigTransaction(MSIHANDLE hInstall) | ||
| 905 | { | ||
| 906 | HRESULT hr = S_OK; | ||
| 907 | UINT er = ERROR_SUCCESS; | ||
| 908 | LPWSTR pwzData = NULL; | ||
| 909 | WCHAR wzConfigCopy[MAX_PATH]; | ||
| 910 | DWORD dwSize = 0; | ||
| 911 | |||
| 912 | BOOL fIsWow64Process = FALSE; | ||
| 913 | BOOL fIsFSRedirectDisabled = FALSE; | ||
| 914 | |||
| 915 | hr = WcaInitialize(hInstall, "CommitIIS7ConfigTransaction"); | ||
| 916 | ExitOnFailure(hr, "failed to initialize IIS7 commit transaction"); | ||
| 917 | |||
| 918 | WcaInitializeWow64(); | ||
| 919 | fIsWow64Process = WcaIsWow64Process(); | ||
| 920 | if (fIsWow64Process) | ||
| 921 | { | ||
| 922 | hr = WcaDisableWow64FSRedirection(); | ||
| 923 | if(FAILED(hr)) | ||
| 924 | { | ||
| 925 | //eat this error | ||
| 926 | hr = S_OK; | ||
| 927 | } | ||
| 928 | else | ||
| 929 | { | ||
| 930 | fIsFSRedirectDisabled = TRUE; | ||
| 931 | } | ||
| 932 | } | ||
| 933 | |||
| 934 | hr = WcaGetProperty( L"CustomActionData", &pwzData); | ||
| 935 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 936 | |||
| 937 | // Config AdminMgr changes already committed, just | ||
| 938 | // delete backup config file. | ||
| 939 | |||
| 940 | dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config", | ||
| 941 | wzConfigCopy, | ||
| 942 | MAX_PATH | ||
| 943 | ); | ||
| 944 | if ( dwSize == 0 ) | ||
| 945 | { | ||
| 946 | ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); | ||
| 947 | } | ||
| 948 | |||
| 949 | hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, L"."); | ||
| 950 | ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of ."); | ||
| 951 | |||
| 952 | hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, pwzData); | ||
| 953 | ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of extension"); | ||
| 954 | |||
| 955 | if (!::DeleteFileW(wzConfigCopy)) | ||
| 956 | { | ||
| 957 | hr = HRESULT_FROM_WIN32(GetLastError()); | ||
| 958 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || | ||
| 959 | HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
| 960 | { | ||
| 961 | WcaLog(LOGMSG_STANDARD, "Failed to delete backup applicationHost, not found - continuing"); | ||
| 962 | hr = S_OK; | ||
| 963 | } | ||
| 964 | else | ||
| 965 | { | ||
| 966 | ExitOnFailure(hr, "failed to delete config backup"); | ||
| 967 | } | ||
| 968 | } | ||
| 969 | |||
| 970 | LExit: | ||
| 971 | ReleaseStr(pwzData); | ||
| 972 | |||
| 973 | // Make sure we revert FS Redirection if necessary before exiting | ||
| 974 | if (fIsFSRedirectDisabled) | ||
| 975 | { | ||
| 976 | fIsFSRedirectDisabled = FALSE; | ||
| 977 | WcaRevertWow64FSRedirection(); | ||
| 978 | } | ||
| 979 | WcaFinalizeWow64(); | ||
| 980 | |||
| 981 | |||
| 982 | if (FAILED(hr)) | ||
| 983 | { | ||
| 984 | er = ERROR_INSTALL_FAILURE; | ||
| 985 | } | ||
| 986 | return WcaFinalize(er); | ||
| 987 | } | ||
| 988 | /******************************************************************** | ||
| 989 | StartIIS7Config Transaction - CUSTOM ACTION ENTRY POINT for backing up config | ||
| 990 | |||
| 991 | Input: deferred CustomActionData - BackupName | ||
| 992 | ********************************************************************/ | ||
| 993 | extern "C" UINT __stdcall StartIIS7ConfigTransaction(MSIHANDLE hInstall) | ||
| 994 | { | ||
| 995 | HRESULT hr = S_OK; | ||
| 996 | UINT er = ERROR_SUCCESS; | ||
| 997 | LPWSTR pwzData = NULL; | ||
| 998 | WCHAR wzConfigSource[MAX_PATH]; | ||
| 999 | WCHAR wzConfigCopy[MAX_PATH]; | ||
| 1000 | DWORD dwSize = 0; | ||
| 1001 | |||
| 1002 | |||
| 1003 | BOOL fIsWow64Process = FALSE; | ||
| 1004 | BOOL fIsFSRedirectDisabled = FALSE; | ||
| 1005 | |||
| 1006 | // initialize | ||
| 1007 | hr = WcaInitialize(hInstall, "StartIIS7ConfigTransaction"); | ||
| 1008 | ExitOnFailure(hr, "failed to initialize StartIIS7ConfigTransaction"); | ||
| 1009 | |||
| 1010 | WcaInitializeWow64(); | ||
| 1011 | fIsWow64Process = WcaIsWow64Process(); | ||
| 1012 | if (fIsWow64Process) | ||
| 1013 | { | ||
| 1014 | hr = WcaDisableWow64FSRedirection(); | ||
| 1015 | if(FAILED(hr)) | ||
| 1016 | { | ||
| 1017 | //eat this error | ||
| 1018 | hr = S_OK; | ||
| 1019 | } | ||
| 1020 | else | ||
| 1021 | { | ||
| 1022 | fIsFSRedirectDisabled = TRUE; | ||
| 1023 | } | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | hr = WcaGetProperty(L"CustomActionData", &pwzData); | ||
| 1027 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 1028 | |||
| 1029 | |||
| 1030 | dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config", | ||
| 1031 | wzConfigSource, | ||
| 1032 | MAX_PATH | ||
| 1033 | ); | ||
| 1034 | if ( dwSize == 0 ) | ||
| 1035 | { | ||
| 1036 | ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); | ||
| 1037 | } | ||
| 1038 | hr = ::StringCchCopyW(wzConfigCopy, MAX_PATH, wzConfigSource); | ||
| 1039 | ExitOnFailure(hr, "Commit IIS7 failed StringCchCopyW"); | ||
| 1040 | |||
| 1041 | //add ca action as extension | ||
| 1042 | |||
| 1043 | hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, L"."); | ||
| 1044 | ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of ."); | ||
| 1045 | |||
| 1046 | hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, pwzData); | ||
| 1047 | ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of extension"); | ||
| 1048 | |||
| 1049 | if ( !::CopyFileW(wzConfigSource, wzConfigCopy, FALSE) ) | ||
| 1050 | { | ||
| 1051 | hr = HRESULT_FROM_WIN32(GetLastError()); | ||
| 1052 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || | ||
| 1053 | HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
| 1054 | { | ||
| 1055 | // IIS may not be installed on the machine, we'll fail later if we try to install anything | ||
| 1056 | WcaLog(LOGMSG_STANDARD, "Failed to back up applicationHost, not found - continuing"); | ||
| 1057 | hr = S_OK; | ||
| 1058 | } | ||
| 1059 | else | ||
| 1060 | { | ||
| 1061 | ExitOnFailure(hr, "Failed to copy config backup %ls -> %ls", wzConfigSource, wzConfigCopy); | ||
| 1062 | } | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | |||
| 1066 | hr = WcaProgressMessage(COST_IIS_TRANSACTIONS, FALSE); | ||
| 1067 | |||
| 1068 | |||
| 1069 | LExit: | ||
| 1070 | |||
| 1071 | ReleaseStr(pwzData); | ||
| 1072 | |||
| 1073 | // Make sure we revert FS Redirection if necessary before exiting | ||
| 1074 | if (fIsFSRedirectDisabled) | ||
| 1075 | { | ||
| 1076 | fIsFSRedirectDisabled = FALSE; | ||
| 1077 | WcaRevertWow64FSRedirection(); | ||
| 1078 | } | ||
| 1079 | WcaFinalizeWow64(); | ||
| 1080 | |||
| 1081 | if (FAILED(hr)) | ||
| 1082 | er = ERROR_INSTALL_FAILURE; | ||
| 1083 | return WcaFinalize(er); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | |||
| 1087 | /******************************************************************** | ||
| 1088 | RollbackIIS7ConfigTransaction - CUSTOM ACTION ENTRY POINT for unbacking up config | ||
| 1089 | |||
| 1090 | Input: deferred CustomActionData - BackupName | ||
| 1091 | ********************************************************************/ | ||
| 1092 | extern "C" UINT __stdcall RollbackIIS7ConfigTransaction(MSIHANDLE hInstall) | ||
| 1093 | { | ||
| 1094 | HRESULT hr = S_OK; | ||
| 1095 | UINT er = ERROR_SUCCESS; | ||
| 1096 | LPWSTR pwzData = NULL; | ||
| 1097 | WCHAR wzConfigSource[MAX_PATH]; | ||
| 1098 | WCHAR wzConfigCopy[MAX_PATH]; | ||
| 1099 | DWORD dwSize = 0; | ||
| 1100 | |||
| 1101 | BOOL fIsWow64Process = FALSE; | ||
| 1102 | BOOL fIsFSRedirectDisabled = FALSE; | ||
| 1103 | |||
| 1104 | hr = WcaInitialize(hInstall, "RollbackIIS7ConfigTransaction"); | ||
| 1105 | ExitOnFailure(hr, "failed to initialize"); | ||
| 1106 | |||
| 1107 | WcaInitializeWow64(); | ||
| 1108 | fIsWow64Process = WcaIsWow64Process(); | ||
| 1109 | if (fIsWow64Process) | ||
| 1110 | { | ||
| 1111 | hr = WcaDisableWow64FSRedirection(); | ||
| 1112 | if(FAILED(hr)) | ||
| 1113 | { | ||
| 1114 | //eat this error | ||
| 1115 | hr = S_OK; | ||
| 1116 | } | ||
| 1117 | else | ||
| 1118 | { | ||
| 1119 | fIsFSRedirectDisabled = TRUE; | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | hr = WcaGetProperty( L"CustomActionData", &pwzData); | ||
| 1124 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 1125 | |||
| 1126 | dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config", | ||
| 1127 | wzConfigSource, | ||
| 1128 | MAX_PATH | ||
| 1129 | ); | ||
| 1130 | if ( dwSize == 0 ) | ||
| 1131 | { | ||
| 1132 | ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); | ||
| 1133 | } | ||
| 1134 | hr = ::StringCchCopyW(wzConfigCopy, MAX_PATH, wzConfigSource); | ||
| 1135 | ExitOnFailure(hr, "Commit IIS7 failed StringCchCopyW"); | ||
| 1136 | |||
| 1137 | //add ca action as extension | ||
| 1138 | |||
| 1139 | hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, L"."); | ||
| 1140 | ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of ."); | ||
| 1141 | |||
| 1142 | hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, pwzData); | ||
| 1143 | ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of extension"); | ||
| 1144 | |||
| 1145 | //copy is reverse of start transaction | ||
| 1146 | if (!::CopyFileW(wzConfigCopy, wzConfigSource, FALSE)) | ||
| 1147 | { | ||
| 1148 | hr = HRESULT_FROM_WIN32(GetLastError()); | ||
| 1149 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || | ||
| 1150 | HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
| 1151 | { | ||
| 1152 | WcaLog(LOGMSG_STANDARD, "Failed to restore applicationHost, not found - continuing"); | ||
| 1153 | hr = S_OK; | ||
| 1154 | } | ||
| 1155 | else | ||
| 1156 | { | ||
| 1157 | ExitOnFailure(hr, "failed to restore config backup"); | ||
| 1158 | } | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | if (!::DeleteFileW(wzConfigCopy)) | ||
| 1162 | { | ||
| 1163 | ExitWithLastError(hr, "failed to delete config backup"); | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | hr = WcaProgressMessage(COST_IIS_TRANSACTIONS, FALSE); | ||
| 1167 | |||
| 1168 | LExit: | ||
| 1169 | ReleaseStr(pwzData); | ||
| 1170 | |||
| 1171 | // Make sure we revert FS Redirection if necessary before exiting | ||
| 1172 | if (fIsFSRedirectDisabled) | ||
| 1173 | { | ||
| 1174 | fIsFSRedirectDisabled = FALSE; | ||
| 1175 | WcaRevertWow64FSRedirection(); | ||
| 1176 | } | ||
| 1177 | WcaFinalizeWow64(); | ||
| 1178 | |||
| 1179 | if (FAILED(hr)) | ||
| 1180 | { | ||
| 1181 | er = ERROR_INSTALL_FAILURE; | ||
| 1182 | } | ||
| 1183 | return WcaFinalize(er); | ||
| 1184 | } | ||
diff --git a/src/ext/Iis/ca/scaexecIIS7.cpp b/src/ext/Iis/ca/scaexecIIS7.cpp new file mode 100644 index 00000000..108007a1 --- /dev/null +++ b/src/ext/Iis/ca/scaexecIIS7.cpp | |||
| @@ -0,0 +1,4205 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "precomp.h" | ||
| 6 | |||
| 7 | //local CAData action functions | ||
| 8 | HRESULT IIS7Site( | ||
| 9 | __inout LPWSTR *ppwzCustomActionData, | ||
| 10 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 11 | ); | ||
| 12 | |||
| 13 | HRESULT IIS7Application( | ||
| 14 | __inout LPWSTR *ppwzCustomActionData, | ||
| 15 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 16 | ); | ||
| 17 | HRESULT IIS7VDir( | ||
| 18 | __inout LPWSTR *ppwzCustomActionData, | ||
| 19 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 20 | ); | ||
| 21 | HRESULT IIS7Binding( | ||
| 22 | __inout LPWSTR *ppwzCustomActionData, | ||
| 23 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 24 | ); | ||
| 25 | HRESULT IIS7AppPool( | ||
| 26 | __inout LPWSTR *ppwzCustomActionData, | ||
| 27 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 28 | ); | ||
| 29 | HRESULT IIS7AppExtension( | ||
| 30 | __inout LPWSTR *ppwzCustomActionData, | ||
| 31 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 32 | ); | ||
| 33 | HRESULT IIS7MimeMap( | ||
| 34 | __inout LPWSTR *ppwzCustomActionData, | ||
| 35 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 36 | ); | ||
| 37 | HRESULT IIS7DirProperties( | ||
| 38 | __inout LPWSTR *ppwzCustomActionData, | ||
| 39 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 40 | ); | ||
| 41 | HRESULT IIS7WebLog( | ||
| 42 | __inout LPWSTR *ppwzCustomActionData, | ||
| 43 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 44 | ); | ||
| 45 | HRESULT IIS7FilterGlobal( | ||
| 46 | __inout LPWSTR *ppwzCustomActionData, | ||
| 47 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 48 | ); | ||
| 49 | HRESULT IIS7FilterSite( | ||
| 50 | __inout LPWSTR *ppwzCustomActionData, | ||
| 51 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 52 | ); | ||
| 53 | HRESULT IIS7HttpHeader( | ||
| 54 | __inout LPWSTR *ppwzCustomActionData, | ||
| 55 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 56 | ); | ||
| 57 | HRESULT IIS7WebError( | ||
| 58 | __inout LPWSTR *ppwzCustomActionData, | ||
| 59 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 60 | ); | ||
| 61 | HRESULT IIS7WebSvcExt( | ||
| 62 | __inout LPWSTR *ppwzCustomActionData, | ||
| 63 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 64 | ); | ||
| 65 | HRESULT IIS7WebProperty( | ||
| 66 | __inout LPWSTR *ppwzCustomActionData, | ||
| 67 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 68 | ); | ||
| 69 | HRESULT IIS7WebDir( | ||
| 70 | __inout LPWSTR *ppwzCustomActionData, | ||
| 71 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 72 | ); | ||
| 73 | HRESULT IIS7AspProperty( | ||
| 74 | __inout LPWSTR *ppwzCustomActionData, | ||
| 75 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 76 | ); | ||
| 77 | HRESULT IIS7SslBinding( | ||
| 78 | __inout LPWSTR *ppwzCustomActionData, | ||
| 79 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 80 | ); | ||
| 81 | //local helper functions | ||
| 82 | |||
| 83 | static HRESULT GetNextAvailableSiteId( | ||
| 84 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 85 | DWORD *plSiteId | ||
| 86 | ); | ||
| 87 | static HRESULT GetSiteElement( | ||
| 88 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 89 | LPCWSTR swSiteName, | ||
| 90 | IAppHostElement **pSiteElement, | ||
| 91 | BOOL* fFound | ||
| 92 | ); | ||
| 93 | static HRESULT GetApplicationElement( | ||
| 94 | IAppHostElement *pSiteElement, | ||
| 95 | LPCWSTR swAppPath, | ||
| 96 | IAppHostElement **pAppElement, | ||
| 97 | BOOL* fFound | ||
| 98 | ); | ||
| 99 | static HRESULT GetApplicationElementForVDir( | ||
| 100 | IAppHostElement *pSiteElement, | ||
| 101 | LPCWSTR swVDirPath, | ||
| 102 | IAppHostElement **ppAppElement, | ||
| 103 | LPCWSTR *ppwzVDirSubPath, | ||
| 104 | BOOL* fFound | ||
| 105 | ); | ||
| 106 | |||
| 107 | static HRESULT CreateApplication( | ||
| 108 | IAppHostElement *pSiteElement, | ||
| 109 | LPCWSTR swAppPath, | ||
| 110 | IAppHostElement **pAppElement | ||
| 111 | ); | ||
| 112 | static HRESULT DeleteApplication( | ||
| 113 | IAppHostElement *pSiteElement, | ||
| 114 | LPCWSTR swAppPath | ||
| 115 | ); | ||
| 116 | |||
| 117 | static HRESULT SetAppPool( | ||
| 118 | IAppHostElement *pAppElementpAppElement, | ||
| 119 | LPCWSTR pwzAppPool | ||
| 120 | ); | ||
| 121 | static HRESULT CreateVdir( | ||
| 122 | IAppHostElement *pAppElement, | ||
| 123 | LPCWSTR pwzVDirPath, | ||
| 124 | LPCWSTR pwzVDirPhyDir | ||
| 125 | ); | ||
| 126 | static HRESULT DeleteVdir( | ||
| 127 | IAppHostElement *pAppElement, | ||
| 128 | LPCWSTR pwzVDirPath | ||
| 129 | ); | ||
| 130 | |||
| 131 | static HRESULT CreateBinding( | ||
| 132 | IAppHostElement *pSiteElem, | ||
| 133 | LPCWSTR pwzProtocol, | ||
| 134 | LPCWSTR pwzInfo | ||
| 135 | ); | ||
| 136 | static HRESULT DeleteBinding( | ||
| 137 | IAppHostElement *pSiteElem, | ||
| 138 | LPCWSTR pwzProtocol, | ||
| 139 | LPCWSTR pwzInfo | ||
| 140 | ); | ||
| 141 | |||
| 142 | static HRESULT CreateSslBinding( | ||
| 143 | IAppHostElement *pSiteElem, | ||
| 144 | LPCWSTR pwzStoreName, | ||
| 145 | LPCWSTR pwzEncodedCertificateHash | ||
| 146 | ); | ||
| 147 | static HRESULT DeleteSslBinding( | ||
| 148 | IAppHostElement *pSiteElem, | ||
| 149 | LPCWSTR pwzStoreName, | ||
| 150 | LPCWSTR pwzEncodedCertificateHash | ||
| 151 | ); | ||
| 152 | |||
| 153 | static HRESULT CreateSite( | ||
| 154 | IAppHostElementCollection *pAdminMgr, | ||
| 155 | LPCWSTR swSiteName, | ||
| 156 | IAppHostElement **pSiteElement | ||
| 157 | ); | ||
| 158 | |||
| 159 | static HRESULT DeleteAppPool( | ||
| 160 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 161 | LPCWSTR swAppPoolName | ||
| 162 | ); | ||
| 163 | static HRESULT CreateAppPool( | ||
| 164 | __inout LPWSTR *ppwzCustomActionData, | ||
| 165 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 166 | LPCWSTR swAppPoolName | ||
| 167 | ); | ||
| 168 | |||
| 169 | static HRESULT SetDirPropAuthentications( | ||
| 170 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 171 | LPCWSTR wcConfigPath, | ||
| 172 | DWORD dwData | ||
| 173 | ); | ||
| 174 | static HRESULT SetDirPropAuthProvider( | ||
| 175 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 176 | LPCWSTR wszConfigPath, | ||
| 177 | __in LPWSTR wszData | ||
| 178 | ); | ||
| 179 | static HRESULT SetDirPropDefDoc( | ||
| 180 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 181 | LPCWSTR wszConfigPath, | ||
| 182 | __in LPWSTR wszData | ||
| 183 | ); | ||
| 184 | |||
| 185 | static HRESULT ClearLocationTag( | ||
| 186 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 187 | LPCWSTR swLocationPath | ||
| 188 | ); | ||
| 189 | |||
| 190 | static HRESULT CreateWebLog( | ||
| 191 | IAppHostElement *pSiteElem, | ||
| 192 | LPCWSTR pwzFormat | ||
| 193 | ); | ||
| 194 | |||
| 195 | static HRESULT CreateGlobalFilter( | ||
| 196 | __inout LPWSTR *ppwzCustomActionData, | ||
| 197 | IAppHostElement *pSection | ||
| 198 | ); | ||
| 199 | static HRESULT DeleteGlobalFilter( | ||
| 200 | __inout LPWSTR *ppwzCustomActionData, | ||
| 201 | IAppHostElement *pSection | ||
| 202 | ); | ||
| 203 | |||
| 204 | static HRESULT CreateSiteFilter( | ||
| 205 | __inout LPWSTR *ppwzCustomActionData, | ||
| 206 | IAppHostWritableAdminManager *pAdminMgr | ||
| 207 | ); | ||
| 208 | static HRESULT DeleteSiteFilter( | ||
| 209 | __inout LPWSTR *ppwzCustomActionData, | ||
| 210 | IAppHostWritableAdminManager *pAdminMgr | ||
| 211 | ); | ||
| 212 | |||
| 213 | static HRESULT DeleteCollectionElement( | ||
| 214 | __in IAppHostElementCollection *pCollection, | ||
| 215 | __in LPCWSTR pwzElementName, | ||
| 216 | __in LPCWSTR pwzAttributeName, | ||
| 217 | __in LPCWSTR pwzAttributeValue | ||
| 218 | ); | ||
| 219 | |||
| 220 | struct SCA_WEB_ERROR_SERVER | ||
| 221 | { | ||
| 222 | int iErrorCode; | ||
| 223 | int iSubCode; | ||
| 224 | WCHAR wzFile[MAX_PATH]; | ||
| 225 | WCHAR wzLangPath[MAX_PATH]; | ||
| 226 | int iResponseMode; | ||
| 227 | SCA_WEB_ERROR_SERVER *psweNext; | ||
| 228 | }; | ||
| 229 | static HRESULT AddWebErrorToList( | ||
| 230 | SCA_WEB_ERROR_SERVER** ppsweList | ||
| 231 | ); | ||
| 232 | static void ScaWebErrorFreeList7( | ||
| 233 | SCA_WEB_ERROR_SERVER *psweList | ||
| 234 | ); | ||
| 235 | static HRESULT PopulateHttpErrors( | ||
| 236 | IAppHostElement *pSection, | ||
| 237 | SCA_WEB_ERROR_SERVER **psweList | ||
| 238 | ); | ||
| 239 | static HRESULT GetErrorFromList( | ||
| 240 | const SCA_WEB_ERROR_SERVER & we, | ||
| 241 | SCA_WEB_ERROR_SERVER **ppsweList, | ||
| 242 | SCA_WEB_ERROR_SERVER **pswe, | ||
| 243 | BOOL *fFound | ||
| 244 | ); | ||
| 245 | |||
| 246 | static void ConvSecToHMS( | ||
| 247 | int Sec, | ||
| 248 | __out_ecount(cchDest) LPWSTR wcTime, | ||
| 249 | size_t cchDest | ||
| 250 | ); | ||
| 251 | static void ConvSecToDHMS( | ||
| 252 | unsigned int Sec, | ||
| 253 | __out_ecount(cchDest) LPWSTR wcTime, | ||
| 254 | size_t cchDest | ||
| 255 | ); | ||
| 256 | |||
| 257 | //////////////////////////////////////////////////////////////////// | ||
| 258 | // ScopeBSTR: Local helper class to construct & free BSTR from LPWSTR | ||
| 259 | // | ||
| 260 | ///////////////////////////////////////////////////////////////////// | ||
| 261 | class ScopeBSTR | ||
| 262 | { | ||
| 263 | public: | ||
| 264 | BSTR m_str; | ||
| 265 | |||
| 266 | ScopeBSTR() | ||
| 267 | { | ||
| 268 | m_str = NULL; | ||
| 269 | } | ||
| 270 | |||
| 271 | ScopeBSTR( __in LPCWSTR pSrc) | ||
| 272 | { | ||
| 273 | if (pSrc == NULL) | ||
| 274 | { | ||
| 275 | m_str = NULL; | ||
| 276 | } | ||
| 277 | else | ||
| 278 | { | ||
| 279 | m_str = ::SysAllocString(pSrc); | ||
| 280 | |||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | ~ScopeBSTR() | ||
| 285 | { | ||
| 286 | ::SysFreeString(m_str); | ||
| 287 | } | ||
| 288 | |||
| 289 | operator BSTR() | ||
| 290 | { | ||
| 291 | return m_str; | ||
| 292 | } | ||
| 293 | }; | ||
| 294 | |||
| 295 | |||
| 296 | /******************************************************************** | ||
| 297 | IIS7ConfigChanges - Start of IIS7 config changes | ||
| 298 | |||
| 299 | *******************************************************************/ | ||
| 300 | HRESULT IIS7ConfigChanges(MSIHANDLE /*hInstall*/, __inout LPWSTR pwzData) | ||
| 301 | { | ||
| 302 | HRESULT hr = S_OK; | ||
| 303 | BOOL fInitializedCom = FALSE; | ||
| 304 | |||
| 305 | IAppHostWritableAdminManager *pAdminMgr = NULL; | ||
| 306 | |||
| 307 | LPWSTR pwz = NULL; | ||
| 308 | LPWSTR pwzLast = NULL; | ||
| 309 | LPWSTR pwzBackup = NULL; | ||
| 310 | DWORD cchData = lstrlenW(pwzData); | ||
| 311 | int iAction = -1; | ||
| 312 | |||
| 313 | int iRetryCount = 0; | ||
| 314 | |||
| 315 | hr = ::CoInitialize(NULL); | ||
| 316 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
| 317 | fInitializedCom = TRUE; | ||
| 318 | |||
| 319 | pwz = pwzLast = pwzData; | ||
| 320 | |||
| 321 | hr = StrAllocString(&pwzBackup, pwz, 0); | ||
| 322 | ExitOnFailure(hr, "Failed to backup custom action data"); | ||
| 323 | |||
| 324 | while (S_OK == (hr = WcaReadIntegerFromCaData(&pwz, &iAction))) | ||
| 325 | { | ||
| 326 | if (NULL == pAdminMgr) | ||
| 327 | { | ||
| 328 | hr = ::CoCreateInstance( __uuidof(AppHostWritableAdminManager), | ||
| 329 | NULL, | ||
| 330 | CLSCTX_INPROC_SERVER, | ||
| 331 | __uuidof(IAppHostWritableAdminManager), | ||
| 332 | reinterpret_cast<void**> (&pAdminMgr)); | ||
| 333 | ExitOnFailure(hr , "Failed to open AppHostWritableAdminManager to configure IIS7"); | ||
| 334 | } | ||
| 335 | |||
| 336 | switch (iAction) | ||
| 337 | { | ||
| 338 | case IIS_SITE: | ||
| 339 | { | ||
| 340 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 341 | hr = IIS7Site(&pwz, pAdminMgr); | ||
| 342 | ExitOnFailure(hr, "Failed to configure IIS site."); | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | case IIS_APPLICATION: | ||
| 346 | { | ||
| 347 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 348 | hr = IIS7Application(&pwz, pAdminMgr); | ||
| 349 | ExitOnFailure(hr, "Failed to configure IIS application."); | ||
| 350 | break; | ||
| 351 | } | ||
| 352 | case IIS_VDIR: | ||
| 353 | { | ||
| 354 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 355 | hr = IIS7VDir(&pwz, pAdminMgr); | ||
| 356 | ExitOnFailure(hr, "Failed to configure IIS VDir."); | ||
| 357 | break; | ||
| 358 | } | ||
| 359 | case IIS_BINDING: | ||
| 360 | { | ||
| 361 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 362 | hr = IIS7Binding(&pwz, pAdminMgr); | ||
| 363 | ExitOnFailure(hr, "Failed to configure IIS site binding."); | ||
| 364 | break; | ||
| 365 | } | ||
| 366 | case IIS_APPPOOL: | ||
| 367 | { | ||
| 368 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 369 | hr = IIS7AppPool(&pwz, pAdminMgr); | ||
| 370 | ExitOnFailure(hr, "Failed to configure IIS appPool."); | ||
| 371 | break; | ||
| 372 | } | ||
| 373 | case IIS_APPEXT_BEGIN: | ||
| 374 | { | ||
| 375 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 376 | hr = IIS7AppExtension(&pwz, pAdminMgr); | ||
| 377 | ExitOnFailure(hr, "Failed to configure IIS AppExtension."); | ||
| 378 | break; | ||
| 379 | } | ||
| 380 | case IIS_MIMEMAP_BEGIN: | ||
| 381 | { | ||
| 382 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 383 | hr = IIS7MimeMap(&pwz, pAdminMgr); | ||
| 384 | ExitOnFailure(hr, "Failed to configure IIS MimeMap."); | ||
| 385 | break; | ||
| 386 | } | ||
| 387 | case IIS_DIRPROP_BEGIN: | ||
| 388 | { | ||
| 389 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 390 | hr = IIS7DirProperties(&pwz, pAdminMgr); | ||
| 391 | ExitOnFailure(hr, "Failed to configure IIS DirProperties."); | ||
| 392 | break; | ||
| 393 | } | ||
| 394 | case IIS_WEBLOG: | ||
| 395 | { | ||
| 396 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 397 | hr = IIS7WebLog(&pwz, pAdminMgr); | ||
| 398 | ExitOnFailure(hr, "Failed to configure IIS WebLog."); | ||
| 399 | break; | ||
| 400 | } | ||
| 401 | case IIS_FILTER_GLOBAL_BEGIN: | ||
| 402 | { | ||
| 403 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 404 | hr = IIS7FilterGlobal(&pwz, pAdminMgr); | ||
| 405 | ExitOnFailure(hr, "Failed to configure IIS filter global."); | ||
| 406 | break; | ||
| 407 | } | ||
| 408 | case IIS_FILTER_BEGIN: | ||
| 409 | { | ||
| 410 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 411 | hr = IIS7FilterSite(&pwz, pAdminMgr); | ||
| 412 | ExitOnFailure(hr, "Failed to configure IIS Filter."); | ||
| 413 | break; | ||
| 414 | } | ||
| 415 | case IIS_HTTP_HEADER_BEGIN: | ||
| 416 | { | ||
| 417 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 418 | hr = IIS7HttpHeader(&pwz, pAdminMgr); | ||
| 419 | ExitOnFailure(hr, "Failed to configure IIS http Header."); | ||
| 420 | break; | ||
| 421 | } | ||
| 422 | case IIS_WEBERROR_BEGIN: | ||
| 423 | { | ||
| 424 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 425 | hr = IIS7WebError(&pwz, pAdminMgr); | ||
| 426 | ExitOnFailure(hr, "Failed to configure IIS http Errors."); | ||
| 427 | break; | ||
| 428 | } | ||
| 429 | case IIS_WEB_SVC_EXT: | ||
| 430 | { | ||
| 431 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 432 | hr = IIS7WebSvcExt(&pwz, pAdminMgr); | ||
| 433 | ExitOnFailure(hr, "Failed to configure IIS web svc ext."); | ||
| 434 | break; | ||
| 435 | } | ||
| 436 | case IIS_PROPERTY: | ||
| 437 | { | ||
| 438 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 439 | hr = IIS7WebProperty(&pwz, pAdminMgr); | ||
| 440 | ExitOnFailure(hr, "Failed to configure IIS web property."); | ||
| 441 | break; | ||
| 442 | } | ||
| 443 | case IIS_WEBDIR: | ||
| 444 | { | ||
| 445 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 446 | hr = IIS7WebDir(&pwz, pAdminMgr); | ||
| 447 | ExitOnFailure(hr, "Failed to configure IIS web directory."); | ||
| 448 | break; | ||
| 449 | } | ||
| 450 | case IIS_ASP_BEGIN: | ||
| 451 | { | ||
| 452 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 453 | hr = IIS7AspProperty(&pwz, pAdminMgr); | ||
| 454 | ExitOnFailure(hr, "Failed to configure IIS Asp property."); | ||
| 455 | break; | ||
| 456 | } | ||
| 457 | case IIS_SSL_BINDING: | ||
| 458 | #pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated") | ||
| 459 | hr = IIS7SslBinding(&pwz, pAdminMgr); | ||
| 460 | ExitOnFailure(hr, "Failed to configure IIS SSL binding."); | ||
| 461 | break; | ||
| 462 | |||
| 463 | default: | ||
| 464 | ExitOnFailure(hr = E_UNEXPECTED, "IIS7ConfigChanges: Unexpected IIS Config action specified: %d", iAction); | ||
| 465 | break; | ||
| 466 | } | ||
| 467 | if (S_OK == hr) | ||
| 468 | { | ||
| 469 | // commit config changes now to close out IIS Admin changes, | ||
| 470 | // the Rollback or Commit defered CAs will determine final commit status. | ||
| 471 | hr = pAdminMgr->CommitChanges(); | ||
| 472 | |||
| 473 | // Our transaction may have been interrupted. | ||
| 474 | if (hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) || hr == HRESULT_FROM_WIN32(ERROR_TRANSACTIONAL_CONFLICT)) | ||
| 475 | { | ||
| 476 | WcaLog(LOGMSG_VERBOSE, "Sharing violation or transactional conflict during attempt to save changes to applicationHost.config"); | ||
| 477 | if (++iRetryCount > 30) | ||
| 478 | { | ||
| 479 | if (IDRETRY == WcaErrorMessage(msierrIISFailedCommitInUse, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0)) | ||
| 480 | { | ||
| 481 | iRetryCount = 0; | ||
| 482 | } | ||
| 483 | else | ||
| 484 | { | ||
| 485 | ExitOnFailure(hr, "Failed to Commit IIS Config Changes, in silent mode or user has chosen to cancel"); | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | // Throw away the changes since IIS has no way to remove uncommited changes from an AdminManager. | ||
| 490 | ReleaseNullObject(pAdminMgr); | ||
| 491 | |||
| 492 | // Restore our CA data backup | ||
| 493 | pwz = pwzLast; | ||
| 494 | hr = ::StringCchCopyW(pwz, cchData - (pwz - pwzData) + 1, pwzBackup); | ||
| 495 | ExitOnFailure(hr , "Failed to restore custom action data backup"); | ||
| 496 | |||
| 497 | } | ||
| 498 | else if (FAILED(hr)) | ||
| 499 | { | ||
| 500 | ExitOnFailure(hr , "Failed to Commit IIS Config Changes"); | ||
| 501 | } | ||
| 502 | else | ||
| 503 | { | ||
| 504 | // store a backup of CA data @ the last place that we successfully commited changes unless we are done. | ||
| 505 | if(NULL != pwz) | ||
| 506 | { | ||
| 507 | pwzLast = pwz; | ||
| 508 | hr = StrAllocString(&pwzBackup, pwz, 0); | ||
| 509 | ExitOnFailure(hr, "Failed to backup custom action data"); | ||
| 510 | } | ||
| 511 | } | ||
| 512 | } | ||
| 513 | } | ||
| 514 | if (E_NOMOREITEMS == hr) // If there are no more items, all is well | ||
| 515 | { | ||
| 516 | hr = S_OK; | ||
| 517 | } | ||
| 518 | LExit: | ||
| 519 | ReleaseObject(pAdminMgr); | ||
| 520 | ReleaseStr(pwzBackup); | ||
| 521 | |||
| 522 | if (fInitializedCom) | ||
| 523 | { | ||
| 524 | ::CoUninitialize(); | ||
| 525 | } | ||
| 526 | |||
| 527 | return hr; | ||
| 528 | } | ||
| 529 | //------------------------------------------------------------------------------------------------- | ||
| 530 | // IIS7AspProperty | ||
| 531 | // Called by WriteIIS7ConfigChanges | ||
| 532 | // Processes asp properties for WebApplication | ||
| 533 | // | ||
| 534 | //------------------------------------------------------------------------------------------------- | ||
| 535 | |||
| 536 | HRESULT IIS7AspProperty( | ||
| 537 | __inout LPWSTR *ppwzCustomActionData, | ||
| 538 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 539 | ) | ||
| 540 | { | ||
| 541 | HRESULT hr = S_OK; | ||
| 542 | |||
| 543 | int iAction = -1; | ||
| 544 | int iData = 0; | ||
| 545 | |||
| 546 | LPWSTR pwzData = NULL; | ||
| 547 | LPWSTR pwzSiteName = NULL; | ||
| 548 | LPWSTR pwzPathName = NULL; | ||
| 549 | LPWSTR pwzLocationPath = NULL; | ||
| 550 | WCHAR wcTime[60]; | ||
| 551 | |||
| 552 | IAppHostElement *pSection = NULL; | ||
| 553 | IAppHostElement *pElement = NULL; | ||
| 554 | |||
| 555 | //read web site key | ||
| 556 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 557 | ExitOnFailure(hr, "Failed read webDir webkey"); | ||
| 558 | |||
| 559 | //read path key | ||
| 560 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzPathName); | ||
| 561 | ExitOnFailure(hr, "Failed read webDir path"); | ||
| 562 | |||
| 563 | //Construct Location path | ||
| 564 | hr = StrAllocFormatted(&pwzLocationPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName); | ||
| 565 | ExitOnFailure(hr, "failed to format webDir location"); | ||
| 566 | // | ||
| 567 | //Do not append trailing '/' for default vDir | ||
| 568 | // | ||
| 569 | if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzPathName, -1, L"/", -1)) | ||
| 570 | { | ||
| 571 | hr = StrAllocConcat(&pwzLocationPath, L"/", 0); | ||
| 572 | ExitOnFailure(hr, "failed to copy location WebDir '/'"); | ||
| 573 | hr = StrAllocConcat(&pwzLocationPath, pwzPathName, 0); | ||
| 574 | ExitOnFailure(hr, "failed to copy location WebDir path"); | ||
| 575 | } | ||
| 576 | |||
| 577 | //get asp section at config path location tag | ||
| 578 | hr = pAdminMgr->GetAdminSection( ScopeBSTR(IIS_CONFIG_ASP_SECTION), pwzLocationPath, &pSection); | ||
| 579 | ExitOnFailure(hr, "Failed get httpErrors section"); | ||
| 580 | |||
| 581 | // Get action | ||
| 582 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 583 | ExitOnFailure(hr, "Failed to read property action"); | ||
| 584 | |||
| 585 | while (IIS_ASP_END != iAction) | ||
| 586 | { | ||
| 587 | switch (iAction) | ||
| 588 | { | ||
| 589 | case IIS_ASP_SESSIONSTATE: | ||
| 590 | { | ||
| 591 | //system.webServer/asp /session | allowSessionState | ||
| 592 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 593 | ExitOnFailure(hr, "Failed to read asp session state"); | ||
| 594 | hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_SESSION), &pElement); | ||
| 595 | ExitOnFailure(hr, "Failed to get asp session element"); | ||
| 596 | hr = Iis7PutPropertyBool( pElement, IIS_CONFIG_ALLOWSTATE, iData); | ||
| 597 | ExitOnFailure(hr, "Failed to put asp session value"); | ||
| 598 | ReleaseNullObject(pElement); | ||
| 599 | break; | ||
| 600 | } | ||
| 601 | case IIS_ASP_SESSIONTIMEOUT: | ||
| 602 | { | ||
| 603 | //system.webServer/asp /session | timeout | ||
| 604 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 605 | ExitOnFailure(hr, "Failed to read asp session timeout"); | ||
| 606 | hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_SESSION), &pElement); | ||
| 607 | ExitOnFailure(hr, "Failed to get asp session timeout"); | ||
| 608 | *wcTime = '\0'; | ||
| 609 | ConvSecToHMS(iData * 60, wcTime, countof( wcTime)); | ||
| 610 | hr = Iis7PutPropertyString( pElement, IIS_CONFIG_TIMEOUT, wcTime); | ||
| 611 | ExitOnFailure(hr, "Failed to put asp timeout value"); | ||
| 612 | ReleaseNullObject(pElement); | ||
| 613 | break; | ||
| 614 | } | ||
| 615 | case IIS_ASP_BUFFER: | ||
| 616 | { | ||
| 617 | //system.webServer/asp | bufferingOn | ||
| 618 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 619 | ExitOnFailure(hr, "Failed to read asp bufferingOn"); | ||
| 620 | hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_BUFFERING, iData); | ||
| 621 | ExitOnFailure(hr, "Failed to put asp bufferingOn value"); | ||
| 622 | break; | ||
| 623 | } | ||
| 624 | case IIS_ASP_PARENTPATHS: | ||
| 625 | { | ||
| 626 | //system.webServer/asp | enableParentPaths | ||
| 627 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 628 | ExitOnFailure(hr, "Failed to read asp ParentPaths"); | ||
| 629 | hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_PARENTPATHS, iData); | ||
| 630 | ExitOnFailure(hr, "Failed to put asp ParentPaths value"); | ||
| 631 | break; | ||
| 632 | } | ||
| 633 | case IIS_ASP_SCRIPTLANG: | ||
| 634 | { | ||
| 635 | //system.webServer/asp | scriptLanguage | ||
| 636 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 637 | ExitOnFailure(hr, "Failed to read asp scriptLanguage"); | ||
| 638 | hr = Iis7PutPropertyString( pSection, IIS_CONFIG_SCRIPTLANG, pwzData); | ||
| 639 | ExitOnFailure(hr, "Failed to put asp scriptLanguage value"); | ||
| 640 | break; | ||
| 641 | } | ||
| 642 | case IIS_ASP_SCRIPTTIMEOUT: | ||
| 643 | { | ||
| 644 | //system.webServer/asp /limits | scriptTimeout | ||
| 645 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 646 | ExitOnFailure(hr, "Failed to read asp scriptTimeout"); | ||
| 647 | hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_LIMITS), &pElement); | ||
| 648 | ExitOnFailure(hr, "Failed to get asp session element"); | ||
| 649 | *wcTime = '\0'; | ||
| 650 | ConvSecToHMS(iData, wcTime, countof( wcTime)); | ||
| 651 | hr = Iis7PutPropertyString( pElement, IIS_CONFIG_SCRIPTTIMEOUT, wcTime); | ||
| 652 | ExitOnFailure(hr, "Failed to put asp scriptTimeout value"); | ||
| 653 | ReleaseNullObject(pElement); | ||
| 654 | break; | ||
| 655 | |||
| 656 | } | ||
| 657 | case IIS_ASP_SCRIPTSERVERDEBUG: | ||
| 658 | { | ||
| 659 | //system.webServer/asp | appAllowDebugging | ||
| 660 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 661 | ExitOnFailure(hr, "Failed to read asp appAllowDebugging"); | ||
| 662 | hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_ALLOWDEBUG, iData); | ||
| 663 | ExitOnFailure(hr, "Failed to put asp appAllowDebugging value"); | ||
| 664 | break; | ||
| 665 | } | ||
| 666 | case IIS_ASP_SCRIPTCLIENTDEBUG: | ||
| 667 | { | ||
| 668 | //system.webServer/asp | appAllowClientDebug | ||
| 669 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 670 | ExitOnFailure(hr, "Failed to read asp appAllowClientDebug"); | ||
| 671 | hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_ALLOWCLIENTDEBUG, iData); | ||
| 672 | ExitOnFailure(hr, "Failed to put asp appAllowClientDebug value"); | ||
| 673 | break; | ||
| 674 | } | ||
| 675 | default: | ||
| 676 | { | ||
| 677 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for asp properties"); | ||
| 678 | break; | ||
| 679 | } | ||
| 680 | } | ||
| 681 | // Get next action | ||
| 682 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 683 | ExitOnFailure(hr, "Failed to read asp prop action"); | ||
| 684 | } | ||
| 685 | |||
| 686 | LExit: | ||
| 687 | ReleaseStr(pwzData); | ||
| 688 | ReleaseStr(pwzSiteName); | ||
| 689 | ReleaseStr(pwzPathName); | ||
| 690 | ReleaseStr(pwzLocationPath); | ||
| 691 | ReleaseObject(pSection); | ||
| 692 | ReleaseObject(pElement); | ||
| 693 | |||
| 694 | return hr; | ||
| 695 | } | ||
| 696 | |||
| 697 | //------------------------------------------------------------------------------------------------- | ||
| 698 | // IIS7WebDir | ||
| 699 | // Called by WriteIIS7ConfigChanges | ||
| 700 | // Processes WebDir | ||
| 701 | // | ||
| 702 | //------------------------------------------------------------------------------------------------- | ||
| 703 | HRESULT IIS7WebDir( | ||
| 704 | __inout LPWSTR *ppwzCustomActionData, | ||
| 705 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 706 | ) | ||
| 707 | { | ||
| 708 | HRESULT hr = S_OK; | ||
| 709 | |||
| 710 | int iAction = -1; | ||
| 711 | |||
| 712 | LPWSTR pwzSiteName = NULL; | ||
| 713 | LPWSTR pwzPathName = NULL; | ||
| 714 | LPWSTR pwzLocationPath = NULL; | ||
| 715 | |||
| 716 | // Get action | ||
| 717 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 718 | ExitOnFailure(hr, "Failed to read property action"); | ||
| 719 | |||
| 720 | //read web site key | ||
| 721 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 722 | ExitOnFailure(hr, "Failed read webDir webkey"); | ||
| 723 | |||
| 724 | //read path key | ||
| 725 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzPathName); | ||
| 726 | ExitOnFailure(hr, "Failed read webDir path"); | ||
| 727 | |||
| 728 | switch (iAction) | ||
| 729 | { | ||
| 730 | case IIS_CREATE: | ||
| 731 | { | ||
| 732 | //no action needed for create since WebDir has a | ||
| 733 | //WebDirProperties element that will create and populate | ||
| 734 | //location tag | ||
| 735 | break; | ||
| 736 | } | ||
| 737 | case IIS_DELETE: | ||
| 738 | { | ||
| 739 | //Construct Location path | ||
| 740 | hr = StrAllocString(&pwzLocationPath, pwzSiteName, 0); | ||
| 741 | ExitOnFailure(hr, "failed to copy location WebDir web name"); | ||
| 742 | // | ||
| 743 | //Do not append trailing '/' for default vDir | ||
| 744 | // | ||
| 745 | if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzPathName, -1, L"/", -1)) | ||
| 746 | { | ||
| 747 | hr = StrAllocConcat(&pwzLocationPath, L"/", 0); | ||
| 748 | ExitOnFailure(hr, "failed to copy location WebDir '/'"); | ||
| 749 | hr = StrAllocConcat(&pwzLocationPath, pwzPathName, 0); | ||
| 750 | ExitOnFailure(hr, "failed to copy location WebDir path"); | ||
| 751 | } | ||
| 752 | // and delete location tag for this application | ||
| 753 | hr = ClearLocationTag(pAdminMgr, pwzLocationPath); | ||
| 754 | ExitOnFailure(hr, "failed to clear location tag for %ls", pwzLocationPath) | ||
| 755 | break; | ||
| 756 | } | ||
| 757 | default: | ||
| 758 | { | ||
| 759 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for WebDir"); | ||
| 760 | break; | ||
| 761 | } | ||
| 762 | } | ||
| 763 | LExit: | ||
| 764 | ReleaseStr(pwzSiteName); | ||
| 765 | ReleaseStr(pwzPathName); | ||
| 766 | ReleaseStr(pwzLocationPath); | ||
| 767 | |||
| 768 | return hr; | ||
| 769 | } | ||
| 770 | |||
| 771 | //------------------------------------------------------------------------------------------------- | ||
| 772 | // IIS7WebProperty | ||
| 773 | // Called by WriteIIS7ConfigChanges | ||
| 774 | // Processes isapiCgiRestriction | ||
| 775 | // | ||
| 776 | //------------------------------------------------------------------------------------------------- | ||
| 777 | HRESULT IIS7WebProperty( | ||
| 778 | __inout LPWSTR *ppwzCustomActionData, | ||
| 779 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 780 | ) | ||
| 781 | { | ||
| 782 | HRESULT hr = S_OK; | ||
| 783 | |||
| 784 | int iAction = -1; | ||
| 785 | int iData = 0; | ||
| 786 | |||
| 787 | IAppHostElement *pSection = NULL; | ||
| 788 | |||
| 789 | // Get action | ||
| 790 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 791 | ExitOnFailure(hr, "Failed to read property action"); | ||
| 792 | |||
| 793 | switch (iAction) | ||
| 794 | { | ||
| 795 | case IIS_PROPERTY_MAXBAND: | ||
| 796 | { | ||
| 797 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 798 | ExitOnFailure(hr, "Failed to read property max band"); | ||
| 799 | //set value at system.applicationHost/webLimits | maxGlobalBandwidth | ||
| 800 | //Get IIS config section | ||
| 801 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_WEBLIMITS_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection); | ||
| 802 | ExitOnFailure(hr, "Failed get isapiCgiRestriction section"); | ||
| 803 | if (!pSection) | ||
| 804 | { | ||
| 805 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 806 | ExitOnFailure(hr, "Failed get isapiCgiRestriction section object"); | ||
| 807 | } | ||
| 808 | hr = Iis7PutPropertyInteger(pSection, IIS_CONFIG_WEBLIMITS_MAXBAND, iData); | ||
| 809 | |||
| 810 | break; | ||
| 811 | } | ||
| 812 | case IIS_PROPERTY_LOGUTF8: | ||
| 813 | { | ||
| 814 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 815 | ExitOnFailure(hr, "Failed to read property log"); | ||
| 816 | //set value at system.applicationHost/log | logInUTF8 | ||
| 817 | //Get IIS config section | ||
| 818 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_LOG_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection); | ||
| 819 | ExitOnFailure(hr, "Failed get isapiCgiRestriction section"); | ||
| 820 | if (!pSection) | ||
| 821 | { | ||
| 822 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 823 | ExitOnFailure(hr, "Failed get isapiCgiRestriction section object"); | ||
| 824 | } | ||
| 825 | hr = Iis7PutPropertyBool(pSection, IIS_CONFIG_LOG_UTF8, iData); | ||
| 826 | |||
| 827 | break; | ||
| 828 | } | ||
| 829 | default: | ||
| 830 | { | ||
| 831 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for Web Property"); | ||
| 832 | break; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | LExit: | ||
| 837 | ReleaseObject(pSection); | ||
| 838 | |||
| 839 | return hr; | ||
| 840 | } | ||
| 841 | |||
| 842 | //------------------------------------------------------------------------------------------------- | ||
| 843 | // IIS7WebSvcExt | ||
| 844 | // Called by WriteIIS7ConfigChanges | ||
| 845 | // Processes isapiCgiRestriction | ||
| 846 | // | ||
| 847 | //------------------------------------------------------------------------------------------------- | ||
| 848 | HRESULT IIS7WebSvcExt( | ||
| 849 | __inout LPWSTR *ppwzCustomActionData, | ||
| 850 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 851 | ) | ||
| 852 | { | ||
| 853 | HRESULT hr = S_OK; | ||
| 854 | |||
| 855 | int iAction = -1; | ||
| 856 | int iData = 0; | ||
| 857 | BOOL fFound = FALSE; | ||
| 858 | LPWSTR pwzData = NULL; | ||
| 859 | LPWSTR pwzPath = NULL; | ||
| 860 | |||
| 861 | IAppHostElement *pSection = NULL; | ||
| 862 | IAppHostElement *pElement = NULL; | ||
| 863 | IAppHostElementCollection *pCollection = NULL; | ||
| 864 | |||
| 865 | // Get action | ||
| 866 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 867 | ExitOnFailure(hr, "Failed to read WebSvcExt action"); | ||
| 868 | |||
| 869 | //get path | ||
| 870 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzPath); | ||
| 871 | ExitOnFailure(hr, "Failed to read WebSvcExt key"); | ||
| 872 | |||
| 873 | //Get IIS config section | ||
| 874 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_RESTRICTION_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection); | ||
| 875 | ExitOnFailure(hr, "Failed get isapiCgiRestriction section"); | ||
| 876 | if (!pSection) | ||
| 877 | { | ||
| 878 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 879 | ExitOnFailure(hr, "Failed get isapiCgiRestriction section object"); | ||
| 880 | } | ||
| 881 | //get collection | ||
| 882 | hr = pSection->get_Collection(&pCollection); | ||
| 883 | ExitOnFailure(hr, "Failed get isapiCgiRestriction collection"); | ||
| 884 | |||
| 885 | //find element | ||
| 886 | hr = Iis7FindAppHostElementPath(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_PATH, pwzPath, &pElement, NULL); | ||
| 887 | ExitOnFailure(hr, "Failed get isapiCgiRestriction element"); | ||
| 888 | fFound = (NULL != pElement); | ||
| 889 | |||
| 890 | switch (iAction) | ||
| 891 | { | ||
| 892 | case IIS_CREATE: | ||
| 893 | { | ||
| 894 | if (!fFound) | ||
| 895 | { | ||
| 896 | //create a restriction element | ||
| 897 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement); | ||
| 898 | ExitOnFailure(hr, "Failed create isapiCgiRestriction element"); | ||
| 899 | //put path | ||
| 900 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzPath); | ||
| 901 | ExitOnFailure(hr, "Failed set isapiCgiRestriction path property"); | ||
| 902 | } | ||
| 903 | //update common properties | ||
| 904 | |||
| 905 | //update allowed | ||
| 906 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 907 | ExitOnFailure(hr, "Failed to read WebSvcExt allowed"); | ||
| 908 | hr = Iis7PutPropertyBool(pElement, IIS_CONFIG_ALLOWED, iData); | ||
| 909 | ExitOnFailure(hr, "Failed set isapiCgiRestriction allowed property"); | ||
| 910 | |||
| 911 | //update groupId | ||
| 912 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 913 | ExitOnFailure(hr, "Failed to read WebSvcExt group ID"); | ||
| 914 | if (*pwzData) | ||
| 915 | { | ||
| 916 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_GROUPID, pwzData); | ||
| 917 | ExitOnFailure(hr, "Failed set isapiCgiRestriction groupId property"); | ||
| 918 | } | ||
| 919 | //update description | ||
| 920 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 921 | ExitOnFailure(hr, "Failed to read WebSvcExt description"); | ||
| 922 | if (*pwzData) | ||
| 923 | { | ||
| 924 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_DESC, pwzData); | ||
| 925 | ExitOnFailure(hr, "Failed set isapiCgiRestriction description property"); | ||
| 926 | } | ||
| 927 | // add element if new | ||
| 928 | if (!fFound) | ||
| 929 | { | ||
| 930 | hr = pCollection->AddElement(pElement); | ||
| 931 | ExitOnFailure(hr, "Failed add isapiCgiRestriction element"); | ||
| 932 | } | ||
| 933 | |||
| 934 | break; | ||
| 935 | } | ||
| 936 | case IIS_DELETE: | ||
| 937 | { | ||
| 938 | hr = DeleteCollectionElement(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_PATH, pwzPath); | ||
| 939 | ExitOnFailure(hr, "Failed delete isapiCgiRestriction element"); | ||
| 940 | break; | ||
| 941 | } | ||
| 942 | default: | ||
| 943 | { | ||
| 944 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for WebSvcExt"); | ||
| 945 | break; | ||
| 946 | } | ||
| 947 | } | ||
| 948 | |||
| 949 | LExit: | ||
| 950 | ReleaseStr(pwzPath); | ||
| 951 | ReleaseStr(pwzData); | ||
| 952 | ReleaseObject(pSection); | ||
| 953 | ReleaseObject(pElement); | ||
| 954 | ReleaseObject(pCollection); | ||
| 955 | |||
| 956 | return hr; | ||
| 957 | |||
| 958 | } | ||
| 959 | |||
| 960 | //------------------------------------------------------------------------------------------------- | ||
| 961 | // IIS7WebError | ||
| 962 | // Called by WriteIIS7ConfigChanges | ||
| 963 | // Processes http header CA Data | ||
| 964 | // | ||
| 965 | //------------------------------------------------------------------------------------------------- | ||
| 966 | |||
| 967 | HRESULT IIS7WebError( | ||
| 968 | __inout LPWSTR *ppwzCustomActionData, | ||
| 969 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 970 | ) | ||
| 971 | { | ||
| 972 | HRESULT hr = S_OK; | ||
| 973 | LPWSTR pwzConfigPath = NULL; | ||
| 974 | LPWSTR pwzSiteName = NULL; | ||
| 975 | LPWSTR pwzAppName = NULL; | ||
| 976 | |||
| 977 | IAppHostElement *pElement = NULL; | ||
| 978 | IAppHostElement *pSection = NULL; | ||
| 979 | IAppHostElementCollection *pCollection = NULL; | ||
| 980 | |||
| 981 | SCA_WEB_ERROR_SERVER *psweList = NULL; | ||
| 982 | SCA_WEB_ERROR_SERVER* pswe = NULL; | ||
| 983 | SCA_WEB_ERROR_SERVER we; | ||
| 984 | BOOL fFound = FALSE; | ||
| 985 | |||
| 986 | int iAction = -1; | ||
| 987 | LPWSTR pwzData = NULL; | ||
| 988 | |||
| 989 | //read web site key | ||
| 990 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 991 | ExitOnFailure(hr, "Failed read web error site name"); | ||
| 992 | |||
| 993 | //read app key | ||
| 994 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppName); | ||
| 995 | ExitOnFailure(hr, "Failed read web error app name"); | ||
| 996 | |||
| 997 | //Construct config root path | ||
| 998 | hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName); | ||
| 999 | ExitOnFailure(hr, "failed to format web error config path"); | ||
| 1000 | |||
| 1001 | if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzAppName, -1, L"/", -1)) | ||
| 1002 | { | ||
| 1003 | hr = StrAllocConcat(&pwzConfigPath, L"/", 0); | ||
| 1004 | ExitOnFailure(hr, "failed to copy web error config path delim"); | ||
| 1005 | hr = StrAllocConcat(&pwzConfigPath, pwzAppName, 0); | ||
| 1006 | ExitOnFailure(hr, "failed to app name to web error config path"); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | //get httpErrors section at config path location tag | ||
| 1010 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPERRORS_SECTION), pwzConfigPath, &pSection); | ||
| 1011 | ExitOnFailure(hr, "Failed get httpErrors section"); | ||
| 1012 | |||
| 1013 | //get existing httpErrors list & clear collection | ||
| 1014 | hr = PopulateHttpErrors(pSection, &psweList); | ||
| 1015 | ExitOnFailure(hr, "Failed to read httpErrors list"); | ||
| 1016 | |||
| 1017 | //get collection | ||
| 1018 | hr = pSection->get_Collection(&pCollection); | ||
| 1019 | ExitOnFailure(hr, "Failed get httpErrors collection"); | ||
| 1020 | |||
| 1021 | DWORD cErrors = 0; | ||
| 1022 | hr = pCollection->get_Count(&cErrors); | ||
| 1023 | |||
| 1024 | // Get web error action | ||
| 1025 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1026 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1027 | while (IIS_WEBERROR_END != iAction) | ||
| 1028 | { | ||
| 1029 | //Process property action | ||
| 1030 | if (IIS_WEBERROR == iAction) | ||
| 1031 | { | ||
| 1032 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &(we.iErrorCode)); | ||
| 1033 | ExitOnFailure(hr, "failed to get httpErrors ErrorCode"); | ||
| 1034 | |||
| 1035 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &(we.iSubCode)); | ||
| 1036 | ExitOnFailure(hr, "failed to get httpErrors SubCode"); | ||
| 1037 | //0 is the sub error code wild card for IIS6, change to -1 for IIS7 | ||
| 1038 | if (we.iSubCode == 0) | ||
| 1039 | { | ||
| 1040 | we.iSubCode = -1; | ||
| 1041 | } | ||
| 1042 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 1043 | ExitOnFailure(hr, "Failed to get httpErrors File"); | ||
| 1044 | hr = ::StringCchCopyW(we.wzFile, countof(we.wzFile), pwzData); | ||
| 1045 | ExitOnFailure(hr, "Failed to copy httpErrors File"); | ||
| 1046 | |||
| 1047 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &(we.iResponseMode)); | ||
| 1048 | ExitOnFailure(hr, "Failed to get httpErrors File code"); | ||
| 1049 | |||
| 1050 | fFound = FALSE; | ||
| 1051 | hr = GetErrorFromList( we, &psweList, &pswe, &fFound); | ||
| 1052 | if (!fFound) | ||
| 1053 | { | ||
| 1054 | hr = AddWebErrorToList(&psweList); | ||
| 1055 | ExitOnFailure(hr, "failed to add web error to list"); | ||
| 1056 | pswe = psweList; | ||
| 1057 | } | ||
| 1058 | else | ||
| 1059 | { | ||
| 1060 | //if overwriting existing http errors element then clear lang path | ||
| 1061 | hr = ::StringCchCopyW(pswe->wzLangPath, countof(pswe->wzLangPath), L""); | ||
| 1062 | ExitOnFailure(hr, "Failed to copy httpErrors lang path value"); | ||
| 1063 | } | ||
| 1064 | pswe->iErrorCode = we.iErrorCode; | ||
| 1065 | pswe->iSubCode = we.iSubCode; | ||
| 1066 | hr = ::StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), we.wzFile); | ||
| 1067 | ExitOnFailure(hr, "Failed to copy httpErrors File value"); | ||
| 1068 | pswe->iResponseMode = we.iResponseMode; | ||
| 1069 | |||
| 1070 | } | ||
| 1071 | else | ||
| 1072 | { | ||
| 1073 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for http header"); | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | // Get AppExt action | ||
| 1077 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1078 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | //No inheritance - put a clear in at this loc tag | ||
| 1082 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pElement); | ||
| 1083 | ExitOnFailure(hr, "Failed create httpErrors clear"); | ||
| 1084 | hr = pCollection->AddElement(pElement); | ||
| 1085 | ExitOnFailure(hr, "Failed add httpErrors clear"); | ||
| 1086 | |||
| 1087 | //now we have merged new, from MSI, http errors with global list | ||
| 1088 | //write this back out at location tag. | ||
| 1089 | // Loop through the HTTP headers | ||
| 1090 | for ( pswe = psweList; pswe; pswe = pswe->psweNext) | ||
| 1091 | { | ||
| 1092 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ERROR), &pElement); | ||
| 1093 | ExitOnFailure(hr, "Failed create httpErrors element"); | ||
| 1094 | |||
| 1095 | // status code | ||
| 1096 | hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_STATUSCODE, pswe->iErrorCode); | ||
| 1097 | ExitOnFailure(hr, "Failed set httpErrors code value"); | ||
| 1098 | |||
| 1099 | //sub status | ||
| 1100 | hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_SUBSTATUS, pswe->iSubCode); | ||
| 1101 | ExitOnFailure(hr, "Failed set httpErrors sub code value"); | ||
| 1102 | |||
| 1103 | //lang path | ||
| 1104 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_LANGPATH, pswe->wzLangPath); | ||
| 1105 | ExitOnFailure(hr, "Failed set httpErrors lang path value"); | ||
| 1106 | |||
| 1107 | //path | ||
| 1108 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pswe->wzFile); | ||
| 1109 | ExitOnFailure(hr, "Failed set httpErrors path value"); | ||
| 1110 | |||
| 1111 | //response mode | ||
| 1112 | hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_RESPMODE, pswe->iResponseMode); | ||
| 1113 | ExitOnFailure(hr, "Failed set httpErrors resp mode value"); | ||
| 1114 | |||
| 1115 | //add the element | ||
| 1116 | hr = pCollection->AddElement(pElement); | ||
| 1117 | ExitOnFailure(hr, "Failed add httpErrors element"); | ||
| 1118 | ReleaseNullObject(pElement); | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | LExit: | ||
| 1122 | ScaWebErrorFreeList7(psweList); | ||
| 1123 | |||
| 1124 | ReleaseStr(pwzConfigPath); | ||
| 1125 | ReleaseStr(pwzSiteName); | ||
| 1126 | ReleaseStr(pwzAppName); | ||
| 1127 | ReleaseStr(pwzData); | ||
| 1128 | ReleaseObject(pElement); | ||
| 1129 | ReleaseObject(pSection); | ||
| 1130 | ReleaseObject(pCollection); | ||
| 1131 | |||
| 1132 | return hr; | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | static HRESULT PopulateHttpErrors(IAppHostElement *pSection, SCA_WEB_ERROR_SERVER **ppsweList) | ||
| 1136 | { | ||
| 1137 | HRESULT hr = S_OK; | ||
| 1138 | |||
| 1139 | IAppHostElement *pElement = NULL; | ||
| 1140 | IAppHostElementCollection *pCollection = NULL; | ||
| 1141 | IAppHostProperty *pProperty = NULL; | ||
| 1142 | |||
| 1143 | DWORD cErrors = 0; | ||
| 1144 | SCA_WEB_ERROR_SERVER *pswe = NULL; | ||
| 1145 | |||
| 1146 | VARIANT vPropValue; | ||
| 1147 | VARIANT vtIndex; | ||
| 1148 | |||
| 1149 | VariantInit(&vPropValue); | ||
| 1150 | VariantInit(&vtIndex); | ||
| 1151 | |||
| 1152 | hr = pSection->get_Collection(&pCollection); | ||
| 1153 | ExitOnFailure(hr, "Failed get httpErrors collection"); | ||
| 1154 | |||
| 1155 | hr = pCollection->get_Count(&cErrors); | ||
| 1156 | ExitOnFailure(hr, "Failed get sites collection count"); | ||
| 1157 | |||
| 1158 | vtIndex.vt = VT_UI4; | ||
| 1159 | for (DWORD i = 0; i < cErrors; ++i) | ||
| 1160 | { | ||
| 1161 | vtIndex.ulVal = i; | ||
| 1162 | hr = pCollection->get_Item(vtIndex , &pElement); | ||
| 1163 | ExitOnFailure(hr, "Failed get httpErrors collection item"); | ||
| 1164 | |||
| 1165 | hr = AddWebErrorToList(ppsweList); | ||
| 1166 | ExitOnFailure(hr, "Failed add web error list item"); | ||
| 1167 | pswe = *ppsweList; | ||
| 1168 | |||
| 1169 | //get all properties | ||
| 1170 | // | ||
| 1171 | // statusCode UINT | ||
| 1172 | // subStatusCode INT | ||
| 1173 | // prefixLanguageFilePath type="string" | ||
| 1174 | // path type="string" | ||
| 1175 | // responseMode type="enum" defaultValue="File"> | ||
| 1176 | // <enum name="File" value="0" /> | ||
| 1177 | // <enum name="ExecuteURL" value="1" /> | ||
| 1178 | // <enum name="Redirect" value="2" /> | ||
| 1179 | |||
| 1180 | // status code | ||
| 1181 | hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_STATUSCODE), &pProperty); | ||
| 1182 | ExitOnFailure(hr, "Failed get httpErrors code property"); | ||
| 1183 | hr = pProperty->get_Value(&vPropValue); | ||
| 1184 | ExitOnFailure(hr, "Failed get httpErrors code value"); | ||
| 1185 | pswe->iErrorCode = vPropValue.uintVal; | ||
| 1186 | ReleaseVariant(vPropValue); | ||
| 1187 | |||
| 1188 | //sub status | ||
| 1189 | hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_SUBSTATUS), &pProperty); | ||
| 1190 | ExitOnFailure(hr, "Failed get httpErrors sub code property"); | ||
| 1191 | hr = pProperty->get_Value(&vPropValue); | ||
| 1192 | ExitOnFailure(hr, "Failed get httpErrors sub code value"); | ||
| 1193 | pswe->iSubCode = vPropValue.intVal; | ||
| 1194 | ReleaseVariant(vPropValue); | ||
| 1195 | |||
| 1196 | //lang path | ||
| 1197 | hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_LANGPATH), &pProperty); | ||
| 1198 | ExitOnFailure(hr, "Failed get httpErrors lang path property"); | ||
| 1199 | hr = pProperty->get_Value(&vPropValue); | ||
| 1200 | ExitOnFailure(hr, "Failed get httpErrors lang path value"); | ||
| 1201 | hr = ::StringCchCopyW(pswe->wzLangPath, countof(pswe->wzLangPath), vPropValue.bstrVal); | ||
| 1202 | ExitOnFailure(hr, "Failed to copy httpErrors lang path"); | ||
| 1203 | ReleaseVariant(vPropValue); | ||
| 1204 | |||
| 1205 | //path | ||
| 1206 | hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_PATH), &pProperty); | ||
| 1207 | ExitOnFailure(hr, "Failed get httpErrors path property"); | ||
| 1208 | hr = pProperty->get_Value(&vPropValue); | ||
| 1209 | ExitOnFailure(hr, "Failed get httpErrors path value"); | ||
| 1210 | hr = ::StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), vPropValue.bstrVal); | ||
| 1211 | ExitOnFailure(hr, "Failed to copy httpErrors File"); | ||
| 1212 | ReleaseVariant(vPropValue); | ||
| 1213 | |||
| 1214 | //response mode | ||
| 1215 | hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_RESPMODE), &pProperty); | ||
| 1216 | ExitOnFailure(hr, "Failed get httpErrors resp mode property"); | ||
| 1217 | hr = pProperty->get_Value(&vPropValue); | ||
| 1218 | ExitOnFailure(hr, "Failed get httpErrors resp mode value"); | ||
| 1219 | pswe->iResponseMode = vPropValue.intVal; | ||
| 1220 | ReleaseVariant(vPropValue); | ||
| 1221 | |||
| 1222 | ReleaseNullObject(pElement); | ||
| 1223 | ReleaseNullObject(pProperty); | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | //remove the elements from connection so we can add back later | ||
| 1227 | hr = pCollection->Clear(); | ||
| 1228 | ExitOnFailure(hr, "Failed clear httpErrors collection"); | ||
| 1229 | |||
| 1230 | LExit: | ||
| 1231 | ReleaseVariant(vPropValue); | ||
| 1232 | ReleaseObject(pProperty); | ||
| 1233 | ReleaseObject(pElement); | ||
| 1234 | ReleaseObject(pCollection); | ||
| 1235 | |||
| 1236 | return hr; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | static void ScaWebErrorFreeList7(SCA_WEB_ERROR_SERVER *psweList) | ||
| 1240 | { | ||
| 1241 | SCA_WEB_ERROR_SERVER *psweDelete = psweList; | ||
| 1242 | while (psweList) | ||
| 1243 | { | ||
| 1244 | psweDelete = psweList; | ||
| 1245 | psweList = psweList->psweNext; | ||
| 1246 | |||
| 1247 | MemFree(psweDelete); | ||
| 1248 | } | ||
| 1249 | } | ||
| 1250 | static HRESULT AddWebErrorToList(SCA_WEB_ERROR_SERVER **ppsweList) | ||
| 1251 | { | ||
| 1252 | HRESULT hr = S_OK; | ||
| 1253 | |||
| 1254 | SCA_WEB_ERROR_SERVER* pswe = static_cast<SCA_WEB_ERROR_SERVER*>(MemAlloc(sizeof(SCA_WEB_ERROR_SERVER), TRUE)); | ||
| 1255 | |||
| 1256 | ExitOnNull(pswe, hr, E_OUTOFMEMORY, "failed to allocate memory for new web error list element"); | ||
| 1257 | |||
| 1258 | pswe->psweNext = *ppsweList; | ||
| 1259 | *ppsweList = pswe; | ||
| 1260 | |||
| 1261 | LExit: | ||
| 1262 | return hr; | ||
| 1263 | } | ||
| 1264 | static HRESULT GetErrorFromList( const SCA_WEB_ERROR_SERVER& we, | ||
| 1265 | SCA_WEB_ERROR_SERVER **ppsweList, | ||
| 1266 | SCA_WEB_ERROR_SERVER **ppswe, | ||
| 1267 | BOOL *fFound) | ||
| 1268 | { | ||
| 1269 | HRESULT hr = S_OK; | ||
| 1270 | |||
| 1271 | *fFound = FALSE; | ||
| 1272 | |||
| 1273 | SCA_WEB_ERROR_SERVER *pswe; | ||
| 1274 | |||
| 1275 | for ( pswe = *ppsweList; pswe; pswe = pswe->psweNext) | ||
| 1276 | { | ||
| 1277 | if ((pswe->iErrorCode == we.iErrorCode) && (pswe->iSubCode == we.iSubCode)) | ||
| 1278 | { | ||
| 1279 | *fFound = TRUE; | ||
| 1280 | *ppswe = pswe; | ||
| 1281 | break; | ||
| 1282 | } | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | return hr; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | //------------------------------------------------------------------------------------------------- | ||
| 1289 | // IIS7HttpHeader | ||
| 1290 | // Called by WriteIIS7ConfigChanges | ||
| 1291 | // Processes http header CA Data | ||
| 1292 | // | ||
| 1293 | //------------------------------------------------------------------------------------------------- | ||
| 1294 | |||
| 1295 | HRESULT IIS7HttpHeader( | ||
| 1296 | __inout LPWSTR *ppwzCustomActionData, | ||
| 1297 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 1298 | ) | ||
| 1299 | { | ||
| 1300 | HRESULT hr = S_OK; | ||
| 1301 | LPWSTR pwzConfigPath = NULL; | ||
| 1302 | LPWSTR pwzSiteName = NULL; | ||
| 1303 | LPWSTR pwzAppName = NULL; | ||
| 1304 | |||
| 1305 | LPWSTR pwzHeaderName = NULL; | ||
| 1306 | LPWSTR pwzHeaderValue = NULL; | ||
| 1307 | |||
| 1308 | IAppHostElement *pElement = NULL; | ||
| 1309 | IAppHostElement *pSection = NULL; | ||
| 1310 | IAppHostElementCollection *pCollection = NULL; | ||
| 1311 | IAppHostElement *pElementHeaders = NULL; | ||
| 1312 | |||
| 1313 | int iAction = -1; | ||
| 1314 | BOOL fFound = FALSE; | ||
| 1315 | |||
| 1316 | //read web site key | ||
| 1317 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 1318 | ExitOnFailure(hr, "Failed read header web site name"); | ||
| 1319 | |||
| 1320 | //read app key | ||
| 1321 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppName); | ||
| 1322 | ExitOnFailure(hr, "Failed read header appkey"); | ||
| 1323 | |||
| 1324 | //Construct config root path | ||
| 1325 | hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName); | ||
| 1326 | ExitOnFailure(hr, "failed to format web error config path"); | ||
| 1327 | |||
| 1328 | if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzAppName, -1, L"/", -1)) | ||
| 1329 | { | ||
| 1330 | hr = StrAllocConcat(&pwzConfigPath, L"/", 0); | ||
| 1331 | ExitOnFailure(hr, "failed to copy web error config path delim"); | ||
| 1332 | hr = StrAllocConcat(&pwzConfigPath, pwzAppName, 0); | ||
| 1333 | ExitOnFailure(hr, "failed to app name to web error config path"); | ||
| 1334 | } | ||
| 1335 | |||
| 1336 | //get admin handlers section at config path location tag | ||
| 1337 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPPROTO_SECTION), pwzConfigPath, &pSection); | ||
| 1338 | ExitOnFailure(hr, "Failed get http protocol section"); | ||
| 1339 | |||
| 1340 | hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_HEADERS), &pElementHeaders); | ||
| 1341 | ExitOnFailure(hr, "Failed get http customHeaders section"); | ||
| 1342 | |||
| 1343 | hr = pElementHeaders->get_Collection(&pCollection); | ||
| 1344 | ExitOnFailure(hr, "Failed get http customHeaders collection"); | ||
| 1345 | |||
| 1346 | // Get filter action | ||
| 1347 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1348 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1349 | while (IIS_HTTP_HEADER_END != iAction) | ||
| 1350 | { | ||
| 1351 | //Process property action | ||
| 1352 | if (IIS_HTTP_HEADER == iAction) | ||
| 1353 | { | ||
| 1354 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzHeaderName); | ||
| 1355 | ExitOnFailure(hr, "Fail to read httpHeader name"); | ||
| 1356 | |||
| 1357 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzHeaderValue); | ||
| 1358 | ExitOnFailure(hr, "Fail to read httpHeader value"); | ||
| 1359 | |||
| 1360 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, pwzHeaderName, &pElement, NULL); | ||
| 1361 | ExitOnFailure(hr, "Failed get isapiCgiRestriction element"); | ||
| 1362 | fFound = (NULL != pElement); | ||
| 1363 | |||
| 1364 | if (!fFound) | ||
| 1365 | { | ||
| 1366 | //make a new element | ||
| 1367 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement); | ||
| 1368 | ExitOnFailure(hr, "Failed to create filter config element"); | ||
| 1369 | |||
| 1370 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_NAME, pwzHeaderName); | ||
| 1371 | ExitOnFailure(hr, "Failed to set header name"); | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_VALUE, pwzHeaderValue); | ||
| 1375 | ExitOnFailure(hr, "Failed to set header Value"); | ||
| 1376 | |||
| 1377 | if (!fFound) | ||
| 1378 | { | ||
| 1379 | hr = pCollection->AddElement(pElement); | ||
| 1380 | ExitOnFailure(hr, "Failed add http header"); | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | } | ||
| 1384 | else | ||
| 1385 | { | ||
| 1386 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for http header"); | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | // Get AppExt action | ||
| 1390 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1391 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | LExit: | ||
| 1395 | ReleaseStr(pwzConfigPath); | ||
| 1396 | ReleaseStr(pwzSiteName); | ||
| 1397 | ReleaseStr(pwzAppName); | ||
| 1398 | ReleaseStr(pwzHeaderName); | ||
| 1399 | ReleaseStr(pwzHeaderValue); | ||
| 1400 | ReleaseObject(pElementHeaders); | ||
| 1401 | ReleaseObject(pElement); | ||
| 1402 | ReleaseObject(pSection); | ||
| 1403 | ReleaseObject(pCollection); | ||
| 1404 | |||
| 1405 | return hr; | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | //------------------------------------------------------------------------------------------------- | ||
| 1409 | // IIS7FilterGlobal | ||
| 1410 | // Called by WriteIIS7ConfigChanges | ||
| 1411 | // Processes Filter CA Data | ||
| 1412 | // | ||
| 1413 | //------------------------------------------------------------------------------------------------- | ||
| 1414 | HRESULT IIS7FilterGlobal( | ||
| 1415 | __inout LPWSTR *ppwzCustomActionData, | ||
| 1416 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 1417 | ) | ||
| 1418 | { | ||
| 1419 | HRESULT hr = S_OK; | ||
| 1420 | int iAction = 0; | ||
| 1421 | |||
| 1422 | IAppHostElement *pSection = NULL; | ||
| 1423 | |||
| 1424 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ISAPI_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection); | ||
| 1425 | ExitOnFailure(hr, "Failed get sites section"); | ||
| 1426 | |||
| 1427 | if (!pSection) | ||
| 1428 | { | ||
| 1429 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 1430 | ExitOnFailure(hr, "Failed get isapiFilters section object"); | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | // Get filter action | ||
| 1434 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1435 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1436 | |||
| 1437 | while (IIS_FILTER_END != iAction) | ||
| 1438 | { | ||
| 1439 | //Process property action | ||
| 1440 | switch (iAction) | ||
| 1441 | { | ||
| 1442 | case IIS_FILTER : | ||
| 1443 | { | ||
| 1444 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1445 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1446 | |||
| 1447 | if (iAction == IIS_CREATE) | ||
| 1448 | { | ||
| 1449 | hr = CreateGlobalFilter(ppwzCustomActionData, pSection); | ||
| 1450 | } | ||
| 1451 | else | ||
| 1452 | { | ||
| 1453 | hr = DeleteGlobalFilter(ppwzCustomActionData, pSection); | ||
| 1454 | } | ||
| 1455 | break; | ||
| 1456 | } | ||
| 1457 | default: | ||
| 1458 | { | ||
| 1459 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for global filter"); | ||
| 1460 | break; | ||
| 1461 | } | ||
| 1462 | } | ||
| 1463 | // Get AppExt action | ||
| 1464 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1465 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1466 | |||
| 1467 | } | ||
| 1468 | |||
| 1469 | LExit: | ||
| 1470 | ReleaseObject(pSection); | ||
| 1471 | |||
| 1472 | return hr; | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | static HRESULT CreateGlobalFilter( __inout LPWSTR *ppwzCustomActionData, IAppHostElement *pSection) | ||
| 1476 | { | ||
| 1477 | HRESULT hr = S_OK; | ||
| 1478 | |||
| 1479 | LPWSTR pwzFilterName = NULL; | ||
| 1480 | LPWSTR pwzSiteName = NULL; | ||
| 1481 | LPWSTR pwzFilterPath = NULL; | ||
| 1482 | int iLoadOrder = 0; | ||
| 1483 | DWORD cFilters = 0; | ||
| 1484 | |||
| 1485 | IAppHostElement *pElement = NULL; | ||
| 1486 | IAppHostElementCollection *pCollection = NULL; | ||
| 1487 | |||
| 1488 | hr = pSection->get_Collection(&pCollection); | ||
| 1489 | ExitOnFailure(hr, "Failed get filter collection"); | ||
| 1490 | |||
| 1491 | hr = pCollection->get_Count(&cFilters); | ||
| 1492 | ExitOnFailure(hr, "Failed get filter collection count"); | ||
| 1493 | |||
| 1494 | // Attempt to delete, we will we recreate with desired property values and order | ||
| 1495 | hr = DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName); | ||
| 1496 | ExitOnFailure(hr, "Failed to delete filter"); | ||
| 1497 | |||
| 1498 | //make a new element | ||
| 1499 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_FILTER), &pElement); | ||
| 1500 | ExitOnFailure(hr, "Failed to create filter config element"); | ||
| 1501 | |||
| 1502 | //filter Name key | ||
| 1503 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName); | ||
| 1504 | ExitOnFailure(hr, "Failed to read filter name"); | ||
| 1505 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_NAME, pwzFilterName); | ||
| 1506 | ExitOnFailure(hr, "Failed to set filter name"); | ||
| 1507 | |||
| 1508 | //web site name | ||
| 1509 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 1510 | ExitOnFailure(hr, "Failed to read filter site name"); | ||
| 1511 | |||
| 1512 | // filter path | ||
| 1513 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterPath); | ||
| 1514 | ExitOnFailure(hr, "Failed to read filter path"); | ||
| 1515 | hr = Iis7PutPropertyString(pElement,IIS_CONFIG_PATH, pwzFilterPath); | ||
| 1516 | ExitOnFailure(hr, "Failed to set filter path"); | ||
| 1517 | |||
| 1518 | //filter load order | ||
| 1519 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iLoadOrder); | ||
| 1520 | ExitOnFailure(hr, "Failed to read filter load order"); | ||
| 1521 | |||
| 1522 | // put element in order in list | ||
| 1523 | int iPosition = -1; | ||
| 1524 | int icFilters = cFilters; | ||
| 1525 | switch (iLoadOrder) | ||
| 1526 | { | ||
| 1527 | case 0 : | ||
| 1528 | { | ||
| 1529 | iPosition = -1; | ||
| 1530 | break; | ||
| 1531 | } | ||
| 1532 | case -1 : | ||
| 1533 | { | ||
| 1534 | iPosition = icFilters; | ||
| 1535 | break; | ||
| 1536 | } | ||
| 1537 | case MSI_NULL_INTEGER : | ||
| 1538 | { | ||
| 1539 | iPosition = icFilters; | ||
| 1540 | break; | ||
| 1541 | } | ||
| 1542 | default: | ||
| 1543 | { | ||
| 1544 | if (iLoadOrder > icFilters) | ||
| 1545 | { | ||
| 1546 | iPosition = icFilters; | ||
| 1547 | } | ||
| 1548 | else | ||
| 1549 | { | ||
| 1550 | iPosition = iLoadOrder; | ||
| 1551 | } | ||
| 1552 | break; | ||
| 1553 | } | ||
| 1554 | } | ||
| 1555 | hr = pCollection->AddElement(pElement, iPosition); | ||
| 1556 | ExitOnFailure(hr, "Failed to add filter element"); | ||
| 1557 | |||
| 1558 | LExit: | ||
| 1559 | ReleaseStr(pwzFilterName); | ||
| 1560 | ReleaseStr(pwzSiteName); | ||
| 1561 | ReleaseStr(pwzFilterPath); | ||
| 1562 | ReleaseObject(pCollection); | ||
| 1563 | ReleaseObject(pElement); | ||
| 1564 | |||
| 1565 | return hr; | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | static HRESULT DeleteGlobalFilter( __inout LPWSTR *ppwzCustomActionData, IAppHostElement *pSection) | ||
| 1569 | { | ||
| 1570 | HRESULT hr = S_OK; | ||
| 1571 | |||
| 1572 | LPWSTR pwzFilterName = NULL; | ||
| 1573 | LPWSTR pwzSiteName = NULL; | ||
| 1574 | |||
| 1575 | IAppHostElementCollection *pCollection = NULL; | ||
| 1576 | |||
| 1577 | hr = pSection->get_Collection(&pCollection); | ||
| 1578 | ExitOnFailure(hr, "Failed get filter collection"); | ||
| 1579 | |||
| 1580 | //filter Name key | ||
| 1581 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName); | ||
| 1582 | ExitOnFailure(hr, "Failed to read filter name"); | ||
| 1583 | |||
| 1584 | //web site name | ||
| 1585 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); // TODO: unused? | ||
| 1586 | ExitOnFailure(hr, "Failed to read filter site name"); | ||
| 1587 | |||
| 1588 | DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName); | ||
| 1589 | ExitOnFailure(hr, "Failed to delete filter %ls", pwzFilterName); | ||
| 1590 | |||
| 1591 | LExit: | ||
| 1592 | ReleaseStr(pwzFilterName); | ||
| 1593 | ReleaseStr(pwzSiteName); | ||
| 1594 | ReleaseObject(pCollection); | ||
| 1595 | |||
| 1596 | return hr; | ||
| 1597 | } | ||
| 1598 | |||
| 1599 | //------------------------------------------------------------------------------------------------- | ||
| 1600 | // IIS7FilterSite | ||
| 1601 | // Called by WriteIIS7ConfigChanges | ||
| 1602 | // Processes Filter CA Data | ||
| 1603 | // | ||
| 1604 | //------------------------------------------------------------------------------------------------- | ||
| 1605 | HRESULT IIS7FilterSite( | ||
| 1606 | __inout LPWSTR *ppwzCustomActionData, | ||
| 1607 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 1608 | ) | ||
| 1609 | { | ||
| 1610 | HRESULT hr = S_OK; | ||
| 1611 | int iAction = 0; | ||
| 1612 | |||
| 1613 | // Get filter action | ||
| 1614 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1615 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1616 | |||
| 1617 | while (IIS_FILTER_END != iAction) | ||
| 1618 | { | ||
| 1619 | //Process property action | ||
| 1620 | switch (iAction) | ||
| 1621 | { | ||
| 1622 | case IIS_FILTER : | ||
| 1623 | { | ||
| 1624 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1625 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1626 | |||
| 1627 | if (iAction == IIS_CREATE) | ||
| 1628 | { | ||
| 1629 | hr = CreateSiteFilter(ppwzCustomActionData, pAdminMgr); | ||
| 1630 | } | ||
| 1631 | else | ||
| 1632 | { | ||
| 1633 | hr = DeleteSiteFilter(ppwzCustomActionData, pAdminMgr); | ||
| 1634 | } | ||
| 1635 | break; | ||
| 1636 | } | ||
| 1637 | default: | ||
| 1638 | { | ||
| 1639 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for global filter"); | ||
| 1640 | break; | ||
| 1641 | } | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | // Get AppExt action | ||
| 1645 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1646 | ExitOnFailure(hr, "Failed to read filter action"); | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | LExit: | ||
| 1650 | return hr; | ||
| 1651 | |||
| 1652 | } | ||
| 1653 | |||
| 1654 | static HRESULT CreateSiteFilter(__inout LPWSTR *ppwzCustomActionData, IAppHostWritableAdminManager *pAdminMgr) | ||
| 1655 | { | ||
| 1656 | HRESULT hr = S_OK; | ||
| 1657 | LPWSTR pwzFilterName = NULL; | ||
| 1658 | LPWSTR pwzSiteName = NULL; | ||
| 1659 | LPWSTR pwzFilterPath = NULL; | ||
| 1660 | LPWSTR pwzConfigPath = NULL; | ||
| 1661 | int iLoadOrder = 0; | ||
| 1662 | DWORD cFilters; | ||
| 1663 | |||
| 1664 | IAppHostElement *pElement = NULL; | ||
| 1665 | IAppHostElement *pSection = NULL; | ||
| 1666 | IAppHostElementCollection *pCollection = NULL; | ||
| 1667 | |||
| 1668 | //filter Name key | ||
| 1669 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName); | ||
| 1670 | ExitOnFailure(hr, "Failed to read filter name"); | ||
| 1671 | |||
| 1672 | //web site name | ||
| 1673 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 1674 | ExitOnFailure(hr, "Failed to read filter site name"); | ||
| 1675 | |||
| 1676 | //Construct config root | ||
| 1677 | hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName); | ||
| 1678 | ExitOnFailure(hr, "failed to format filter config path"); | ||
| 1679 | |||
| 1680 | //get admin isapiFilters section at config path location tag | ||
| 1681 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ISAPI_SECTION), pwzConfigPath, &pSection); | ||
| 1682 | ExitOnFailure(hr, "Failed get isapiFilters section"); | ||
| 1683 | |||
| 1684 | hr = pSection->get_Collection(&pCollection); | ||
| 1685 | ExitOnFailure(hr, "Failed get filter collection"); | ||
| 1686 | |||
| 1687 | hr = pCollection->get_Count(&cFilters); | ||
| 1688 | ExitOnFailure(hr, "Failed get filter collection count"); | ||
| 1689 | |||
| 1690 | // Attempt to delete, we will we recreate with desired property values and order | ||
| 1691 | hr = DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName); | ||
| 1692 | ExitOnFailure(hr, "Failed to delete filter"); | ||
| 1693 | |||
| 1694 | //make a new element | ||
| 1695 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_FILTER), &pElement); | ||
| 1696 | ExitOnFailure(hr, "Failed to create filter config element"); | ||
| 1697 | |||
| 1698 | hr = Iis7PutPropertyString(pElement,IIS_CONFIG_NAME, pwzFilterName); | ||
| 1699 | ExitOnFailure(hr, "Failed to set filter name"); | ||
| 1700 | |||
| 1701 | // filter path | ||
| 1702 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterPath); | ||
| 1703 | ExitOnFailure(hr, "Failed to read filter path"); | ||
| 1704 | |||
| 1705 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzFilterPath); | ||
| 1706 | ExitOnFailure(hr, "Failed to set filter path"); | ||
| 1707 | |||
| 1708 | //filter load order | ||
| 1709 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iLoadOrder); | ||
| 1710 | ExitOnFailure(hr, "Failed to read filter load order"); | ||
| 1711 | |||
| 1712 | // put element in order in list | ||
| 1713 | int iPosition = -1; | ||
| 1714 | int icFilters = cFilters; | ||
| 1715 | switch (iLoadOrder) | ||
| 1716 | { | ||
| 1717 | case 0 : | ||
| 1718 | { | ||
| 1719 | iPosition = -1; | ||
| 1720 | break; | ||
| 1721 | } | ||
| 1722 | case -1 : | ||
| 1723 | { | ||
| 1724 | iPosition = icFilters; | ||
| 1725 | break; | ||
| 1726 | } | ||
| 1727 | case MSI_NULL_INTEGER : | ||
| 1728 | { | ||
| 1729 | iPosition = icFilters; | ||
| 1730 | break; | ||
| 1731 | } | ||
| 1732 | default: | ||
| 1733 | { | ||
| 1734 | if (iLoadOrder > icFilters) | ||
| 1735 | { | ||
| 1736 | iPosition = icFilters; | ||
| 1737 | } | ||
| 1738 | else | ||
| 1739 | { | ||
| 1740 | iPosition = iLoadOrder; | ||
| 1741 | } | ||
| 1742 | break; | ||
| 1743 | } | ||
| 1744 | } | ||
| 1745 | |||
| 1746 | hr = pCollection->AddElement(pElement, iPosition); | ||
| 1747 | ExitOnFailure(hr, "Failed to add filter element"); | ||
| 1748 | |||
| 1749 | LExit: | ||
| 1750 | ReleaseStr(pwzFilterName); | ||
| 1751 | ReleaseStr(pwzSiteName); | ||
| 1752 | ReleaseStr(pwzFilterPath); | ||
| 1753 | ReleaseStr(pwzConfigPath); | ||
| 1754 | ReleaseObject(pElement); | ||
| 1755 | ReleaseObject(pSection); | ||
| 1756 | ReleaseObject(pCollection); | ||
| 1757 | |||
| 1758 | return hr; | ||
| 1759 | } | ||
| 1760 | |||
| 1761 | static HRESULT DeleteSiteFilter(__inout LPWSTR *ppwzCustomActionData, IAppHostWritableAdminManager *pAdminMgr) | ||
| 1762 | { | ||
| 1763 | HRESULT hr = S_OK; | ||
| 1764 | LPWSTR pwzFilterName = NULL; | ||
| 1765 | LPWSTR pwzSiteName = NULL; | ||
| 1766 | LPWSTR pwzConfigPath = NULL; | ||
| 1767 | |||
| 1768 | IAppHostElement *pSection = NULL; | ||
| 1769 | IAppHostElementCollection *pCollection = NULL; | ||
| 1770 | |||
| 1771 | //filter Name key | ||
| 1772 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName); | ||
| 1773 | ExitOnFailure(hr, "Failed to read filter name"); | ||
| 1774 | |||
| 1775 | //web site name | ||
| 1776 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 1777 | ExitOnFailure(hr, "Failed to read filter site name"); | ||
| 1778 | |||
| 1779 | //Construct config root | ||
| 1780 | hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName); | ||
| 1781 | ExitOnFailure(hr, "failed to format filter config path"); | ||
| 1782 | |||
| 1783 | //get admin isapiFilters section at config path location tag | ||
| 1784 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ISAPI_SECTION), pwzConfigPath, &pSection); | ||
| 1785 | ExitOnFailure(hr, "Failed get isapiFilters section"); | ||
| 1786 | |||
| 1787 | hr = pSection->get_Collection(&pCollection); | ||
| 1788 | ExitOnFailure(hr, "Failed get filter collection"); | ||
| 1789 | |||
| 1790 | DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName); | ||
| 1791 | ExitOnFailure(hr, "Failed to delete filter %ls", pwzFilterName); | ||
| 1792 | |||
| 1793 | LExit: | ||
| 1794 | ReleaseStr(pwzFilterName); | ||
| 1795 | ReleaseStr(pwzSiteName); | ||
| 1796 | ReleaseStr(pwzConfigPath); | ||
| 1797 | ReleaseObject(pSection); | ||
| 1798 | ReleaseObject(pCollection); | ||
| 1799 | |||
| 1800 | return hr; | ||
| 1801 | } | ||
| 1802 | |||
| 1803 | //------------------------------------------------------------------------------------------------- | ||
| 1804 | // IIS7Site | ||
| 1805 | // Called by WriteIIS7ConfigChanges | ||
| 1806 | // Processes WebSite CA Data | ||
| 1807 | // | ||
| 1808 | //------------------------------------------------------------------------------------------------- | ||
| 1809 | HRESULT IIS7Site( | ||
| 1810 | __inout LPWSTR *ppwzCustomActionData, | ||
| 1811 | __in IAppHostWritableAdminManager *pAdminMgr) | ||
| 1812 | { | ||
| 1813 | HRESULT hr = S_OK; | ||
| 1814 | int iAction = -1; | ||
| 1815 | int iData = 0; | ||
| 1816 | BOOL fFound = FALSE; | ||
| 1817 | |||
| 1818 | LPWSTR pwzSiteName = NULL; | ||
| 1819 | IAppHostElement *pSites = NULL; | ||
| 1820 | IAppHostElementCollection *pCollection = NULL; | ||
| 1821 | IAppHostElement *pSiteElem = NULL; | ||
| 1822 | IAppHostElement *pElement = NULL; | ||
| 1823 | |||
| 1824 | // Get site action | ||
| 1825 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 1826 | ExitOnFailure(hr, "Failed to read site action"); | ||
| 1827 | |||
| 1828 | //get site name | ||
| 1829 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 1830 | ExitOnFailure(hr, "Failed to read site key"); | ||
| 1831 | |||
| 1832 | //Get site if it exists | ||
| 1833 | hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fFound); | ||
| 1834 | ExitOnFailure(hr, "Failed to read sites from config"); | ||
| 1835 | |||
| 1836 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_SITES_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSites); | ||
| 1837 | ExitOnFailure(hr, "Failed get sites section"); | ||
| 1838 | ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object"); | ||
| 1839 | |||
| 1840 | hr = pSites->get_Collection( &pCollection); | ||
| 1841 | ExitOnFailure(hr, "Failed get site collection"); | ||
| 1842 | switch (iAction) | ||
| 1843 | { | ||
| 1844 | case IIS_DELETE : | ||
| 1845 | { | ||
| 1846 | if (fFound) | ||
| 1847 | { | ||
| 1848 | hr = DeleteCollectionElement(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, pwzSiteName); | ||
| 1849 | ExitOnFailure(hr, "Failed to delete website"); | ||
| 1850 | } | ||
| 1851 | ExitFunction(); | ||
| 1852 | break; | ||
| 1853 | } | ||
| 1854 | case IIS_CREATE : | ||
| 1855 | { | ||
| 1856 | if (!fFound) | ||
| 1857 | { | ||
| 1858 | //Create the site | ||
| 1859 | hr = CreateSite(pCollection, pwzSiteName, &pSiteElem); | ||
| 1860 | ExitOnFailure(hr, "Failed to create site"); | ||
| 1861 | |||
| 1862 | } | ||
| 1863 | } | ||
| 1864 | } | ||
| 1865 | // | ||
| 1866 | //Set other Site properties | ||
| 1867 | // | ||
| 1868 | //set site Id | ||
| 1869 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 1870 | ExitOnFailure(hr, "Failed to read site Id"); | ||
| 1871 | if (iData != MSI_NULL_INTEGER && -1 != iData) | ||
| 1872 | { | ||
| 1873 | hr = Iis7PutPropertyInteger(pSiteElem, IIS_CONFIG_SITE_ID, iData); | ||
| 1874 | ExitOnFailure(hr, "Failed set site Id data"); | ||
| 1875 | } | ||
| 1876 | //Set Site AutoStart | ||
| 1877 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 1878 | ExitOnFailure(hr, "Failed to read site autostart"); | ||
| 1879 | if (MSI_NULL_INTEGER != iData) | ||
| 1880 | { | ||
| 1881 | hr = Iis7PutPropertyBool(pSiteElem, IIS_CONFIG_AUTOSTART, iData); | ||
| 1882 | ExitOnFailure(hr, "Failed set site config data"); | ||
| 1883 | } | ||
| 1884 | |||
| 1885 | //Set Site Connection timeout | ||
| 1886 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 1887 | ExitOnFailure(hr, "Failed to read site connection tomeout data"); | ||
| 1888 | if (MSI_NULL_INTEGER != iData) | ||
| 1889 | { | ||
| 1890 | // get limits element, get connectionTimeout property | ||
| 1891 | hr = pSiteElem->GetElementByName(ScopeBSTR(IIS_CONFIG_LIMITS), &pElement); | ||
| 1892 | ExitOnFailure(hr, "Failed to read limits from config"); | ||
| 1893 | //convert iData in seconds to timeSpan hh:mm:ss | ||
| 1894 | WCHAR wcTime[60]; | ||
| 1895 | *wcTime = '\0'; | ||
| 1896 | ConvSecToHMS( iData, wcTime, countof( wcTime)); | ||
| 1897 | |||
| 1898 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CONNECTTIMEOUT, wcTime); | ||
| 1899 | ExitOnFailure(hr, "IIS: failed set connection timeout config data"); | ||
| 1900 | } | ||
| 1901 | |||
| 1902 | LExit: | ||
| 1903 | ReleaseStr(pwzSiteName); | ||
| 1904 | ReleaseObject(pSites); | ||
| 1905 | ReleaseObject(pCollection); | ||
| 1906 | ReleaseObject(pSiteElem); | ||
| 1907 | ReleaseObject(pElement); | ||
| 1908 | |||
| 1909 | return hr; | ||
| 1910 | } | ||
| 1911 | //------------------------------------------------------------------------------------------------- | ||
| 1912 | // IIS7Application | ||
| 1913 | // Processes Application CA Data | ||
| 1914 | // | ||
| 1915 | // | ||
| 1916 | //------------------------------------------------------------------------------------------------- | ||
| 1917 | |||
| 1918 | HRESULT IIS7Application( | ||
| 1919 | __inout LPWSTR *ppwzCustomActionData, | ||
| 1920 | __in IAppHostWritableAdminManager *pAdminMgr) | ||
| 1921 | { | ||
| 1922 | HRESULT hr = S_OK; | ||
| 1923 | |||
| 1924 | int iAction = -1; | ||
| 1925 | BOOL fSiteFound = FALSE; | ||
| 1926 | BOOL fAppFound = FALSE; | ||
| 1927 | |||
| 1928 | LPWSTR pwzSiteName = NULL; | ||
| 1929 | LPWSTR pwzAppPath = NULL; | ||
| 1930 | LPWSTR pwzAppPool = NULL; | ||
| 1931 | LPWSTR pwzLocationPath = NULL; | ||
| 1932 | IAppHostElement *pSiteElem = NULL; | ||
| 1933 | IAppHostElement *pAppElement = NULL; | ||
| 1934 | // Get Application action | ||
| 1935 | hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction); | ||
| 1936 | ExitOnFailure(hr, "Failed to read application action") | ||
| 1937 | //get site key name | ||
| 1938 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 1939 | ExitOnFailure(hr, "Failed to read app site key"); | ||
| 1940 | //get application path | ||
| 1941 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppPath); | ||
| 1942 | ExitOnFailure(hr, "Failed to read app path key"); | ||
| 1943 | //get application Pool | ||
| 1944 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppPool); | ||
| 1945 | ExitOnFailure(hr, "Failed to read app pool key"); | ||
| 1946 | |||
| 1947 | //Get site if it exists | ||
| 1948 | hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound); | ||
| 1949 | ExitOnFailure(hr, "Failed to read sites from config"); | ||
| 1950 | |||
| 1951 | switch (iAction) | ||
| 1952 | { | ||
| 1953 | case IIS_CREATE : | ||
| 1954 | { | ||
| 1955 | if (fSiteFound) | ||
| 1956 | { | ||
| 1957 | //have site get application collection | ||
| 1958 | hr = GetApplicationElement(pSiteElem, | ||
| 1959 | pwzAppPath, | ||
| 1960 | &pAppElement, | ||
| 1961 | &fAppFound); | ||
| 1962 | ExitOnFailure(hr, "Error reading application from config"); | ||
| 1963 | |||
| 1964 | if (!fAppFound) | ||
| 1965 | { | ||
| 1966 | //Create Application | ||
| 1967 | hr = CreateApplication(pSiteElem, pwzAppPath, &pAppElement); | ||
| 1968 | ExitOnFailure(hr, "Error creating application in config"); | ||
| 1969 | } | ||
| 1970 | //Update application properties: | ||
| 1971 | // | ||
| 1972 | //Set appPool | ||
| 1973 | hr = SetAppPool(pAppElement, pwzAppPool); | ||
| 1974 | ExitOnFailure(hr, "Unable to set appPool for application"); | ||
| 1975 | } | ||
| 1976 | else | ||
| 1977 | { | ||
| 1978 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 1979 | ExitOnFailure(hr, "Site not found for create application"); | ||
| 1980 | } | ||
| 1981 | break; | ||
| 1982 | } | ||
| 1983 | case IIS_DELETE : | ||
| 1984 | { | ||
| 1985 | if (fSiteFound) | ||
| 1986 | { | ||
| 1987 | //have site get application collection | ||
| 1988 | hr = GetApplicationElement( pSiteElem, | ||
| 1989 | pwzAppPath, | ||
| 1990 | &pAppElement, | ||
| 1991 | &fAppFound); | ||
| 1992 | ExitOnFailure(hr, "Error reading application from config") | ||
| 1993 | if (fAppFound) | ||
| 1994 | { | ||
| 1995 | //delete Application | ||
| 1996 | hr = DeleteApplication(pSiteElem, pwzAppPath); | ||
| 1997 | ExitOnFailure(hr, "Error deleating application from config") | ||
| 1998 | //Construct Location path | ||
| 1999 | // TODO: it seems odd that these are just | ||
| 2000 | // jammed together, need to determine if this requires a '\' | ||
| 2001 | hr = StrAllocString(&pwzLocationPath, pwzSiteName, 0); | ||
| 2002 | ExitOnFailure(hr, "failed to copy location config path web name"); | ||
| 2003 | hr = StrAllocConcat(&pwzLocationPath, pwzAppPath, 0); | ||
| 2004 | ExitOnFailure(hr, "failed to copy location config path appPath "); | ||
| 2005 | |||
| 2006 | // and delete location tag for this application | ||
| 2007 | hr = ClearLocationTag(pAdminMgr, pwzLocationPath); | ||
| 2008 | ExitOnFailure(hr, "failed to clear location tag for %ls", pwzLocationPath); | ||
| 2009 | } | ||
| 2010 | } | ||
| 2011 | break; | ||
| 2012 | } | ||
| 2013 | default: | ||
| 2014 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for Application"); | ||
| 2015 | break; | ||
| 2016 | } | ||
| 2017 | |||
| 2018 | LExit: | ||
| 2019 | ReleaseStr(pwzSiteName); | ||
| 2020 | ReleaseStr(pwzAppPath); | ||
| 2021 | ReleaseStr(pwzAppPool); | ||
| 2022 | ReleaseStr(pwzLocationPath); | ||
| 2023 | ReleaseObject(pSiteElem); | ||
| 2024 | ReleaseObject(pAppElement); | ||
| 2025 | |||
| 2026 | return hr; | ||
| 2027 | } | ||
| 2028 | //------------------------------------------------------------------------------------------------- | ||
| 2029 | // IIS7VDir | ||
| 2030 | // Processes VDir CA Data | ||
| 2031 | // | ||
| 2032 | // | ||
| 2033 | //------------------------------------------------------------------------------------------------- | ||
| 2034 | HRESULT IIS7VDir( | ||
| 2035 | __inout LPWSTR *ppwzCustomActionData, | ||
| 2036 | __in IAppHostWritableAdminManager *pAdminMgr) | ||
| 2037 | { | ||
| 2038 | HRESULT hr = S_OK; | ||
| 2039 | |||
| 2040 | int iAction = -1; | ||
| 2041 | BOOL fSiteFound = FALSE; | ||
| 2042 | BOOL fAppFound = FALSE; | ||
| 2043 | |||
| 2044 | LPWSTR pwzSiteName = NULL; | ||
| 2045 | LPWSTR pwzVDirPath = NULL; | ||
| 2046 | LPWSTR pwzVDirPhyDir = NULL; | ||
| 2047 | LPCWSTR pwzVDirSubPath = NULL; | ||
| 2048 | |||
| 2049 | IAppHostElement *pSiteElem = NULL; | ||
| 2050 | IAppHostElement *pAppElement = NULL; | ||
| 2051 | IAppHostElementCollection *pElement = NULL; | ||
| 2052 | |||
| 2053 | // Get Application action | ||
| 2054 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 2055 | ExitOnFailure(hr, "Failed to read VDir action"); | ||
| 2056 | |||
| 2057 | //get site key name | ||
| 2058 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 2059 | ExitOnFailure(hr, "Failed to read site key"); | ||
| 2060 | //get VDir path | ||
| 2061 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzVDirPath); | ||
| 2062 | ExitOnFailure(hr, "Failed to read VDir key"); | ||
| 2063 | //get physical dir path | ||
| 2064 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzVDirPhyDir); | ||
| 2065 | ExitOnFailure(hr, "Failed to read VDirPath key"); | ||
| 2066 | |||
| 2067 | //Get site if it exists | ||
| 2068 | hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound); | ||
| 2069 | ExitOnFailure(hr, "Failed to read sites from config"); | ||
| 2070 | |||
| 2071 | if (IIS_CREATE == iAction) | ||
| 2072 | { | ||
| 2073 | if (fSiteFound) | ||
| 2074 | { | ||
| 2075 | //have site get application | ||
| 2076 | hr = GetApplicationElementForVDir( pSiteElem, | ||
| 2077 | pwzVDirPath, | ||
| 2078 | &pAppElement, | ||
| 2079 | &pwzVDirSubPath, | ||
| 2080 | &fAppFound); | ||
| 2081 | ExitOnFailure(hr, "Error reading application element from config"); | ||
| 2082 | |||
| 2083 | if (!fAppFound) | ||
| 2084 | { | ||
| 2085 | // need application to add vDir | ||
| 2086 | hr = E_FILENOTFOUND; | ||
| 2087 | ExitOnFailure(hr, "Error application not found for create VDir"); | ||
| 2088 | } | ||
| 2089 | // | ||
| 2090 | // create the virDir | ||
| 2091 | // | ||
| 2092 | hr = CreateVdir(pAppElement, pwzVDirSubPath, pwzVDirPhyDir); | ||
| 2093 | ExitOnFailure(hr, "Failed to create vdir for application"); | ||
| 2094 | } | ||
| 2095 | else | ||
| 2096 | { | ||
| 2097 | hr = E_FILENOTFOUND; | ||
| 2098 | ExitOnFailure(hr, "IIS: site not found for create VDir"); | ||
| 2099 | } | ||
| 2100 | } | ||
| 2101 | else if (IIS_DELETE == iAction) | ||
| 2102 | { | ||
| 2103 | if (fSiteFound) | ||
| 2104 | { | ||
| 2105 | //have site get application | ||
| 2106 | hr = GetApplicationElementForVDir( pSiteElem, | ||
| 2107 | pwzVDirPath, | ||
| 2108 | &pAppElement, | ||
| 2109 | &pwzVDirSubPath, | ||
| 2110 | &fAppFound); | ||
| 2111 | ExitOnFailure(hr, "Error reading application from config") | ||
| 2112 | if (fAppFound) | ||
| 2113 | { | ||
| 2114 | //delete vdir | ||
| 2115 | hr = DeleteVdir(pAppElement, pwzVDirSubPath); | ||
| 2116 | ExitOnFailure(hr, "Unable to delete vdir for application"); | ||
| 2117 | } | ||
| 2118 | } | ||
| 2119 | } | ||
| 2120 | |||
| 2121 | LExit: | ||
| 2122 | ReleaseStr(pwzSiteName); | ||
| 2123 | ReleaseStr(pwzVDirPath); | ||
| 2124 | ReleaseStr(pwzVDirPhyDir); | ||
| 2125 | ReleaseObject(pSiteElem); | ||
| 2126 | ReleaseObject(pAppElement); | ||
| 2127 | ReleaseObject(pElement); | ||
| 2128 | |||
| 2129 | return hr; | ||
| 2130 | } | ||
| 2131 | |||
| 2132 | //------------------------------------------------------------------------------------------------- | ||
| 2133 | // IIS7Binding | ||
| 2134 | // Processes Bindings CA Data | ||
| 2135 | // | ||
| 2136 | // | ||
| 2137 | //------------------------------------------------------------------------------------------------- | ||
| 2138 | HRESULT IIS7Binding( | ||
| 2139 | __inout LPWSTR *ppwzCustomActionData, | ||
| 2140 | __in IAppHostWritableAdminManager *pAdminMgr) | ||
| 2141 | { | ||
| 2142 | HRESULT hr = S_OK; | ||
| 2143 | |||
| 2144 | int iAction = -1; | ||
| 2145 | BOOL fSiteFound = FALSE; | ||
| 2146 | |||
| 2147 | LPWSTR pwzSiteName = NULL; | ||
| 2148 | LPWSTR pwzProtocol = NULL; | ||
| 2149 | LPWSTR pwzInfo = NULL; | ||
| 2150 | |||
| 2151 | IAppHostElement *pSiteElem = NULL; | ||
| 2152 | |||
| 2153 | // Get Application action | ||
| 2154 | hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction); | ||
| 2155 | ExitOnFailure(hr, "Failed to read binding action"); | ||
| 2156 | |||
| 2157 | //get site key name | ||
| 2158 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 2159 | ExitOnFailure(hr, "Failed to read binding site name key"); | ||
| 2160 | |||
| 2161 | //get binding protocol | ||
| 2162 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzProtocol); | ||
| 2163 | ExitOnFailure(hr, "Failed to read binding protocol"); | ||
| 2164 | |||
| 2165 | //get binding info | ||
| 2166 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzInfo); | ||
| 2167 | ExitOnFailure(hr, "Failed to read binding info"); | ||
| 2168 | |||
| 2169 | //Get site if it exists | ||
| 2170 | hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound); | ||
| 2171 | ExitOnFailure(hr, "Failed to read sites from config"); | ||
| 2172 | |||
| 2173 | if (IIS_CREATE == iAction) | ||
| 2174 | { | ||
| 2175 | if (fSiteFound) | ||
| 2176 | { | ||
| 2177 | //add binding | ||
| 2178 | hr = CreateBinding(pSiteElem, pwzProtocol, pwzInfo); | ||
| 2179 | ExitOnFailure(hr, "Failed to create site binding"); | ||
| 2180 | } | ||
| 2181 | else | ||
| 2182 | { | ||
| 2183 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 2184 | ExitOnFailure(hr, "Site not found for create binding"); | ||
| 2185 | } | ||
| 2186 | } | ||
| 2187 | else if (IIS_DELETE == iAction) | ||
| 2188 | { | ||
| 2189 | if (fSiteFound) | ||
| 2190 | { | ||
| 2191 | //delete binding | ||
| 2192 | hr = DeleteBinding(pSiteElem, pwzProtocol, pwzInfo); | ||
| 2193 | ExitOnFailure(hr, "Failed to delete binding"); | ||
| 2194 | } | ||
| 2195 | } | ||
| 2196 | |||
| 2197 | LExit: | ||
| 2198 | ReleaseStr(pwzSiteName); | ||
| 2199 | ReleaseStr(pwzProtocol); | ||
| 2200 | ReleaseStr(pwzInfo); | ||
| 2201 | ReleaseObject(pSiteElem); | ||
| 2202 | |||
| 2203 | return hr; | ||
| 2204 | } | ||
| 2205 | //------------------------------------------------------------------------------------------------- | ||
| 2206 | // IIS7Binding | ||
| 2207 | // Processes WebLog CA Data | ||
| 2208 | // | ||
| 2209 | // | ||
| 2210 | //------------------------------------------------------------------------------------------------- | ||
| 2211 | HRESULT IIS7WebLog( | ||
| 2212 | __inout LPWSTR *ppwzCustomActionData, | ||
| 2213 | __in IAppHostWritableAdminManager *pAdminMgr) | ||
| 2214 | { | ||
| 2215 | HRESULT hr = S_OK; | ||
| 2216 | |||
| 2217 | BOOL fSiteFound = FALSE; | ||
| 2218 | |||
| 2219 | LPWSTR pwzSiteName = NULL; | ||
| 2220 | LPWSTR pwzLogFormat = NULL; | ||
| 2221 | |||
| 2222 | IAppHostElement *pSiteElem = NULL; | ||
| 2223 | |||
| 2224 | //get site key name | ||
| 2225 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 2226 | ExitOnFailure(hr, "Failed to read web log site name key"); | ||
| 2227 | |||
| 2228 | //get log format | ||
| 2229 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzLogFormat); | ||
| 2230 | ExitOnFailure(hr, "Failed to read web log protocol"); | ||
| 2231 | |||
| 2232 | //Get site if it exists | ||
| 2233 | hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound); | ||
| 2234 | ExitOnFailure(hr, "Failed to read web log sites from config"); | ||
| 2235 | |||
| 2236 | if (fSiteFound) | ||
| 2237 | { | ||
| 2238 | //add log format | ||
| 2239 | hr = CreateWebLog(pSiteElem, pwzLogFormat); | ||
| 2240 | ExitOnFailure(hr, "Failed to create weblog file format"); | ||
| 2241 | } | ||
| 2242 | else | ||
| 2243 | { | ||
| 2244 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 2245 | ExitOnFailure(hr, "Site not found for create weblog file format"); | ||
| 2246 | } | ||
| 2247 | |||
| 2248 | LExit: | ||
| 2249 | ReleaseStr(pwzSiteName); | ||
| 2250 | ReleaseStr(pwzLogFormat); | ||
| 2251 | ReleaseObject(pSiteElem); | ||
| 2252 | |||
| 2253 | return hr; | ||
| 2254 | } | ||
| 2255 | //------------------------------------------------------------------------------------------------- | ||
| 2256 | // IIS7AppPool | ||
| 2257 | // Processes AppPool CA Data | ||
| 2258 | // | ||
| 2259 | // | ||
| 2260 | //------------------------------------------------------------------------------------------------- | ||
| 2261 | HRESULT IIS7AppPool( | ||
| 2262 | __inout LPWSTR *ppwzCustomActionData, | ||
| 2263 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 2264 | ) | ||
| 2265 | { | ||
| 2266 | HRESULT hr = S_OK; | ||
| 2267 | |||
| 2268 | int iAction = -1; | ||
| 2269 | |||
| 2270 | LPWSTR pwzAppPoolName = NULL; | ||
| 2271 | |||
| 2272 | // Get AppPool action | ||
| 2273 | hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction); | ||
| 2274 | ExitOnFailure(hr, "Failed to read AppPool action"); | ||
| 2275 | |||
| 2276 | //get appPool name | ||
| 2277 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppPoolName); | ||
| 2278 | ExitOnFailure(hr, "Failed to read AppPool name key"); | ||
| 2279 | |||
| 2280 | switch (iAction) | ||
| 2281 | { | ||
| 2282 | case IIS_CREATE : | ||
| 2283 | { | ||
| 2284 | hr = CreateAppPool(ppwzCustomActionData, pAdminMgr, pwzAppPoolName); | ||
| 2285 | break; | ||
| 2286 | } | ||
| 2287 | case IIS_DELETE: | ||
| 2288 | { | ||
| 2289 | hr = DeleteAppPool(pAdminMgr, pwzAppPoolName); | ||
| 2290 | break; | ||
| 2291 | } | ||
| 2292 | default: | ||
| 2293 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for appPool"); | ||
| 2294 | break; | ||
| 2295 | } | ||
| 2296 | |||
| 2297 | LExit: | ||
| 2298 | ReleaseStr(pwzAppPoolName); | ||
| 2299 | return hr; | ||
| 2300 | } | ||
| 2301 | |||
| 2302 | //------------------------------------------------------------------------------------------------- | ||
| 2303 | // IIS7AppExtension | ||
| 2304 | // Processes AppExtension (config handlers) CA Data | ||
| 2305 | // | ||
| 2306 | // | ||
| 2307 | //------------------------------------------------------------------------------------------------- | ||
| 2308 | HRESULT IIS7AppExtension( | ||
| 2309 | __inout LPWSTR *ppwzCustomActionData, | ||
| 2310 | __in IAppHostWritableAdminManager *pAdminMgr) | ||
| 2311 | { | ||
| 2312 | HRESULT hr = S_OK; | ||
| 2313 | |||
| 2314 | LPWSTR pwzWebName = NULL; | ||
| 2315 | LPWSTR pwzWebRoot = NULL; | ||
| 2316 | LPWSTR pwzData = NULL; | ||
| 2317 | LPWSTR pwzConfigPath = NULL; | ||
| 2318 | LPWSTR pwzHandlerName = NULL; | ||
| 2319 | LPWSTR pwzPath = NULL; | ||
| 2320 | int iAction = -1; | ||
| 2321 | |||
| 2322 | IAppHostElement *pSection = NULL; | ||
| 2323 | IAppHostElement *pElement = NULL; | ||
| 2324 | IAppHostElementCollection *pCollection = NULL; | ||
| 2325 | |||
| 2326 | BOOL fFound = FALSE; | ||
| 2327 | DWORD cHandlers = 1000; | ||
| 2328 | |||
| 2329 | //get web name | ||
| 2330 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebName); | ||
| 2331 | ExitOnFailure(hr, "Failed to read appExt Web name key"); | ||
| 2332 | |||
| 2333 | //get root name | ||
| 2334 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebRoot); | ||
| 2335 | ExitOnFailure(hr, "Failed to read appExt Web name key"); | ||
| 2336 | |||
| 2337 | //Construct config root | ||
| 2338 | hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzWebName); | ||
| 2339 | ExitOnFailure(hr, "failed to format appext config path"); | ||
| 2340 | // | ||
| 2341 | //Do not append trailing '/' for default vDir | ||
| 2342 | // | ||
| 2343 | if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzWebRoot, -1, L"/", -1)) | ||
| 2344 | { | ||
| 2345 | hr = StrAllocConcat(&pwzConfigPath, L"/", 0); | ||
| 2346 | ExitOnFailure(hr, "failed to copy appext config path delim"); | ||
| 2347 | hr = StrAllocConcat(&pwzConfigPath, pwzWebRoot, 0); | ||
| 2348 | ExitOnFailure(hr, "failed to copy appext config path root name"); | ||
| 2349 | } | ||
| 2350 | //get admin handlers section at config path location tag | ||
| 2351 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HANDLERS_SECTION), pwzConfigPath, &pSection); | ||
| 2352 | ExitOnFailure(hr, "Failed get appext section"); | ||
| 2353 | |||
| 2354 | if (!pSection) | ||
| 2355 | { | ||
| 2356 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 2357 | ExitOnFailure(hr, "Failed get appext section object"); | ||
| 2358 | } | ||
| 2359 | |||
| 2360 | // Get AppExt action | ||
| 2361 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 2362 | ExitOnFailure(hr, "Failed to read appExt action"); | ||
| 2363 | |||
| 2364 | hr = pSection->get_Collection(&pCollection); | ||
| 2365 | ExitOnFailure(hr, "Failed get handlers collection for appext"); | ||
| 2366 | |||
| 2367 | while (IIS_APPEXT_END != iAction) | ||
| 2368 | { | ||
| 2369 | fFound = FALSE; | ||
| 2370 | |||
| 2371 | //Process property action | ||
| 2372 | switch (iAction) | ||
| 2373 | { | ||
| 2374 | case IIS_APPEXT : | ||
| 2375 | { | ||
| 2376 | // These IDs aren't really stable but this is stable enough to support repair since the MSI won't change | ||
| 2377 | hr = StrAllocFormatted(&pwzHandlerName, L"MsiCustom-%u", ++cHandlers); | ||
| 2378 | ExitOnFailure(hr, "Failed increment handler name"); | ||
| 2379 | |||
| 2380 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, pwzHandlerName, &pElement, NULL); | ||
| 2381 | ExitOnFailure(hr, "Failed to find mimemap extension"); | ||
| 2382 | |||
| 2383 | fFound = (NULL != pElement); | ||
| 2384 | if (!fFound) | ||
| 2385 | { | ||
| 2386 | //create new handler element | ||
| 2387 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement); | ||
| 2388 | ExitOnFailure(hr, "Failed get create handler element for appext"); | ||
| 2389 | |||
| 2390 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_NAME, pwzHandlerName); | ||
| 2391 | ExitOnFailure(hr, "Failed set appext name property"); | ||
| 2392 | } | ||
| 2393 | |||
| 2394 | //BUGBUG: For compat we are assuming these are all ISAPI MODULES so we are | ||
| 2395 | //setting the modules property to IsapiModule. | ||
| 2396 | //Currently can't deal with handlers of different module types. | ||
| 2397 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_MODULES, L"IsapiModule"); | ||
| 2398 | ExitOnFailure(hr, "Failed set site appExt path property"); | ||
| 2399 | |||
| 2400 | //get extension (path) | ||
| 2401 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2402 | ExitOnFailure(hr, "Failed to read appExt extension"); | ||
| 2403 | hr = StrAllocFormatted(&pwzPath, L"*.%s", pwzData); | ||
| 2404 | ExitOnFailure(hr, "Failed decorate appExt path"); | ||
| 2405 | //put property | ||
| 2406 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzPath); | ||
| 2407 | ExitOnFailure(hr, "Failed set site appExt path property"); | ||
| 2408 | |||
| 2409 | //get executable | ||
| 2410 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2411 | ExitOnFailure(hr, "Failed to read appExt executable"); | ||
| 2412 | //put property | ||
| 2413 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_EXECUTABLE, pwzData); | ||
| 2414 | ExitOnFailure(hr, "Failed set site appExt executable property"); | ||
| 2415 | |||
| 2416 | //get verbs | ||
| 2417 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2418 | ExitOnFailure(hr, "Failed to read appExt verbs"); | ||
| 2419 | //put property | ||
| 2420 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_VERBS, pwzData); | ||
| 2421 | ExitOnFailure(hr, "Failed set site appExt verbs property"); | ||
| 2422 | |||
| 2423 | break; | ||
| 2424 | } | ||
| 2425 | default: | ||
| 2426 | { | ||
| 2427 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for AppExt"); | ||
| 2428 | break; | ||
| 2429 | } | ||
| 2430 | } | ||
| 2431 | |||
| 2432 | if (!fFound) | ||
| 2433 | { | ||
| 2434 | // put handler element at beginning of list | ||
| 2435 | hr = pCollection->AddElement(pElement, 0); | ||
| 2436 | ExitOnFailure(hr, "Failed add handler element for appext"); | ||
| 2437 | } | ||
| 2438 | |||
| 2439 | ReleaseNullObject(pElement); | ||
| 2440 | |||
| 2441 | // Get AppExt action | ||
| 2442 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 2443 | ExitOnFailure(hr, "Failed to read AppPool Property action"); | ||
| 2444 | } | ||
| 2445 | |||
| 2446 | LExit: | ||
| 2447 | ReleaseStr(pwzWebName); | ||
| 2448 | ReleaseStr(pwzWebRoot); | ||
| 2449 | ReleaseStr(pwzData); | ||
| 2450 | ReleaseStr(pwzConfigPath); | ||
| 2451 | ReleaseStr(pwzHandlerName); | ||
| 2452 | ReleaseStr(pwzPath); | ||
| 2453 | ReleaseObject(pSection); | ||
| 2454 | ReleaseObject(pElement); | ||
| 2455 | ReleaseObject(pCollection); | ||
| 2456 | |||
| 2457 | return hr; | ||
| 2458 | } | ||
| 2459 | |||
| 2460 | //------------------------------------------------------------------------------------------------- | ||
| 2461 | // IIS7MimeMap | ||
| 2462 | // Processes Mime Map (config handlers) CA Data | ||
| 2463 | // | ||
| 2464 | // | ||
| 2465 | //------------------------------------------------------------------------------------------------- | ||
| 2466 | HRESULT IIS7MimeMap( | ||
| 2467 | __inout LPWSTR *ppwzCustomActionData, | ||
| 2468 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 2469 | ) | ||
| 2470 | { | ||
| 2471 | HRESULT hr = S_OK; | ||
| 2472 | LPWSTR pwzConfigPath = NULL; | ||
| 2473 | LPWSTR pwzWebName = NULL; | ||
| 2474 | LPWSTR pwzWebRoot = NULL; | ||
| 2475 | LPWSTR pwzData = NULL; | ||
| 2476 | int iAction = -1; | ||
| 2477 | |||
| 2478 | IAppHostElement *pSection = NULL; | ||
| 2479 | IAppHostElement *pElement = NULL; | ||
| 2480 | IAppHostElementCollection *pCollection = NULL; | ||
| 2481 | |||
| 2482 | BOOL fFound = FALSE; | ||
| 2483 | |||
| 2484 | //get web name | ||
| 2485 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebName); | ||
| 2486 | ExitOnFailure(hr, "Failed to read mime map Web name key"); | ||
| 2487 | |||
| 2488 | //get vdir root name | ||
| 2489 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebRoot); | ||
| 2490 | ExitOnFailure(hr, "Failed to read vdir root name key"); | ||
| 2491 | |||
| 2492 | //Construct config root | ||
| 2493 | hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzWebName); | ||
| 2494 | ExitOnFailure(hr, "failed to format mime map config path web name"); | ||
| 2495 | // | ||
| 2496 | //Do not append trailing '/' for default vDir | ||
| 2497 | // | ||
| 2498 | if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzWebRoot, -1, L"/", -1)) | ||
| 2499 | { | ||
| 2500 | hr = StrAllocConcat(&pwzConfigPath, L"/", 0); | ||
| 2501 | ExitOnFailure(hr, "failed to copy appext config path delim"); | ||
| 2502 | hr = StrAllocConcat(&pwzConfigPath, pwzWebRoot, 0); | ||
| 2503 | ExitOnFailure(hr, "failed to copy appext config path root name"); | ||
| 2504 | } | ||
| 2505 | |||
| 2506 | //get admin section <staticContent> at config path location tag | ||
| 2507 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection); | ||
| 2508 | ExitOnFailure(hr, "Failed get staticContent section for mimemap"); | ||
| 2509 | |||
| 2510 | if (!pSection) | ||
| 2511 | { | ||
| 2512 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 2513 | ExitOnFailure(hr, "Failed get staticContent section object"); | ||
| 2514 | } | ||
| 2515 | |||
| 2516 | // Get mimemap action | ||
| 2517 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 2518 | ExitOnFailure(hr, "Failed to read mimemap action"); | ||
| 2519 | |||
| 2520 | hr = pSection->get_Collection(&pCollection); | ||
| 2521 | ExitOnFailure(hr, "Failed get staticContent collection for mimemap"); | ||
| 2522 | |||
| 2523 | while (IIS_MIMEMAP_END != iAction) | ||
| 2524 | { | ||
| 2525 | //Process property action | ||
| 2526 | switch (iAction) | ||
| 2527 | { | ||
| 2528 | case IIS_MIMEMAP : | ||
| 2529 | { | ||
| 2530 | //get extension | ||
| 2531 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2532 | ExitOnFailure(hr, "Failed to read mimemap extension"); | ||
| 2533 | |||
| 2534 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_MIMEMAP, IIS_CONFIG_FILEEXT, pwzData, &pElement, NULL); | ||
| 2535 | ExitOnFailure(hr, "Failed to find mimemap extension"); | ||
| 2536 | fFound = (NULL != pElement); | ||
| 2537 | |||
| 2538 | if (!fFound) | ||
| 2539 | { | ||
| 2540 | //create new mimeMap element | ||
| 2541 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_MIMEMAP), &pElement); | ||
| 2542 | ExitOnFailure(hr, "Failed get create MimeMap element"); | ||
| 2543 | } | ||
| 2544 | |||
| 2545 | //put property | ||
| 2546 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_FILEEXT, pwzData); | ||
| 2547 | ExitOnFailure(hr, "Failed set mimemap extension property"); | ||
| 2548 | |||
| 2549 | //get type | ||
| 2550 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2551 | ExitOnFailure(hr, "Failed to read mimemap type"); | ||
| 2552 | //put property | ||
| 2553 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_MIMETYPE, pwzData); | ||
| 2554 | ExitOnFailure(hr, "Failed set mimemap type property"); | ||
| 2555 | |||
| 2556 | break; | ||
| 2557 | } | ||
| 2558 | default: | ||
| 2559 | { | ||
| 2560 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for mimeMap"); | ||
| 2561 | break; | ||
| 2562 | } | ||
| 2563 | } | ||
| 2564 | |||
| 2565 | if (!fFound) | ||
| 2566 | { | ||
| 2567 | // put mimeMap element at beginning of list | ||
| 2568 | hr = pCollection->AddElement(pElement, -1); | ||
| 2569 | ExitOnFailure(hr, "Failed add mimemap"); | ||
| 2570 | } | ||
| 2571 | |||
| 2572 | // Get AppExt action | ||
| 2573 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 2574 | ExitOnFailure(hr, "Failed to read mimemap action"); | ||
| 2575 | |||
| 2576 | ReleaseNullObject(pElement); | ||
| 2577 | } | ||
| 2578 | |||
| 2579 | LExit: | ||
| 2580 | ReleaseStr(pwzConfigPath); | ||
| 2581 | ReleaseStr(pwzWebName); | ||
| 2582 | ReleaseStr(pwzWebRoot); | ||
| 2583 | ReleaseStr(pwzData); | ||
| 2584 | ReleaseObject(pSection); | ||
| 2585 | ReleaseObject(pElement); | ||
| 2586 | ReleaseObject(pCollection); | ||
| 2587 | |||
| 2588 | return hr; | ||
| 2589 | } | ||
| 2590 | |||
| 2591 | //------------------------------------------------------------------------------------------------- | ||
| 2592 | // IIS7DirProperties | ||
| 2593 | // ProcessesVdir Properties CA Data | ||
| 2594 | // | ||
| 2595 | // | ||
| 2596 | //------------------------------------------------------------------------------------------------- | ||
| 2597 | HRESULT IIS7DirProperties( | ||
| 2598 | __inout LPWSTR *ppwzCustomActionData, | ||
| 2599 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 2600 | ) | ||
| 2601 | { | ||
| 2602 | HRESULT hr = S_OK; | ||
| 2603 | WCHAR wcTime[60]; | ||
| 2604 | LPWSTR pwzConfigPath = NULL; | ||
| 2605 | LPWSTR pwzWebName = NULL; | ||
| 2606 | LPWSTR pwzWebRoot = NULL; | ||
| 2607 | LPWSTR pwzData = NULL; | ||
| 2608 | int iAction = -1; | ||
| 2609 | int iData = 0; | ||
| 2610 | DWORD dwData = 0; | ||
| 2611 | |||
| 2612 | IAppHostElement *pSection = NULL; | ||
| 2613 | IAppHostElement *pElement = NULL; | ||
| 2614 | IAppHostElementCollection *pCollection = NULL; | ||
| 2615 | |||
| 2616 | //get web name | ||
| 2617 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebName); | ||
| 2618 | ExitOnFailure(hr, "Failed to read DirProp Web name key"); | ||
| 2619 | |||
| 2620 | //get vdir root name | ||
| 2621 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebRoot); | ||
| 2622 | ExitOnFailure(hr, "Failed to read DirProp Web name key"); | ||
| 2623 | |||
| 2624 | //Construct config root | ||
| 2625 | hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzWebName); | ||
| 2626 | ExitOnFailure(hr, "failed to format mime map config path web name"); | ||
| 2627 | // | ||
| 2628 | //Do not append trailing '/' for default vDir | ||
| 2629 | // | ||
| 2630 | if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzWebRoot, -1, L"/", -1)) | ||
| 2631 | { | ||
| 2632 | hr = StrAllocConcat(&pwzConfigPath, L"/", 0); | ||
| 2633 | ExitOnFailure(hr, "failed to copy appext config path delim"); | ||
| 2634 | hr = StrAllocConcat(&pwzConfigPath, pwzWebRoot, 0); | ||
| 2635 | ExitOnFailure(hr, "failed to copy appext config path root name"); | ||
| 2636 | } | ||
| 2637 | |||
| 2638 | // Get DirProps action | ||
| 2639 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 2640 | ExitOnFailure(hr, "Failed to read DirProps action"); | ||
| 2641 | |||
| 2642 | while (IIS_DIRPROP_END != iAction) | ||
| 2643 | { | ||
| 2644 | //Process property action | ||
| 2645 | switch (iAction) | ||
| 2646 | { | ||
| 2647 | case IIS_DIRPROP_ACCESS : | ||
| 2648 | { | ||
| 2649 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 2650 | ExitOnFailure(hr, "Failed to read DirProps access"); | ||
| 2651 | //iData contains bit flags for <handlers accessPolicy=""> | ||
| 2652 | //no translation required | ||
| 2653 | //get admin section at config path location tag | ||
| 2654 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HANDLERS_SECTION), pwzConfigPath, &pSection); | ||
| 2655 | ExitOnFailure(hr, "Failed get handlers section for DirProp"); | ||
| 2656 | if (!pSection) | ||
| 2657 | { | ||
| 2658 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 2659 | ExitOnFailure(hr, "Failed get handlers section object for DirProps"); | ||
| 2660 | } | ||
| 2661 | dwData = iData; | ||
| 2662 | hr = Iis7PutPropertyInteger( pSection, L"accessPolicy", dwData); | ||
| 2663 | ExitOnFailure(hr, "Failed set accessPolicy for DirProps"); | ||
| 2664 | ReleaseNullObject(pSection); | ||
| 2665 | break; | ||
| 2666 | } | ||
| 2667 | case IIS_DIRPROP_USER : | ||
| 2668 | { | ||
| 2669 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2670 | ExitOnFailure(hr, "Failed to read DirProps user"); | ||
| 2671 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/anonymousAuthentication"), pwzConfigPath, &pSection); | ||
| 2672 | ExitOnFailure(hr, "Failed get AnonymousAuthentication section for DirProp"); | ||
| 2673 | hr = Iis7PutPropertyString( pSection, IIS_CONFIG_USERNAME, pwzData); | ||
| 2674 | ExitOnFailure(hr, "Failed set accessPolicy for DirProps"); | ||
| 2675 | ReleaseNullObject(pSection); | ||
| 2676 | break; | ||
| 2677 | } | ||
| 2678 | case IIS_DIRPROP_PWD : | ||
| 2679 | { | ||
| 2680 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2681 | ExitOnFailure(hr, "Failed to read DirProps pwd"); | ||
| 2682 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/anonymousAuthentication"), pwzConfigPath, &pSection); | ||
| 2683 | ExitOnFailure(hr, "Failed get AnonymousAuthentication section for DirProp"); | ||
| 2684 | hr = Iis7PutPropertyString( pSection, IIS_CONFIG_PASSWORD, pwzData); | ||
| 2685 | ExitOnFailure(hr, "Failed set accessPolicy for DirProps"); | ||
| 2686 | ReleaseNullObject(pSection); | ||
| 2687 | break; | ||
| 2688 | } | ||
| 2689 | case IIS_DIRPROP_DEFDOCS : | ||
| 2690 | { | ||
| 2691 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2692 | ExitOnFailure(hr, "Failed to read DirProps def doc"); | ||
| 2693 | hr = SetDirPropDefDoc(pAdminMgr, pwzConfigPath, pwzData); | ||
| 2694 | ExitOnFailure(hr, "Failed to set DirProps Default Documents"); | ||
| 2695 | break; | ||
| 2696 | } | ||
| 2697 | case IIS_DIRPROP_AUTH : | ||
| 2698 | { | ||
| 2699 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 2700 | ExitOnFailure(hr, "Failed to read DirProps auth"); | ||
| 2701 | //iData contains bit flags for /security/authentication/<...> | ||
| 2702 | // Anonymous = 1 | ||
| 2703 | // Basic = 2 | ||
| 2704 | // Windows = 4 | ||
| 2705 | // Digest =16 | ||
| 2706 | // Passport =64 *not supported | ||
| 2707 | //translation required from bit map to section | ||
| 2708 | // E.G security/authentication/windowsAuthentication [property enabled true|false] | ||
| 2709 | dwData= iData; | ||
| 2710 | hr = SetDirPropAuthentications(pAdminMgr, pwzConfigPath, dwData); | ||
| 2711 | ExitOnFailure(hr, "Failed set Authentication for DirProps"); | ||
| 2712 | break; | ||
| 2713 | } | ||
| 2714 | case IIS_DIRPROP_SSLFLAGS : | ||
| 2715 | { | ||
| 2716 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 2717 | ExitOnFailure(hr, "Failed to read DirProps sslFlags"); | ||
| 2718 | //iData contains bit flags for /security/access sslFlags | ||
| 2719 | //no translation required | ||
| 2720 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/access"), pwzConfigPath, &pSection); | ||
| 2721 | ExitOnFailure(hr, "Failed get security/access section for DirProp"); | ||
| 2722 | dwData = iData; | ||
| 2723 | hr = Iis7PutPropertyInteger( pSection, L"sslFlags", dwData); | ||
| 2724 | ExitOnFailure(hr, "Failed set security/access for DirProps"); | ||
| 2725 | ReleaseNullObject(pSection); | ||
| 2726 | break; | ||
| 2727 | } | ||
| 2728 | case IIS_DIRPROP_AUTHPROVID : | ||
| 2729 | { | ||
| 2730 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2731 | ExitOnFailure(hr, "Failed to read DirProps auth provider"); | ||
| 2732 | hr = SetDirPropAuthProvider(pAdminMgr, pwzConfigPath, pwzData); | ||
| 2733 | ExitOnFailure(hr, "Failed to set DirProps auth provider"); | ||
| 2734 | break; | ||
| 2735 | } | ||
| 2736 | case IIS_DIRPROP_ASPERROR: | ||
| 2737 | { | ||
| 2738 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 2739 | ExitOnFailure(hr, "Failed to read DirProps aspDetailedError"); | ||
| 2740 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ASP_SECTION), pwzConfigPath, &pSection); | ||
| 2741 | ExitOnFailure(hr, "Failed get asp section for DirProp"); | ||
| 2742 | hr = Iis7PutPropertyBool(pSection, IIS_CONFIG_SCRIPTERROR, iData); | ||
| 2743 | ExitOnFailure(hr, "Failed to set DirProps aspDetailedError"); | ||
| 2744 | ReleaseNullObject(pSection); | ||
| 2745 | break; | ||
| 2746 | } | ||
| 2747 | case IIS_DIRPROP_HTTPEXPIRES: | ||
| 2748 | { | ||
| 2749 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2750 | ExitOnFailure(hr, "Failed to read DirProps httpExpires provider"); | ||
| 2751 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection); | ||
| 2752 | ExitOnFailure(hr, "Failed get staticContent section for DirProp"); | ||
| 2753 | hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_CLIENTCACHE), &pElement); | ||
| 2754 | ExitOnFailure(hr, "Failed to get clientCache element"); | ||
| 2755 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_HTTPEXPIRES, pwzData); | ||
| 2756 | ExitOnFailure(hr, "Failed to set clientCache httpExpires value"); | ||
| 2757 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CACHECONTROLMODE, IIS_CONFIG_USEEXPIRES); | ||
| 2758 | ExitOnFailure(hr, "Failed to set clientCache cacheControlMode value"); | ||
| 2759 | ReleaseNullObject(pSection); | ||
| 2760 | ReleaseNullObject(pElement); | ||
| 2761 | break; | ||
| 2762 | } | ||
| 2763 | case IIS_DIRPROP_MAXAGE: | ||
| 2764 | { | ||
| 2765 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 2766 | ExitOnFailure(hr, "Failed to read DirProps httpExpires provider"); | ||
| 2767 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection); | ||
| 2768 | ExitOnFailure(hr, "Failed get staticContent section for DirProp"); | ||
| 2769 | hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_CLIENTCACHE), &pElement); | ||
| 2770 | ExitOnFailure(hr, "Failed to get clientCache element"); | ||
| 2771 | *wcTime = '\0'; | ||
| 2772 | ConvSecToDHMS(iData, wcTime, countof(wcTime)); | ||
| 2773 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_MAXAGE, wcTime); | ||
| 2774 | ExitOnFailure(hr, "Failed to set clientCache maxAge value"); | ||
| 2775 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CACHECONTROLMODE, IIS_CONFIG_USEMAXAGE); | ||
| 2776 | ExitOnFailure(hr, "Failed to set clientCache cacheControlMode value"); | ||
| 2777 | ReleaseNullObject(pSection); | ||
| 2778 | ReleaseNullObject(pElement); | ||
| 2779 | break; | ||
| 2780 | } | ||
| 2781 | case IIS_DIRPROP_CACHECUST: | ||
| 2782 | { | ||
| 2783 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 2784 | ExitOnFailure(hr, "Failed to read DirProps cacheControlCustom"); | ||
| 2785 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection); | ||
| 2786 | ExitOnFailure(hr, "Failed get staticContent section for DirProp"); | ||
| 2787 | hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_CLIENTCACHE), &pElement); | ||
| 2788 | ExitOnFailure(hr, "Failed to get clientCache element"); | ||
| 2789 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CACHECUST, pwzData); | ||
| 2790 | ExitOnFailure(hr, "Failed to set clientCache cacheControlCustom value"); | ||
| 2791 | ReleaseNullObject(pSection); | ||
| 2792 | ReleaseNullObject(pElement); | ||
| 2793 | break; | ||
| 2794 | } | ||
| 2795 | case IIS_DIRPROP_NOCUSTERROR: | ||
| 2796 | { | ||
| 2797 | //no value, if have ID tag write clear to system.webServer/httpErrors | ||
| 2798 | //error collection | ||
| 2799 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPERRORS_SECTION), pwzConfigPath, &pSection); | ||
| 2800 | ExitOnFailure(hr, "Failed get httperrors section for DirProp"); | ||
| 2801 | hr = pSection->get_Collection(&pCollection); | ||
| 2802 | ExitOnFailure(hr, "Failed get error collection for DirProp"); | ||
| 2803 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pElement); | ||
| 2804 | ExitOnFailure(hr, "Failed to create clear element for error collection for DirProp"); | ||
| 2805 | hr = pCollection->AddElement(pElement); | ||
| 2806 | ExitOnFailure(hr, "Failed to add lear element for error collection for DirProp"); | ||
| 2807 | ReleaseNullObject(pSection); | ||
| 2808 | ReleaseNullObject(pElement); | ||
| 2809 | break; | ||
| 2810 | } | ||
| 2811 | case IIS_DIRPROP_LOGVISITS: | ||
| 2812 | { | ||
| 2813 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 2814 | ExitOnFailure(hr, "Failed to read DirProps logVisits"); | ||
| 2815 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPLOGGING_SECTION), pwzConfigPath, &pSection); | ||
| 2816 | ExitOnFailure(hr, "Failed get httpLogging section for DirProp"); | ||
| 2817 | hr = Iis7PutPropertyBool(pSection, IIS_CONFIG_DONTLOG, iData); | ||
| 2818 | ExitOnFailure(hr, "Failed to set DirProps aspDetailedError"); | ||
| 2819 | ReleaseNullObject(pSection); | ||
| 2820 | break; | ||
| 2821 | } | ||
| 2822 | default: | ||
| 2823 | { | ||
| 2824 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for WebDirProperties"); | ||
| 2825 | break; | ||
| 2826 | } | ||
| 2827 | } | ||
| 2828 | |||
| 2829 | // Get AppExt action | ||
| 2830 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 2831 | ExitOnFailure(hr, "Failed to read DirProps Property action"); | ||
| 2832 | } | ||
| 2833 | LExit: | ||
| 2834 | ReleaseStr(pwzConfigPath); | ||
| 2835 | ReleaseStr(pwzWebName); | ||
| 2836 | ReleaseStr(pwzWebRoot); | ||
| 2837 | ReleaseStr(pwzData); | ||
| 2838 | ReleaseObject(pSection); | ||
| 2839 | ReleaseObject(pElement); | ||
| 2840 | ReleaseObject(pCollection); | ||
| 2841 | |||
| 2842 | return hr; | ||
| 2843 | } | ||
| 2844 | |||
| 2845 | //------------------------------------------------------------------------------------------------- | ||
| 2846 | // IIS7SslBinding | ||
| 2847 | // ProcessesVdir Properties CA Data | ||
| 2848 | // | ||
| 2849 | // | ||
| 2850 | //------------------------------------------------------------------------------------------------- | ||
| 2851 | HRESULT IIS7SslBinding( | ||
| 2852 | __inout LPWSTR *ppwzCustomActionData, | ||
| 2853 | __in IAppHostWritableAdminManager *pAdminMgr | ||
| 2854 | ) | ||
| 2855 | { | ||
| 2856 | HRESULT hr = S_OK; | ||
| 2857 | int iAction = -1; | ||
| 2858 | BOOL fSiteFound = FALSE; | ||
| 2859 | |||
| 2860 | LPWSTR pwzSiteName = NULL; | ||
| 2861 | LPWSTR pwzStoreName = NULL; | ||
| 2862 | LPWSTR pwzEncodedCertificateHash = NULL; | ||
| 2863 | |||
| 2864 | IAppHostElement *pSiteElem = NULL; | ||
| 2865 | |||
| 2866 | // Get Application action | ||
| 2867 | hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction); | ||
| 2868 | ExitOnFailure(hr, "Failed to read binding action"); | ||
| 2869 | |||
| 2870 | //get site key name | ||
| 2871 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); | ||
| 2872 | ExitOnFailure(hr, "Failed to read binding site name key"); | ||
| 2873 | |||
| 2874 | //get binding protocol | ||
| 2875 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzStoreName); | ||
| 2876 | ExitOnFailure(hr, "Failed to read binding protocol"); | ||
| 2877 | |||
| 2878 | //get binding info | ||
| 2879 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzEncodedCertificateHash); | ||
| 2880 | ExitOnFailure(hr, "Failed to read binding info"); | ||
| 2881 | |||
| 2882 | //Get site if it exists | ||
| 2883 | hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound); | ||
| 2884 | ExitOnFailure(hr, "Failed to read sites from config"); | ||
| 2885 | |||
| 2886 | if (IIS_CREATE == iAction) | ||
| 2887 | { | ||
| 2888 | if (fSiteFound) | ||
| 2889 | { | ||
| 2890 | //add SSL cert to binding | ||
| 2891 | hr = CreateSslBinding(pSiteElem, pwzStoreName, pwzEncodedCertificateHash); | ||
| 2892 | ExitOnFailure(hr, "Failed to create site binding"); | ||
| 2893 | } | ||
| 2894 | else | ||
| 2895 | { | ||
| 2896 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 2897 | ExitOnFailure(hr, "Site not found for create binding"); | ||
| 2898 | } | ||
| 2899 | } | ||
| 2900 | else if (IIS_DELETE == iAction) | ||
| 2901 | { | ||
| 2902 | if (fSiteFound) | ||
| 2903 | { | ||
| 2904 | //delete binding | ||
| 2905 | hr = DeleteSslBinding(pSiteElem, pwzStoreName, pwzEncodedCertificateHash); | ||
| 2906 | ExitOnFailure(hr, "Failed to delete binding"); | ||
| 2907 | } | ||
| 2908 | } | ||
| 2909 | |||
| 2910 | LExit: | ||
| 2911 | ReleaseStr(pwzSiteName); | ||
| 2912 | ReleaseStr(pwzStoreName); | ||
| 2913 | ReleaseStr(pwzEncodedCertificateHash); | ||
| 2914 | ReleaseObject(pSiteElem); | ||
| 2915 | |||
| 2916 | return hr; | ||
| 2917 | } | ||
| 2918 | |||
| 2919 | //------------------------------------------------------------------------------------------------- | ||
| 2920 | // Helper Functions | ||
| 2921 | // | ||
| 2922 | // | ||
| 2923 | // | ||
| 2924 | //------------------------------------------------------------------------------------------------- | ||
| 2925 | |||
| 2926 | static HRESULT GetNextAvailableSiteId( | ||
| 2927 | IAppHostElementCollection *pCollection, | ||
| 2928 | DWORD *plSiteId | ||
| 2929 | ) | ||
| 2930 | { | ||
| 2931 | HRESULT hr = S_OK; | ||
| 2932 | IAppHostElement *pElement = NULL; | ||
| 2933 | IAppHostProperty *pProperty = NULL; | ||
| 2934 | |||
| 2935 | DWORD cSites; | ||
| 2936 | DWORD plNextAvailSite = 0; | ||
| 2937 | VARIANT vPropValue; | ||
| 2938 | VARIANT vtIndex; | ||
| 2939 | |||
| 2940 | VariantInit(&vPropValue); | ||
| 2941 | VariantInit(&vtIndex); | ||
| 2942 | |||
| 2943 | *plSiteId = 0; | ||
| 2944 | |||
| 2945 | hr = pCollection->get_Count(&cSites); | ||
| 2946 | ExitOnFailure(hr, "Failed get sites collection count"); | ||
| 2947 | |||
| 2948 | vtIndex.vt = VT_UI4; | ||
| 2949 | for (DWORD i = 0; i < cSites; ++i) | ||
| 2950 | { | ||
| 2951 | vtIndex.ulVal = i; | ||
| 2952 | hr = pCollection->get_Item(vtIndex , &pElement); | ||
| 2953 | ExitOnFailure(hr, "Failed get sites collection item"); | ||
| 2954 | |||
| 2955 | hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_ID), &pProperty); | ||
| 2956 | ExitOnFailure(hr, "Failed get site property"); | ||
| 2957 | |||
| 2958 | hr = pProperty->get_Value(&vPropValue); | ||
| 2959 | ExitOnFailure(hr, "Failed get site property value"); | ||
| 2960 | |||
| 2961 | *plSiteId = vPropValue.lVal; | ||
| 2962 | if (*plSiteId > plNextAvailSite) | ||
| 2963 | { | ||
| 2964 | plNextAvailSite = *plSiteId; | ||
| 2965 | } | ||
| 2966 | ReleaseNullObject(pElement); | ||
| 2967 | ReleaseNullObject(pProperty); | ||
| 2968 | } | ||
| 2969 | *plSiteId = ++plNextAvailSite; | ||
| 2970 | |||
| 2971 | LExit: | ||
| 2972 | ReleaseVariant(vPropValue); | ||
| 2973 | ReleaseVariant(vtIndex); | ||
| 2974 | |||
| 2975 | ReleaseObject(pElement); | ||
| 2976 | ReleaseObject(pProperty); | ||
| 2977 | |||
| 2978 | return hr; | ||
| 2979 | } | ||
| 2980 | |||
| 2981 | static HRESULT GetSiteElement( | ||
| 2982 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 2983 | LPCWSTR swSiteName, | ||
| 2984 | IAppHostElement **ppSiteElement, | ||
| 2985 | BOOL* fFound | ||
| 2986 | ) | ||
| 2987 | { | ||
| 2988 | HRESULT hr = S_OK; | ||
| 2989 | IAppHostElement *pSites = NULL; | ||
| 2990 | IAppHostElementCollection *pCollection = NULL; | ||
| 2991 | |||
| 2992 | *fFound = FALSE; | ||
| 2993 | |||
| 2994 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_SITES_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSites); | ||
| 2995 | ExitOnFailure(hr, "Failed get sites section"); | ||
| 2996 | ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object"); | ||
| 2997 | |||
| 2998 | hr = pSites->get_Collection(&pCollection); | ||
| 2999 | ExitOnFailure(hr, "Failed get sites collection"); | ||
| 3000 | |||
| 3001 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, swSiteName, ppSiteElement, NULL); | ||
| 3002 | ExitOnFailure(hr, "Failed to find site %ls", swSiteName); | ||
| 3003 | |||
| 3004 | *fFound = ppSiteElement != NULL && *ppSiteElement != NULL; | ||
| 3005 | |||
| 3006 | LExit: | ||
| 3007 | ReleaseObject(pSites); | ||
| 3008 | ReleaseObject(pCollection); | ||
| 3009 | |||
| 3010 | return hr; | ||
| 3011 | } | ||
| 3012 | |||
| 3013 | static HRESULT GetApplicationElement( IAppHostElement *pSiteElement, | ||
| 3014 | LPCWSTR swAppPath, | ||
| 3015 | IAppHostElement **ppAppElement, | ||
| 3016 | BOOL* fFound) | ||
| 3017 | { | ||
| 3018 | HRESULT hr = S_OK; | ||
| 3019 | IAppHostElementCollection *pCollection = NULL; | ||
| 3020 | |||
| 3021 | *fFound = FALSE; | ||
| 3022 | |||
| 3023 | hr = pSiteElement->get_Collection( &pCollection); | ||
| 3024 | ExitOnFailure(hr, "Failed get site app collection"); | ||
| 3025 | |||
| 3026 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_APPLICATION, IIS_CONFIG_PATH, swAppPath, ppAppElement, NULL); | ||
| 3027 | ExitOnFailure(hr, "Failed to find app %ls", swAppPath); | ||
| 3028 | |||
| 3029 | *fFound = ppAppElement != NULL && *ppAppElement != NULL; | ||
| 3030 | |||
| 3031 | LExit: | ||
| 3032 | ReleaseObject(pCollection); | ||
| 3033 | |||
| 3034 | return hr; | ||
| 3035 | } | ||
| 3036 | |||
| 3037 | static HRESULT GetApplicationElementForVDir( IAppHostElement *pSiteElement, | ||
| 3038 | LPCWSTR pwzVDirPath, | ||
| 3039 | IAppHostElement **ppAppElement, | ||
| 3040 | LPCWSTR *ppwzVDirSubPath, | ||
| 3041 | BOOL* fFound) | ||
| 3042 | { | ||
| 3043 | HRESULT hr = S_OK; | ||
| 3044 | IAppHostElementCollection *pCollection = NULL; | ||
| 3045 | LPWSTR pwzAppPath = NULL; | ||
| 3046 | *fFound = FALSE; | ||
| 3047 | *ppwzVDirSubPath = NULL; | ||
| 3048 | |||
| 3049 | hr = pSiteElement->get_Collection( &pCollection); | ||
| 3050 | ExitOnFailure(hr, "Failed get site app collection"); | ||
| 3051 | |||
| 3052 | // Start with full path | ||
| 3053 | int iLastPathIndex = lstrlenW(pwzVDirPath) - 1; | ||
| 3054 | hr = StrAllocString(&pwzAppPath, pwzVDirPath, 0); | ||
| 3055 | ExitOnFailure(hr, "Failed allocate application path"); | ||
| 3056 | |||
| 3057 | for (int iSubPathIndex = iLastPathIndex; (iSubPathIndex >= 0) && (!*fFound); --iSubPathIndex) | ||
| 3058 | { | ||
| 3059 | // We are looking at the full path, or at a directory boundary, or at the root | ||
| 3060 | if (iSubPathIndex == iLastPathIndex || | ||
| 3061 | '/' == pwzAppPath[iSubPathIndex] || | ||
| 3062 | 0 == iSubPathIndex) | ||
| 3063 | { | ||
| 3064 | // break the path if needed | ||
| 3065 | if ('/' == pwzAppPath[iSubPathIndex]) | ||
| 3066 | { | ||
| 3067 | pwzAppPath[iSubPathIndex] = '\0'; | ||
| 3068 | } | ||
| 3069 | |||
| 3070 | // Special case for root path, need an empty app path | ||
| 3071 | LPCWSTR pwzAppSearchPath = 0 == iSubPathIndex ? L"/" : pwzAppPath; | ||
| 3072 | |||
| 3073 | // Try to find an app with the specified path | ||
| 3074 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_APPLICATION, IIS_CONFIG_PATH, pwzAppSearchPath, ppAppElement, NULL); | ||
| 3075 | ExitOnFailure(hr, "Failed to search for app %ls", pwzAppSearchPath); | ||
| 3076 | *fFound = ppAppElement != NULL && *ppAppElement != NULL; | ||
| 3077 | |||
| 3078 | if (*fFound) | ||
| 3079 | { | ||
| 3080 | // set return value for sub path | ||
| 3081 | // special case for app path == vdir path, need an empty subpath. | ||
| 3082 | *ppwzVDirSubPath = (iSubPathIndex == iLastPathIndex) ? L"/" : pwzVDirPath + iSubPathIndex; | ||
| 3083 | } | ||
| 3084 | } | ||
| 3085 | } | ||
| 3086 | |||
| 3087 | LExit: | ||
| 3088 | ReleaseObject(pCollection); | ||
| 3089 | ReleaseStr(pwzAppPath); | ||
| 3090 | |||
| 3091 | return hr; | ||
| 3092 | } | ||
| 3093 | |||
| 3094 | static HRESULT CreateSite( | ||
| 3095 | __in IAppHostElementCollection *pCollection, | ||
| 3096 | __in LPCWSTR swSiteName, | ||
| 3097 | __out IAppHostElement **pSiteElement | ||
| 3098 | ) | ||
| 3099 | { | ||
| 3100 | HRESULT hr = S_OK; | ||
| 3101 | IAppHostElement *pNewElement = NULL; | ||
| 3102 | |||
| 3103 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_SITE), &pNewElement); | ||
| 3104 | ExitOnFailure(hr, "Failed create site element"); | ||
| 3105 | |||
| 3106 | hr = Iis7PutPropertyString(pNewElement, IIS_CONFIG_NAME, swSiteName); | ||
| 3107 | ExitOnFailure(hr, "Failed set site name property"); | ||
| 3108 | |||
| 3109 | DWORD lSiteId = 0; | ||
| 3110 | hr = GetNextAvailableSiteId(pCollection, &lSiteId); | ||
| 3111 | ExitOnFailure(hr, "Failed get next site id"); | ||
| 3112 | |||
| 3113 | Iis7PutPropertyInteger(pNewElement, IIS_CONFIG_ID, lSiteId); | ||
| 3114 | ExitOnFailure(hr, "Failed set site id property"); | ||
| 3115 | |||
| 3116 | hr = pCollection->AddElement(pNewElement); | ||
| 3117 | ExitOnFailure(hr, "Failed add site element"); | ||
| 3118 | |||
| 3119 | *pSiteElement = pNewElement; | ||
| 3120 | pNewElement = NULL; | ||
| 3121 | |||
| 3122 | LExit: | ||
| 3123 | ReleaseObject(pNewElement); | ||
| 3124 | |||
| 3125 | return hr; | ||
| 3126 | } | ||
| 3127 | |||
| 3128 | static HRESULT CreateApplication( | ||
| 3129 | IAppHostElement *pSiteElement, | ||
| 3130 | LPCWSTR swAppPath, | ||
| 3131 | IAppHostElement **pAppElement | ||
| 3132 | ) | ||
| 3133 | { | ||
| 3134 | HRESULT hr = S_OK; | ||
| 3135 | IAppHostElement *pNewElement = NULL; | ||
| 3136 | IAppHostElementCollection *pCollection = NULL; | ||
| 3137 | |||
| 3138 | hr = pSiteElement->get_Collection(&pCollection); | ||
| 3139 | ExitOnFailure(hr, "Failed get application collection"); | ||
| 3140 | |||
| 3141 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_APPLICATION), &pNewElement); | ||
| 3142 | ExitOnFailure(hr, "Failed get application element"); | ||
| 3143 | |||
| 3144 | hr = Iis7PutPropertyString(pNewElement, IIS_CONFIG_PATH, swAppPath); | ||
| 3145 | ExitOnFailure(hr, "Failed set application path property"); | ||
| 3146 | |||
| 3147 | hr = pCollection->AddElement(pNewElement); | ||
| 3148 | ExitOnFailure(hr, "Failed add application to collection"); | ||
| 3149 | |||
| 3150 | *pAppElement = pNewElement; | ||
| 3151 | pNewElement = NULL; | ||
| 3152 | |||
| 3153 | LExit: | ||
| 3154 | ReleaseObject(pCollection); | ||
| 3155 | ReleaseObject(pNewElement); | ||
| 3156 | |||
| 3157 | return hr; | ||
| 3158 | } | ||
| 3159 | |||
| 3160 | static HRESULT DeleteApplication( | ||
| 3161 | IAppHostElement *pSiteElement, | ||
| 3162 | LPCWSTR swAppPath | ||
| 3163 | ) | ||
| 3164 | { | ||
| 3165 | HRESULT hr = S_OK; | ||
| 3166 | IAppHostElementCollection *pCollection = NULL; | ||
| 3167 | |||
| 3168 | hr = pSiteElement->get_Collection(&pCollection); | ||
| 3169 | ExitOnFailure(hr, "Failed get application collection"); | ||
| 3170 | |||
| 3171 | hr = DeleteCollectionElement(pCollection, IIS_CONFIG_APPLICATION, IIS_CONFIG_PATH, swAppPath); | ||
| 3172 | ExitOnFailure(hr, "Failed to delete website"); | ||
| 3173 | |||
| 3174 | LExit: | ||
| 3175 | ReleaseObject(pCollection); | ||
| 3176 | |||
| 3177 | return hr; | ||
| 3178 | } | ||
| 3179 | |||
| 3180 | static HRESULT SetAppPool( | ||
| 3181 | IAppHostElement *pAppElement, | ||
| 3182 | LPCWSTR pwzAppPool | ||
| 3183 | ) | ||
| 3184 | { | ||
| 3185 | HRESULT hr = S_OK; | ||
| 3186 | |||
| 3187 | if (*pwzAppPool != 0) | ||
| 3188 | { | ||
| 3189 | hr = Iis7PutPropertyString(pAppElement, IIS_CONFIG_APPPOOL, pwzAppPool); | ||
| 3190 | ExitOnFailure(hr, "Failed set application appPool property"); | ||
| 3191 | } | ||
| 3192 | LExit: | ||
| 3193 | return hr; | ||
| 3194 | } | ||
| 3195 | |||
| 3196 | static HRESULT CreateVdir( | ||
| 3197 | IAppHostElement *pAppElement, | ||
| 3198 | LPCWSTR pwzVDirPath, | ||
| 3199 | LPCWSTR pwzVDirPhyDir | ||
| 3200 | ) | ||
| 3201 | { | ||
| 3202 | HRESULT hr = S_OK; | ||
| 3203 | IAppHostElement *pElement = NULL; | ||
| 3204 | IAppHostElementCollection *pCollection = NULL; | ||
| 3205 | BOOL fFound; | ||
| 3206 | |||
| 3207 | hr = pAppElement->get_Collection(&pCollection); | ||
| 3208 | ExitOnFailure(hr, "Failed get application VDir collection"); | ||
| 3209 | |||
| 3210 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_VDIR, IIS_CONFIG_PATH, pwzVDirPath, &pElement, NULL); | ||
| 3211 | ExitOnFailure(hr, "Failed while finding virtualDir"); | ||
| 3212 | fFound = (NULL != pElement); | ||
| 3213 | |||
| 3214 | if (!fFound) | ||
| 3215 | { | ||
| 3216 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_VDIR), &pElement); | ||
| 3217 | ExitOnFailure(hr, "Failed create application VDir collection"); | ||
| 3218 | |||
| 3219 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzVDirPath); | ||
| 3220 | ExitOnFailure(hr, "Failed set VDir path property"); | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PHYSPATH, pwzVDirPhyDir); | ||
| 3224 | ExitOnFailure(hr, "Failed set VDir phys path property"); | ||
| 3225 | |||
| 3226 | if (!fFound) | ||
| 3227 | { | ||
| 3228 | hr = pCollection->AddElement(pElement); | ||
| 3229 | ExitOnFailure(hr, "Failed add application VDir element"); | ||
| 3230 | } | ||
| 3231 | |||
| 3232 | LExit: | ||
| 3233 | ReleaseObject(pCollection); | ||
| 3234 | ReleaseObject(pElement); | ||
| 3235 | |||
| 3236 | return hr; | ||
| 3237 | } | ||
| 3238 | |||
| 3239 | static HRESULT DeleteVdir( | ||
| 3240 | IAppHostElement *pAppElement, | ||
| 3241 | LPCWSTR pwzVDirPath | ||
| 3242 | ) | ||
| 3243 | { | ||
| 3244 | HRESULT hr = S_OK; | ||
| 3245 | IAppHostElementCollection *pCollection = NULL; | ||
| 3246 | |||
| 3247 | hr = pAppElement->get_Collection(&pCollection); | ||
| 3248 | ExitOnFailure(hr, "Failed get application VDir collection"); | ||
| 3249 | |||
| 3250 | hr = DeleteCollectionElement(pCollection, IIS_CONFIG_VDIR, IIS_CONFIG_PATH, pwzVDirPath); | ||
| 3251 | ExitOnFailure(hr, "Failed to delete vdir"); | ||
| 3252 | |||
| 3253 | LExit: | ||
| 3254 | ReleaseObject(pCollection); | ||
| 3255 | |||
| 3256 | return hr; | ||
| 3257 | } | ||
| 3258 | |||
| 3259 | static HRESULT CreateBinding( | ||
| 3260 | IAppHostElement *pSiteElem, | ||
| 3261 | LPCWSTR pwzProtocol, | ||
| 3262 | LPCWSTR pwzInfo | ||
| 3263 | ) | ||
| 3264 | { | ||
| 3265 | HRESULT hr = S_OK; | ||
| 3266 | IAppHostChildElementCollection *pChildElems = NULL; | ||
| 3267 | IAppHostElement *pBindings = NULL; | ||
| 3268 | IAppHostElement *pBindingElement = NULL; | ||
| 3269 | IAppHostElementCollection *pCollection = NULL; | ||
| 3270 | |||
| 3271 | VARIANT vtProp; | ||
| 3272 | |||
| 3273 | VariantInit(&vtProp); | ||
| 3274 | |||
| 3275 | hr = pSiteElem->get_ChildElements(&pChildElems); | ||
| 3276 | ExitOnFailure(hr, "Failed get site child elements collection"); | ||
| 3277 | |||
| 3278 | vtProp.vt = VT_BSTR; | ||
| 3279 | vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS); | ||
| 3280 | hr = pChildElems->get_Item(vtProp, &pBindings); | ||
| 3281 | ExitOnFailure(hr, "Failed get bindings element"); | ||
| 3282 | ReleaseVariant(vtProp); | ||
| 3283 | |||
| 3284 | hr = pBindings->get_Collection(&pCollection); | ||
| 3285 | ExitOnFailure(hr, "Failed get bindings collection"); | ||
| 3286 | |||
| 3287 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_BINDING), &pBindingElement); | ||
| 3288 | ExitOnFailure(hr, "Failed get binding element"); | ||
| 3289 | |||
| 3290 | hr = Iis7PutPropertyString(pBindingElement, IIS_CONFIG_PROTOCOL, pwzProtocol); | ||
| 3291 | ExitOnFailure(hr, "Failed set binding protocol property"); | ||
| 3292 | |||
| 3293 | hr = Iis7PutPropertyString(pBindingElement, IIS_CONFIG_BINDINGINFO, pwzInfo); | ||
| 3294 | ExitOnFailure(hr, "Failed set binding information property"); | ||
| 3295 | |||
| 3296 | hr = pCollection->AddElement(pBindingElement); | ||
| 3297 | if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) | ||
| 3298 | { | ||
| 3299 | //Eat this error. Binding is there and nothing to repair since | ||
| 3300 | //identity == protocol + info so all is OK | ||
| 3301 | hr = S_OK; | ||
| 3302 | } | ||
| 3303 | else | ||
| 3304 | { | ||
| 3305 | ExitOnFailure(hr, "Failed add binding to site"); | ||
| 3306 | } | ||
| 3307 | |||
| 3308 | LExit: | ||
| 3309 | ReleaseVariant(vtProp); | ||
| 3310 | |||
| 3311 | ReleaseObject(pCollection); | ||
| 3312 | ReleaseObject(pChildElems); | ||
| 3313 | ReleaseObject(pBindingElement); | ||
| 3314 | ReleaseObject(pBindings); | ||
| 3315 | |||
| 3316 | return hr; | ||
| 3317 | } | ||
| 3318 | static HRESULT CreateWebLog( | ||
| 3319 | IAppHostElement *pSiteElem, | ||
| 3320 | LPCWSTR pwzFormat | ||
| 3321 | ) | ||
| 3322 | { | ||
| 3323 | HRESULT hr = S_OK; | ||
| 3324 | IAppHostChildElementCollection *pChildElems = NULL; | ||
| 3325 | IAppHostElement *pLogFile = NULL; | ||
| 3326 | |||
| 3327 | VARIANT vtProp; | ||
| 3328 | |||
| 3329 | VariantInit(&vtProp); | ||
| 3330 | |||
| 3331 | hr = pSiteElem->get_ChildElements(&pChildElems); | ||
| 3332 | ExitOnFailure(hr, "Failed get site child elements collection"); | ||
| 3333 | |||
| 3334 | vtProp.vt = VT_BSTR; | ||
| 3335 | vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_WEBLOG); | ||
| 3336 | hr = pChildElems->get_Item(vtProp, &pLogFile); | ||
| 3337 | ExitOnFailure(hr, "Failed get logfile element"); | ||
| 3338 | ReleaseVariant(vtProp); | ||
| 3339 | |||
| 3340 | if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzFormat, -1, L"none", -1)) | ||
| 3341 | { | ||
| 3342 | hr = Iis7PutPropertyString(pLogFile, IIS_CONFIG_LOGFORMAT, pwzFormat); | ||
| 3343 | ExitOnFailure(hr, "Failed set logfile format property"); | ||
| 3344 | hr = Iis7PutPropertyString(pLogFile, IIS_CONFIG_ENABLED, IIS_CONFIG_TRUE); | ||
| 3345 | ExitOnFailure(hr, "Failed set logfile enabled property"); | ||
| 3346 | } | ||
| 3347 | else | ||
| 3348 | { | ||
| 3349 | hr = Iis7PutPropertyString(pLogFile, IIS_CONFIG_ENABLED, IIS_CONFIG_FALSE); | ||
| 3350 | ExitOnFailure(hr, "Failed set logfile enabled property"); | ||
| 3351 | } | ||
| 3352 | |||
| 3353 | LExit: | ||
| 3354 | ReleaseVariant(vtProp); | ||
| 3355 | |||
| 3356 | ReleaseObject(pLogFile); | ||
| 3357 | ReleaseObject(pChildElems); | ||
| 3358 | |||
| 3359 | return hr; | ||
| 3360 | } | ||
| 3361 | |||
| 3362 | static HRESULT DeleteBinding( | ||
| 3363 | IAppHostElement* /*pSiteElem*/, | ||
| 3364 | LPCWSTR /*pwzProtocol*/, | ||
| 3365 | LPCWSTR /*pwzInfo*/ | ||
| 3366 | ) | ||
| 3367 | { | ||
| 3368 | HRESULT hr = S_OK; | ||
| 3369 | // | ||
| 3370 | //this isn't supported right now, we should support this for the SiteSearch scenario | ||
| 3371 | return hr; | ||
| 3372 | } | ||
| 3373 | |||
| 3374 | struct SCA_SSLBINDINGINFO | ||
| 3375 | { | ||
| 3376 | IIS7_APPHOSTELEMENTCOMPARISON comparison; | ||
| 3377 | LPCWSTR pwzStoreName; | ||
| 3378 | LPCWSTR pwzEncodedCertificateHash; | ||
| 3379 | HRESULT hr; | ||
| 3380 | }; | ||
| 3381 | |||
| 3382 | static BOOL AddSslCertificateToBindingCallback(IAppHostElement *pBindingElement, LPVOID pContext) | ||
| 3383 | { | ||
| 3384 | HRESULT hr = S_OK; | ||
| 3385 | VARIANT vtProp; | ||
| 3386 | VariantInit(&vtProp); | ||
| 3387 | SCA_SSLBINDINGINFO* pBindingInfo = (SCA_SSLBINDINGINFO*)pContext; | ||
| 3388 | IAppHostMethodCollection *pAppHostMethodCollection = NULL; | ||
| 3389 | IAppHostMethod *pAddSslMethod = NULL; | ||
| 3390 | IAppHostMethodInstance *pAddSslMethodInstance = NULL; | ||
| 3391 | IAppHostElement *pAddSslInput = NULL; | ||
| 3392 | int iWsaError = 0; | ||
| 3393 | WSADATA wsaData = {}; | ||
| 3394 | BOOL fWsaInitialized = FALSE; | ||
| 3395 | |||
| 3396 | // IIS's AddSslCertificate doesn't initialize WinSock on 2008 before using it to parse the IP | ||
| 3397 | // Initialize before calling to workaround the failure. | ||
| 3398 | iWsaError = WSAStartup(MAKEWORD(2, 2), &wsaData); | ||
| 3399 | if (0 != iWsaError) | ||
| 3400 | { | ||
| 3401 | ExitOnWin32Error(iWsaError, hr, "Failed to initialize WinSock"); | ||
| 3402 | } | ||
| 3403 | |||
| 3404 | fWsaInitialized = TRUE; | ||
| 3405 | |||
| 3406 | if (Iis7IsMatchingAppHostElement(pBindingElement, &pBindingInfo->comparison)) | ||
| 3407 | { | ||
| 3408 | hr = pBindingElement->get_Methods(&pAppHostMethodCollection); | ||
| 3409 | ExitOnFailure(hr, "failed to get binding method collection"); | ||
| 3410 | |||
| 3411 | hr = Iis7FindAppHostMethod(pAppHostMethodCollection, L"AddSslCertificate", &pAddSslMethod, NULL); | ||
| 3412 | if (FAILED(hr)) | ||
| 3413 | { | ||
| 3414 | WcaLog(LOGMSG_STANDARD, "The AddSslCertificate method is not supported by the binding element, SSL certificate will not be associated with the website"); | ||
| 3415 | ExitFunction(); | ||
| 3416 | } | ||
| 3417 | |||
| 3418 | pAddSslMethod->CreateInstance(&pAddSslMethodInstance); | ||
| 3419 | ExitOnFailure(hr, "failed to create an instance of AddSslCertificate method"); | ||
| 3420 | |||
| 3421 | pAddSslMethodInstance->get_Input(&pAddSslInput); | ||
| 3422 | ExitOnFailure(hr, "failed to get input element of AddSslCertificate method"); | ||
| 3423 | |||
| 3424 | Iis7PutPropertyString(pAddSslInput, IIS_CONFIG_CERTIFICATESTORENAME, pBindingInfo->pwzStoreName); | ||
| 3425 | ExitOnFailure(hr, "failed to set certificateStoreName input parameter of AddSslCertificate method"); | ||
| 3426 | |||
| 3427 | Iis7PutPropertyString(pAddSslInput, IIS_CONFIG_CERTIFICATEHASH, pBindingInfo->pwzEncodedCertificateHash); | ||
| 3428 | ExitOnFailure(hr, "failed to set certificateHash input parameter of AddSslCertificate method"); | ||
| 3429 | |||
| 3430 | hr = pAddSslMethodInstance->Execute(); | ||
| 3431 | ExitOnFailure(hr, "failed to execute AddSslCertificate method"); | ||
| 3432 | } | ||
| 3433 | LExit: | ||
| 3434 | pBindingInfo->hr = hr; | ||
| 3435 | ReleaseObject(pAppHostMethodCollection); | ||
| 3436 | ReleaseObject(pAddSslMethod); | ||
| 3437 | ReleaseObject(pAddSslMethodInstance); | ||
| 3438 | ReleaseObject(pAddSslInput); | ||
| 3439 | if (fWsaInitialized) | ||
| 3440 | { | ||
| 3441 | WSACleanup(); | ||
| 3442 | } | ||
| 3443 | |||
| 3444 | return FAILED(hr); | ||
| 3445 | } | ||
| 3446 | |||
| 3447 | static HRESULT CreateSslBinding( IAppHostElement *pSiteElem, LPCWSTR pwzStoreName, LPCWSTR pwzEncodedCertificateHash) | ||
| 3448 | { | ||
| 3449 | HRESULT hr = S_OK; | ||
| 3450 | IAppHostChildElementCollection *pChildElems = NULL; | ||
| 3451 | IAppHostElement *pBindingsElement = NULL; | ||
| 3452 | IAppHostElementCollection *pBindingsCollection = NULL; | ||
| 3453 | SCA_SSLBINDINGINFO bindingInfo = {}; | ||
| 3454 | VARIANT vtProp; | ||
| 3455 | VariantInit(&vtProp); | ||
| 3456 | |||
| 3457 | hr = pSiteElem->get_ChildElements(&pChildElems); | ||
| 3458 | ExitOnFailure(hr, "Failed get site child elements collection"); | ||
| 3459 | |||
| 3460 | vtProp.vt = VT_BSTR; | ||
| 3461 | vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS); | ||
| 3462 | hr = pChildElems->get_Item(vtProp, &pBindingsElement); | ||
| 3463 | ExitOnFailure(hr, "Failed get bindings element"); | ||
| 3464 | ReleaseVariant(vtProp); | ||
| 3465 | |||
| 3466 | hr = pBindingsElement->get_Collection(&pBindingsCollection); | ||
| 3467 | ExitOnFailure(hr, "Failed get bindings collection"); | ||
| 3468 | |||
| 3469 | bindingInfo.comparison.sczElementName = IIS_CONFIG_BINDING; | ||
| 3470 | bindingInfo.comparison.sczAttributeName = IIS_CONFIG_PROTOCOL; | ||
| 3471 | vtProp.vt = VT_BSTR; | ||
| 3472 | vtProp.bstrVal = ::SysAllocString(L"https"); | ||
| 3473 | bindingInfo.comparison.pvAttributeValue = &vtProp; | ||
| 3474 | bindingInfo.pwzStoreName = pwzStoreName; | ||
| 3475 | bindingInfo.pwzEncodedCertificateHash = pwzEncodedCertificateHash; | ||
| 3476 | |||
| 3477 | // Our current IISWebSiteCertificates schema does not allow specification of the website binding | ||
| 3478 | // to associate the certificate with. For now just associate it with all secure bindings. | ||
| 3479 | |||
| 3480 | hr = Iis7EnumAppHostElements(pBindingsCollection, AddSslCertificateToBindingCallback, &bindingInfo, NULL, NULL); | ||
| 3481 | ExitOnFailure(hr, "Failed to enumerate bindings collection"); | ||
| 3482 | hr = bindingInfo.hr; | ||
| 3483 | ExitOnFailure(hr, "Failed to add ssl binding"); | ||
| 3484 | |||
| 3485 | LExit: | ||
| 3486 | ReleaseVariant(vtProp); | ||
| 3487 | |||
| 3488 | ReleaseObject(pChildElems); | ||
| 3489 | ReleaseObject(pBindingsElement); | ||
| 3490 | ReleaseObject(pBindingsCollection); | ||
| 3491 | |||
| 3492 | return hr; | ||
| 3493 | } | ||
| 3494 | |||
| 3495 | static HRESULT DeleteSslBinding( | ||
| 3496 | IAppHostElement * /*pSiteElem*/, | ||
| 3497 | LPCWSTR /*pwzStoreName*/, | ||
| 3498 | LPCWSTR /*pwzEncodedCertificateHash*/ | ||
| 3499 | ) | ||
| 3500 | { | ||
| 3501 | HRESULT hr = S_OK; | ||
| 3502 | // | ||
| 3503 | //this isn't supported right now, we should support this for the SiteSearch scenario | ||
| 3504 | return hr; | ||
| 3505 | } | ||
| 3506 | |||
| 3507 | static HRESULT DeleteAppPool( IAppHostWritableAdminManager *pAdminMgr, | ||
| 3508 | LPCWSTR swAppPoolName) | ||
| 3509 | { | ||
| 3510 | HRESULT hr = S_OK; | ||
| 3511 | IAppHostElement *pAppPools = NULL; | ||
| 3512 | IAppHostElementCollection *pCollection = NULL; | ||
| 3513 | |||
| 3514 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_APPPOOL_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pAppPools); | ||
| 3515 | ExitOnFailure(hr, "Failed get AppPools section"); | ||
| 3516 | ExitOnNull(pAppPools, hr, E_UNEXPECTED, "Failed get appPools section object"); | ||
| 3517 | |||
| 3518 | hr = pAppPools->get_Collection( &pCollection); | ||
| 3519 | ExitOnFailure(hr, "Failed get AppPools collection"); | ||
| 3520 | |||
| 3521 | hr = DeleteCollectionElement(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, swAppPoolName); | ||
| 3522 | ExitOnFailure(hr, "Failed to delete app pool %ls", swAppPoolName); | ||
| 3523 | |||
| 3524 | LExit: | ||
| 3525 | ReleaseObject(pAppPools); | ||
| 3526 | ReleaseObject(pCollection); | ||
| 3527 | |||
| 3528 | return hr; | ||
| 3529 | } | ||
| 3530 | |||
| 3531 | static HRESULT CreateAppPool( | ||
| 3532 | __inout LPWSTR *ppwzCustomActionData, | ||
| 3533 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 3534 | LPCWSTR swAppPoolName | ||
| 3535 | ) | ||
| 3536 | { | ||
| 3537 | HRESULT hr = S_OK; | ||
| 3538 | IAppHostElement *pAppPools = NULL; | ||
| 3539 | IAppHostElement *pAppPoolElement = NULL; | ||
| 3540 | IAppHostElement *pElement = NULL; | ||
| 3541 | IAppHostElement *pElement2 = NULL; | ||
| 3542 | IAppHostElement *pElement3 = NULL; | ||
| 3543 | IAppHostElementCollection *pCollection = NULL; | ||
| 3544 | IAppHostElementCollection *pCollection2 = NULL; | ||
| 3545 | int iAction = -1; | ||
| 3546 | int iData = 0; | ||
| 3547 | LPWSTR pwzData = NULL; | ||
| 3548 | WCHAR wcData[512]; | ||
| 3549 | WCHAR wcTime[60]; | ||
| 3550 | BOOL fFound = FALSE; | ||
| 3551 | |||
| 3552 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_APPPOOL_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pAppPools); | ||
| 3553 | ExitOnFailure(hr, "Failed get AppPools section"); | ||
| 3554 | ExitOnNull(pAppPools, hr, ERROR_FILE_NOT_FOUND, "Failed get AppPools section object"); | ||
| 3555 | |||
| 3556 | hr = pAppPools->get_Collection( &pCollection); | ||
| 3557 | ExitOnFailure(hr, "Failed get AppPools collection"); | ||
| 3558 | |||
| 3559 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, swAppPoolName, &pAppPoolElement, NULL); | ||
| 3560 | ExitOnFailure(hr, "Failed find AppPool element"); | ||
| 3561 | fFound = (NULL != pAppPoolElement); | ||
| 3562 | |||
| 3563 | if (!fFound) | ||
| 3564 | { | ||
| 3565 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pAppPoolElement); | ||
| 3566 | ExitOnFailure(hr, "Failed create AppPool element"); | ||
| 3567 | } | ||
| 3568 | |||
| 3569 | hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_NAME, swAppPoolName); | ||
| 3570 | ExitOnFailure(hr, "Failed set AppPool name property"); | ||
| 3571 | |||
| 3572 | //For WiX II6 /ABO compat we will default managedPipelineMode="Classic" | ||
| 3573 | hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_PIPELINEMODE, L"Classic"); | ||
| 3574 | ExitOnFailure(hr, "Failed set AppPool managedPipelineMode property"); | ||
| 3575 | //For WiX II6 /ABO compat we will be hardcoding autostart="true" | ||
| 3576 | hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_APPPOOL_AUTO, L"true"); | ||
| 3577 | ExitOnFailure(hr, "Failed set AppPool autoStart property"); | ||
| 3578 | |||
| 3579 | if (!fFound) | ||
| 3580 | { | ||
| 3581 | hr = pCollection->AddElement(pAppPoolElement); | ||
| 3582 | ExitOnFailure(hr, "Failed to add appPool element"); | ||
| 3583 | } | ||
| 3584 | |||
| 3585 | // Get AppPool Property action | ||
| 3586 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 3587 | ExitOnFailure(hr, "Failed to read AppPool Property action"); | ||
| 3588 | while (IIS_APPPOOL_END != iAction) | ||
| 3589 | { | ||
| 3590 | //Process property action | ||
| 3591 | switch (iAction) | ||
| 3592 | { | ||
| 3593 | case IIS_APPPOOL_RECYCLE_MIN : | ||
| 3594 | { | ||
| 3595 | // /recycling / periodicRestart | time | ||
| 3596 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3597 | ExitOnFailure(hr, "Failed to read AppPool recycle min"); | ||
| 3598 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement); | ||
| 3599 | ExitOnFailure(hr, "Failed to get AppPool recycling element"); | ||
| 3600 | hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2); | ||
| 3601 | ExitOnFailure(hr, "Failed to get AppPool periodicRestart element"); | ||
| 3602 | *wcTime = '\0'; | ||
| 3603 | ConvSecToHMS(iData * 60, wcTime, countof(wcTime)); | ||
| 3604 | hr = Iis7PutPropertyString(pElement2, IIS_CONFIG_TIME, wcTime); | ||
| 3605 | ExitOnFailure(hr, "Failed to set AppPool periodicRestart time value"); | ||
| 3606 | ReleaseNullObject(pElement); | ||
| 3607 | ReleaseNullObject(pElement2); | ||
| 3608 | break; | ||
| 3609 | } | ||
| 3610 | case IIS_APPPOOL_RECYCLE_REQ : | ||
| 3611 | { | ||
| 3612 | // /recycling / periodicRestart | requests | ||
| 3613 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3614 | ExitOnFailure(hr, "Failed to read AppPool recycle req"); | ||
| 3615 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement); | ||
| 3616 | ExitOnFailure(hr, "Failed to get AppPool recycling element"); | ||
| 3617 | hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2); | ||
| 3618 | ExitOnFailure(hr, "Failed to get AppPool periodicRestart element"); | ||
| 3619 | hr = Iis7PutPropertyInteger(pElement2, IIS_CONFIG_REQUESTS, iData); | ||
| 3620 | ExitOnFailure(hr, "Failed to set AppPool periodicRestart time value"); | ||
| 3621 | ReleaseNullObject(pElement); | ||
| 3622 | ReleaseNullObject(pElement2); | ||
| 3623 | break; | ||
| 3624 | } | ||
| 3625 | case IIS_APPPOOL_RECYCLE_TIMES : | ||
| 3626 | { | ||
| 3627 | // /recycling / periodicRestart | schedule | ||
| 3628 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 3629 | ExitOnFailure(hr, "Failed to read AppPool recycle times"); | ||
| 3630 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement); | ||
| 3631 | ExitOnFailure(hr, "Failed to get AppPool recycling element"); | ||
| 3632 | hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2); | ||
| 3633 | ExitOnFailure(hr, "Failed to get AppPool periodicRestart element"); | ||
| 3634 | hr = pElement2->GetElementByName(ScopeBSTR(IIS_CONFIG_SCHEDULE), &pElement3); | ||
| 3635 | ExitOnFailure(hr, "Failed to get AppPool schedule element"); | ||
| 3636 | hr = pElement3->get_Collection(&pCollection2); | ||
| 3637 | ExitOnFailure(hr, "Failed to get AppPool schedule collection"); | ||
| 3638 | |||
| 3639 | WCHAR wcDelim[] = L","; | ||
| 3640 | const WCHAR *wszToken = NULL; | ||
| 3641 | WCHAR *wszNextToken = NULL; | ||
| 3642 | wszToken = wcstok_s( pwzData, wcDelim, &wszNextToken); | ||
| 3643 | |||
| 3644 | while (wszToken) | ||
| 3645 | { | ||
| 3646 | *wcData = '\0'; | ||
| 3647 | hr = ::StringCchCopyW(wcData, countof(wcData), wszToken); | ||
| 3648 | ExitOnFailure(hr, "failed to copy AppPool schedule"); | ||
| 3649 | hr = ::StringCchCatW(wcData, countof(wcData), L":00"); | ||
| 3650 | ExitOnFailure(hr, "failed to append AppPool schedule"); | ||
| 3651 | |||
| 3652 | hr = pCollection2->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement3); | ||
| 3653 | ExitOnFailure(hr, "Failed to create AppPool schedule element"); | ||
| 3654 | |||
| 3655 | hr = Iis7PutPropertyString(pElement3, IIS_CONFIG_VALUE, wcData); | ||
| 3656 | ExitOnFailure(hr, "Failed to set AppPool schedule value"); | ||
| 3657 | |||
| 3658 | hr = pCollection2->AddElement(pElement3); | ||
| 3659 | if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) | ||
| 3660 | { | ||
| 3661 | //Eat this error, recycle time already exists NBD | ||
| 3662 | hr = S_OK; | ||
| 3663 | } | ||
| 3664 | ExitOnFailure(hr, "Failed to add win auth providers element"); | ||
| 3665 | ReleaseNullObject(pElement3); | ||
| 3666 | wszToken = wcstok_s( NULL, wcDelim, &wszNextToken); | ||
| 3667 | } | ||
| 3668 | ReleaseNullObject(pElement); | ||
| 3669 | ReleaseNullObject(pElement2); | ||
| 3670 | ReleaseNullObject(pElement3); | ||
| 3671 | ReleaseNullObject(pCollection2); | ||
| 3672 | break; | ||
| 3673 | } | ||
| 3674 | case IIS_APPPOOL_RECYCLE_VIRMEM : | ||
| 3675 | { | ||
| 3676 | // /recycling / periodicRestart | memory | ||
| 3677 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3678 | ExitOnFailure(hr, "Failed to read AppPool recycle vir memory"); | ||
| 3679 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement); | ||
| 3680 | ExitOnFailure(hr, "Failed to get AppPool recycling element"); | ||
| 3681 | hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2); | ||
| 3682 | ExitOnFailure(hr, "Failed to get AppPool periodicRestart element"); | ||
| 3683 | hr = Iis7PutPropertyInteger(pElement2, IIS_CONFIG_MEMORY, iData); | ||
| 3684 | ExitOnFailure(hr, "Failed to set AppPool periodicRestart memory"); | ||
| 3685 | ReleaseNullObject(pElement); | ||
| 3686 | ReleaseNullObject(pElement2); | ||
| 3687 | break; | ||
| 3688 | } | ||
| 3689 | case IIS_APPPOOL_RECYCLE_PRIVMEM : | ||
| 3690 | { | ||
| 3691 | // /recycling / periodicRestart | privateMemory | ||
| 3692 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3693 | ExitOnFailure(hr, "Failed to read AppPool recycle priv mem"); | ||
| 3694 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement); | ||
| 3695 | ExitOnFailure(hr, "Failed to get AppPool recycling element"); | ||
| 3696 | hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2); | ||
| 3697 | ExitOnFailure(hr, "Failed to get AppPool periodicRestart element"); | ||
| 3698 | hr = Iis7PutPropertyInteger(pElement2, IIS_CONFIG_PRIVMEMORY, iData); | ||
| 3699 | ExitOnFailure(hr, "Failed to set AppPool periodicRestart private memory"); | ||
| 3700 | ReleaseNullObject(pElement); | ||
| 3701 | ReleaseNullObject(pElement2); | ||
| 3702 | break; | ||
| 3703 | } | ||
| 3704 | case IIS_APPPOOL_RECYCLE_IDLTIMEOUT : | ||
| 3705 | { | ||
| 3706 | // /processModel | idleTimeout | ||
| 3707 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3708 | ExitOnFailure(hr, "Failed to read AppPool idle timeout"); | ||
| 3709 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement); | ||
| 3710 | ExitOnFailure(hr, "Failed to get AppPool processModel element"); | ||
| 3711 | *wcTime = '\0'; | ||
| 3712 | ConvSecToHMS(iData * 60, wcTime, countof(wcTime)); | ||
| 3713 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDLETIMEOUT, wcTime); | ||
| 3714 | ExitOnFailure(hr, "Failed to set AppPool processModel idle timeout value"); | ||
| 3715 | ReleaseNullObject(pElement); | ||
| 3716 | break; | ||
| 3717 | } | ||
| 3718 | case IIS_APPPOOL_RECYCLE_QUEUELIMIT : | ||
| 3719 | { | ||
| 3720 | // /applicationPools | queueLength | ||
| 3721 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3722 | ExitOnFailure(hr, "Failed to read AppPool recycle queue limit"); | ||
| 3723 | hr = Iis7PutPropertyInteger(pAppPoolElement, IIS_CONFIG_QUEUELENGTH, iData); | ||
| 3724 | ExitOnFailure(hr, "Failed to set AppPool recycle queue limit value"); | ||
| 3725 | break; | ||
| 3726 | } | ||
| 3727 | case IIS_APPPOOL_MAXPROCESS : | ||
| 3728 | { | ||
| 3729 | // /processModel | maxProcesses | ||
| 3730 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3731 | ExitOnFailure(hr, "Failed to read AppPool max processes"); | ||
| 3732 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement); | ||
| 3733 | ExitOnFailure(hr, "Failed to get AppPool processModel element"); | ||
| 3734 | hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_MAXWRKPROCESSES, iData); | ||
| 3735 | ExitOnFailure(hr, "Failed to set AppPool processModel maxProcesses value"); | ||
| 3736 | ReleaseNullObject(pElement); | ||
| 3737 | break; | ||
| 3738 | } | ||
| 3739 | case IIS_APPPOOL_IDENTITY : | ||
| 3740 | { | ||
| 3741 | //"LocalSystem" 0 | ||
| 3742 | //"LocalService" 1 | ||
| 3743 | //"NetworkService" 2 | ||
| 3744 | //"SpecificUser" 3 | ||
| 3745 | //"ApplicationPoolIdentity" 4 | ||
| 3746 | // /processModel | identityType | ||
| 3747 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3748 | ExitOnFailure(hr, "Failed to read AppPool identity"); | ||
| 3749 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement); | ||
| 3750 | ExitOnFailure(hr, "Failed to get AppPool processModel element"); | ||
| 3751 | if (iData == 0) | ||
| 3752 | { | ||
| 3753 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_LOCALSYSTEM); | ||
| 3754 | } | ||
| 3755 | else if (iData == 1) | ||
| 3756 | { | ||
| 3757 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_LOCALSERVICE); | ||
| 3758 | } | ||
| 3759 | else if (iData == 2) | ||
| 3760 | { | ||
| 3761 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_NETWORKSERVICE); | ||
| 3762 | } | ||
| 3763 | else if (iData == 3) | ||
| 3764 | { | ||
| 3765 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_SPECIFICUSER); | ||
| 3766 | } | ||
| 3767 | else if (iData == 4) | ||
| 3768 | { | ||
| 3769 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_APPLICATIONPOOLIDENTITY); | ||
| 3770 | } | ||
| 3771 | ExitOnFailure(hr, "Failed to set AppPool processModel identityType value"); | ||
| 3772 | ReleaseNullObject(pElement); | ||
| 3773 | break; | ||
| 3774 | } | ||
| 3775 | case IIS_APPPOOL_USER : | ||
| 3776 | { | ||
| 3777 | // /processModel | userName | ||
| 3778 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 3779 | ExitOnFailure(hr, "Failed to read AppPool user"); | ||
| 3780 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement); | ||
| 3781 | ExitOnFailure(hr, "Failed to get AppPool processModel element"); | ||
| 3782 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_USERNAME, pwzData); | ||
| 3783 | ExitOnFailure(hr, "Failed to set AppPool processModel username value"); | ||
| 3784 | ReleaseNullObject(pElement); | ||
| 3785 | break; | ||
| 3786 | } | ||
| 3787 | case IIS_APPPOOL_PWD : | ||
| 3788 | { | ||
| 3789 | // /processModel | password | ||
| 3790 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 3791 | ExitOnFailure(hr, "Failed to read AppPool pwd"); | ||
| 3792 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement); | ||
| 3793 | ExitOnFailure(hr, "Failed to get AppPool processModel element"); | ||
| 3794 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PASSWORD, pwzData); | ||
| 3795 | ExitOnFailure(hr, "Failed to set AppPool processModel password value"); | ||
| 3796 | ReleaseNullObject(pElement); | ||
| 3797 | break; | ||
| 3798 | } | ||
| 3799 | case IIS_APPPOOL_RECYCLE_CPU_PCT: | ||
| 3800 | { | ||
| 3801 | // /cpu | limit | ||
| 3802 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3803 | ExitOnFailure(hr, "Failed to read cpu pct"); | ||
| 3804 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_CPU), &pElement); | ||
| 3805 | ExitOnFailure(hr, "Failed to get AppPool cpu element"); | ||
| 3806 | // limit is maximum percentage of CPU time (in 1/1000ths of one percent) | ||
| 3807 | hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_LIMIT, iData * 1000); | ||
| 3808 | ExitOnFailure(hr, "Failed to set AppPool cpu limit"); | ||
| 3809 | ReleaseNullObject(pElement); | ||
| 3810 | break; | ||
| 3811 | } | ||
| 3812 | case IIS_APPPOOL_RECYCLE_CPU_REFRESH: | ||
| 3813 | { | ||
| 3814 | // /cpu | resetInterval | ||
| 3815 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3816 | ExitOnFailure(hr, "Failed to read cpu refresh pwd"); | ||
| 3817 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_CPU), &pElement); | ||
| 3818 | ExitOnFailure(hr, "Failed to get AppPool cpu element"); | ||
| 3819 | *wcTime = '\0'; | ||
| 3820 | ConvSecToHMS(iData * 60, wcTime, countof(wcTime)); | ||
| 3821 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_RESETINTERVAL, wcTime); | ||
| 3822 | ExitOnFailure(hr, "Failed to set AppPool cpu resetInterval value"); | ||
| 3823 | ReleaseNullObject(pElement); | ||
| 3824 | break; | ||
| 3825 | } | ||
| 3826 | case IIS_APPPOOL_RECYCLE_CPU_ACTION: | ||
| 3827 | { | ||
| 3828 | // /cpu | action | ||
| 3829 | //"NoAction" 0 | ||
| 3830 | //"KillW3wp" 1 | ||
| 3831 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3832 | ExitOnFailure(hr, "Failed to read cpu action"); | ||
| 3833 | hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_CPU), &pElement); | ||
| 3834 | ExitOnFailure(hr, "Failed to get AppPool cpu element"); | ||
| 3835 | if (iData) | ||
| 3836 | { | ||
| 3837 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CPU_ACTION, IIS_CONFIG_KILLW3WP); | ||
| 3838 | } | ||
| 3839 | else | ||
| 3840 | { | ||
| 3841 | hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CPU_ACTION, IIS_CONFIG_NOACTION); | ||
| 3842 | } | ||
| 3843 | ExitOnFailure(hr, "Failed to set AppPool cpu action value"); | ||
| 3844 | ReleaseNullObject(pElement); | ||
| 3845 | break; | ||
| 3846 | } | ||
| 3847 | case IIS_APPPOOL_32BIT: | ||
| 3848 | { | ||
| 3849 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData); | ||
| 3850 | ExitOnFailure(hr, "Failed to read enable32BitAppOnWin64 value"); | ||
| 3851 | // enable32BitAppOnWin64 | ||
| 3852 | hr = Iis7PutPropertyBool(pAppPoolElement, IIS_CONFIG_ENABLE32, iData ? TRUE : FALSE); | ||
| 3853 | ExitOnFailure(hr, "Failed to set AppPool enable32BitAppOnWin64 value"); | ||
| 3854 | break; | ||
| 3855 | } | ||
| 3856 | case IIS_APPPOOL_MANAGED_PIPELINE_MODE: | ||
| 3857 | { | ||
| 3858 | // managedPipelineMode | ||
| 3859 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 3860 | ExitOnFailure(hr, "Failed to read AppPool managedRuntimeVersion"); | ||
| 3861 | hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_PIPELINEMODE, pwzData); | ||
| 3862 | ExitOnFailure(hr, "Failed set AppPool managedPipelineMode property"); | ||
| 3863 | break; | ||
| 3864 | } | ||
| 3865 | case IIS_APPPOOL_MANAGED_RUNTIME_VERSION: | ||
| 3866 | { | ||
| 3867 | // managedRuntimeVersion | ||
| 3868 | hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData); | ||
| 3869 | ExitOnFailure(hr, "Failed to read AppPool managedRuntimeVersion"); | ||
| 3870 | hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_MANAGEDRUNTIMEVERSION, pwzData); | ||
| 3871 | ExitOnFailure(hr, "Failed set AppPool managedRuntimeVersion property"); | ||
| 3872 | break; | ||
| 3873 | } | ||
| 3874 | |||
| 3875 | default: | ||
| 3876 | ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for AppPool"); | ||
| 3877 | break; | ||
| 3878 | |||
| 3879 | } | ||
| 3880 | // Get AppPool property action | ||
| 3881 | hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction); | ||
| 3882 | ExitOnFailure(hr, "Failed to read AppPool Property action"); | ||
| 3883 | } | ||
| 3884 | |||
| 3885 | LExit: | ||
| 3886 | ReleaseObject(pAppPools); | ||
| 3887 | ReleaseObject(pCollection); | ||
| 3888 | ReleaseObject(pCollection2); | ||
| 3889 | ReleaseObject(pAppPoolElement); | ||
| 3890 | ReleaseObject(pElement); | ||
| 3891 | ReleaseObject(pElement2); | ||
| 3892 | ReleaseObject(pElement3); | ||
| 3893 | |||
| 3894 | return hr; | ||
| 3895 | } | ||
| 3896 | |||
| 3897 | static HRESULT SetDirPropAuthentications(IAppHostWritableAdminManager *pAdminMgr, | ||
| 3898 | LPCWSTR wszConfigPath, | ||
| 3899 | DWORD dwData) | ||
| 3900 | { | ||
| 3901 | HRESULT hr = S_OK; | ||
| 3902 | IAppHostElement *pSection = NULL; | ||
| 3903 | |||
| 3904 | //dwData contains bit flags for /security/authentication/<...> | ||
| 3905 | // Anonymous = 1 | ||
| 3906 | // Basic = 2 | ||
| 3907 | // Windows = 4 | ||
| 3908 | // Digest =16 | ||
| 3909 | // Passport =64 *not supported | ||
| 3910 | //translation required from bit map to section name | ||
| 3911 | // E.G security/authentication/windowsAuthentication [property enabled true|false] | ||
| 3912 | |||
| 3913 | // AnonymousAuthentication = 1 | ||
| 3914 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/anonymousAuthentication"), ScopeBSTR(wszConfigPath), &pSection); | ||
| 3915 | ExitOnFailure(hr, "Failed get AnonymousAuthentication section for DirProp"); | ||
| 3916 | if (!pSection) | ||
| 3917 | { | ||
| 3918 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 3919 | ExitOnFailure(hr, "Failed get AnonymousAuthentication section object for DirProps"); | ||
| 3920 | } | ||
| 3921 | |||
| 3922 | hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x1)); | ||
| 3923 | ExitOnFailure(hr, "Failed set AnonymousAuthentication enabled for DirProps"); | ||
| 3924 | ReleaseNullObject(pSection); | ||
| 3925 | |||
| 3926 | // basicAuthentication = 2 | ||
| 3927 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/basicAuthentication"), ScopeBSTR(wszConfigPath), &pSection); | ||
| 3928 | ExitOnFailure(hr, "Failed get basicAuthentication section for DirProp"); | ||
| 3929 | if (!pSection) | ||
| 3930 | { | ||
| 3931 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 3932 | ExitOnFailure(hr, "Failed get basicAuthentication section object for DirProps"); | ||
| 3933 | } | ||
| 3934 | |||
| 3935 | hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x2)); | ||
| 3936 | ExitOnFailure(hr, "Failed set basicAuthentication enabled for DirProps"); | ||
| 3937 | ReleaseNullObject(pSection); | ||
| 3938 | |||
| 3939 | // WindowsAuthentication = 4 | ||
| 3940 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/windowsAuthentication"), ScopeBSTR(wszConfigPath), &pSection); | ||
| 3941 | ExitOnFailure(hr, "Failed get windowsAuthentication section for DirProp"); | ||
| 3942 | if (!pSection) | ||
| 3943 | { | ||
| 3944 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 3945 | ExitOnFailure(hr, "Failed get windowsAuthentication section object for DirProps"); | ||
| 3946 | } | ||
| 3947 | |||
| 3948 | hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x4)); | ||
| 3949 | ExitOnFailure(hr, "Failed set windowsAuthentication enabled for DirProps"); | ||
| 3950 | ReleaseNullObject(pSection); | ||
| 3951 | |||
| 3952 | // digestAuthentication = 16 | ||
| 3953 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/digestAuthentication"), ScopeBSTR(wszConfigPath), &pSection); | ||
| 3954 | ExitOnFailure(hr, "Failed get digestAuthentication section for DirProp"); | ||
| 3955 | if (!pSection) | ||
| 3956 | { | ||
| 3957 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 3958 | ExitOnFailure(hr, "Failed get digestAuthentication section object for DirProps"); | ||
| 3959 | } | ||
| 3960 | |||
| 3961 | hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x10)); | ||
| 3962 | ExitOnFailure(hr, "Failed set digestAuthentication enabled for DirProps"); | ||
| 3963 | ReleaseNullObject(pSection); | ||
| 3964 | |||
| 3965 | LExit: | ||
| 3966 | ReleaseObject(pSection); | ||
| 3967 | |||
| 3968 | return hr; | ||
| 3969 | } | ||
| 3970 | |||
| 3971 | static HRESULT SetDirPropAuthProvider(IAppHostWritableAdminManager *pAdminMgr, | ||
| 3972 | LPCWSTR wszConfigPath, | ||
| 3973 | __in LPWSTR wszData) | ||
| 3974 | { | ||
| 3975 | HRESULT hr = S_OK; | ||
| 3976 | IAppHostElement *pSection = NULL; | ||
| 3977 | IAppHostElement *pElement = NULL; | ||
| 3978 | IAppHostElement *pNewElement = NULL; | ||
| 3979 | IAppHostElementCollection *pCollection = NULL; | ||
| 3980 | |||
| 3981 | WCHAR wcDelim[] = L","; | ||
| 3982 | const WCHAR *wszToken = NULL; | ||
| 3983 | WCHAR *wszNextToken = NULL; | ||
| 3984 | |||
| 3985 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/windowsAuthentication"), ScopeBSTR(wszConfigPath), &pSection); | ||
| 3986 | ExitOnFailure(hr, "Failed get windowsAuthentication section for DirProp providers"); | ||
| 3987 | |||
| 3988 | hr = pSection->GetElementByName(ScopeBSTR(L"providers"), &pElement); | ||
| 3989 | ExitOnFailure(hr, "Failed get win auth providers section"); | ||
| 3990 | |||
| 3991 | hr = pElement->get_Collection(&pCollection); | ||
| 3992 | ExitOnFailure(hr, "Failed get win auth providers collection"); | ||
| 3993 | |||
| 3994 | hr = pCollection->Clear(); | ||
| 3995 | ExitOnFailure(hr, "Failed to clear win auth providers collection"); | ||
| 3996 | |||
| 3997 | //Clear out inherited items - add clear | ||
| 3998 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pNewElement); | ||
| 3999 | ExitOnFailure(hr, "Failed to create win auth providers clear element"); | ||
| 4000 | hr = pCollection->AddElement(pNewElement); | ||
| 4001 | ExitOnFailure(hr, "Failed to add win auth providers clear element"); | ||
| 4002 | ReleaseNullObject(pNewElement); | ||
| 4003 | |||
| 4004 | wszToken = wcstok_s( wszData, wcDelim, &wszNextToken); | ||
| 4005 | for (int i = 0; (wszToken); ++i) | ||
| 4006 | { | ||
| 4007 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pNewElement); | ||
| 4008 | ExitOnFailure(hr, "Failed to create win auth providers element"); | ||
| 4009 | |||
| 4010 | hr = Iis7PutPropertyString( pNewElement, IIS_CONFIG_VALUE, wszToken); | ||
| 4011 | ExitOnFailure(hr, "Failed to set win auth providers value"); | ||
| 4012 | |||
| 4013 | hr = pCollection->AddElement(pNewElement, i); | ||
| 4014 | ExitOnFailure(hr, "Failed to add win auth providers element"); | ||
| 4015 | ReleaseNullObject(pNewElement); | ||
| 4016 | |||
| 4017 | wszToken = wcstok_s( NULL, wcDelim, &wszNextToken); | ||
| 4018 | } | ||
| 4019 | |||
| 4020 | LExit: | ||
| 4021 | ReleaseObject(pSection); | ||
| 4022 | ReleaseObject(pCollection); | ||
| 4023 | ReleaseObject(pElement); | ||
| 4024 | ReleaseObject(pNewElement); | ||
| 4025 | |||
| 4026 | return hr; | ||
| 4027 | } | ||
| 4028 | |||
| 4029 | static HRESULT SetDirPropDefDoc( | ||
| 4030 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 4031 | LPCWSTR wszConfigPath, | ||
| 4032 | __in LPWSTR wszData) | ||
| 4033 | { | ||
| 4034 | HRESULT hr = S_OK; | ||
| 4035 | IAppHostElement *pSection = NULL; | ||
| 4036 | IAppHostElement *pElement = NULL; | ||
| 4037 | IAppHostElement *pNewElement = NULL; | ||
| 4038 | IAppHostElementCollection *pCollection = NULL; | ||
| 4039 | |||
| 4040 | WCHAR wcDelim[] = L","; | ||
| 4041 | const WCHAR *wszToken = NULL; | ||
| 4042 | WCHAR *wszNextToken = NULL; | ||
| 4043 | |||
| 4044 | hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_DEFAULTDOC_SECTION), ScopeBSTR(wszConfigPath), &pSection); | ||
| 4045 | ExitOnFailure(hr, "Failed get defaultDocument section for DirProp"); | ||
| 4046 | |||
| 4047 | hr = pSection->GetElementByName(ScopeBSTR(L"files"), &pElement); | ||
| 4048 | ExitOnFailure(hr, "Failed get win files section"); | ||
| 4049 | |||
| 4050 | hr = pElement->get_Collection(&pCollection); | ||
| 4051 | ExitOnFailure(hr, "Failed get files collection"); | ||
| 4052 | |||
| 4053 | hr = pCollection->Clear(); | ||
| 4054 | ExitOnFailure(hr, "Failed clear files collection"); | ||
| 4055 | |||
| 4056 | //Clear out inherited items - add clear | ||
| 4057 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pNewElement); | ||
| 4058 | ExitOnFailure(hr, "Failed to create files clear element"); | ||
| 4059 | hr = pCollection->AddElement(pNewElement); | ||
| 4060 | ExitOnFailure(hr, "Failed to add files clear element"); | ||
| 4061 | |||
| 4062 | wszToken = wcstok_s( wszData, wcDelim, &wszNextToken); | ||
| 4063 | for (int i = 0; (wszToken); ++i) | ||
| 4064 | { | ||
| 4065 | hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pNewElement); | ||
| 4066 | ExitOnFailure(hr, "Failed to create win auth providers element"); | ||
| 4067 | |||
| 4068 | hr = Iis7PutPropertyString( pNewElement, IIS_CONFIG_VALUE, wszToken); | ||
| 4069 | ExitOnFailure(hr, "Failed to set win auth providers value"); | ||
| 4070 | |||
| 4071 | hr = pCollection->AddElement(pNewElement, i); | ||
| 4072 | ExitOnFailure(hr, "Failed to add defaultDocument Files element"); | ||
| 4073 | ReleaseNullObject(pNewElement); | ||
| 4074 | |||
| 4075 | wszToken = wcstok_s( NULL, wcDelim, &wszNextToken); | ||
| 4076 | } | ||
| 4077 | |||
| 4078 | LExit: | ||
| 4079 | ReleaseObject(pSection); | ||
| 4080 | ReleaseObject(pCollection); | ||
| 4081 | ReleaseObject(pNewElement); | ||
| 4082 | |||
| 4083 | return hr; | ||
| 4084 | } | ||
| 4085 | |||
| 4086 | static HRESULT ClearLocationTag( | ||
| 4087 | IAppHostWritableAdminManager *pAdminMgr, | ||
| 4088 | LPCWSTR swLocationPath | ||
| 4089 | ) | ||
| 4090 | { | ||
| 4091 | HRESULT hr = S_OK; | ||
| 4092 | IAppHostConfigManager *pConfigMgr = NULL; | ||
| 4093 | IAppHostConfigFile *pConfigFile = NULL; | ||
| 4094 | IAppHostConfigLocationCollection *pLocationCollection = NULL; | ||
| 4095 | IAppHostConfigLocation *pLocation = NULL; | ||
| 4096 | |||
| 4097 | DWORD dwCount = 0; | ||
| 4098 | BSTR bstrLocationPath = NULL; | ||
| 4099 | |||
| 4100 | hr = pAdminMgr->get_ConfigManager(&pConfigMgr); | ||
| 4101 | ExitOnFailure(hr, "Failed to get IIS ConfigManager interface"); | ||
| 4102 | |||
| 4103 | hr = pConfigMgr->GetConfigFile(ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pConfigFile); | ||
| 4104 | ExitOnFailure(hr, "Failed to get IIS ConfigFile interface"); | ||
| 4105 | |||
| 4106 | hr = pConfigFile->get_Locations(&pLocationCollection); | ||
| 4107 | ExitOnFailure(hr, "Failed to get IIS location tag collection"); | ||
| 4108 | |||
| 4109 | hr = pLocationCollection->get_Count(&dwCount); | ||
| 4110 | ExitOnFailure(hr, "Failed to get IIS location collection count"); | ||
| 4111 | |||
| 4112 | VARIANT vtIndex; | ||
| 4113 | vtIndex.vt = VT_UI4; | ||
| 4114 | for (DWORD i = 0; i < dwCount; ++i) | ||
| 4115 | { | ||
| 4116 | vtIndex.ulVal = i; | ||
| 4117 | hr = pLocationCollection->get_Item(vtIndex, &pLocation); | ||
| 4118 | ExitOnFailure(hr, "Failed to get IIS location collection count"); | ||
| 4119 | |||
| 4120 | hr = pLocation->get_Path(&bstrLocationPath); | ||
| 4121 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, swLocationPath, -1, bstrLocationPath, -1)) | ||
| 4122 | { | ||
| 4123 | hr = pLocationCollection->DeleteLocation(vtIndex); | ||
| 4124 | ExitOnFailure(hr, "Failed to delete IIS location tag %ls",swLocationPath); | ||
| 4125 | break; | ||
| 4126 | } | ||
| 4127 | |||
| 4128 | ReleaseNullObject(pLocation); | ||
| 4129 | ::SysFreeString(bstrLocationPath); | ||
| 4130 | bstrLocationPath = NULL; | ||
| 4131 | } | ||
| 4132 | LExit: | ||
| 4133 | ReleaseObject(pConfigMgr); | ||
| 4134 | ReleaseObject(pConfigFile); | ||
| 4135 | ReleaseObject(pLocationCollection); | ||
| 4136 | ReleaseObject(pLocation); | ||
| 4137 | ReleaseBSTR(bstrLocationPath); | ||
| 4138 | |||
| 4139 | return hr; | ||
| 4140 | |||
| 4141 | } | ||
| 4142 | |||
| 4143 | static HRESULT DeleteCollectionElement( | ||
| 4144 | __in IAppHostElementCollection *pCollection, | ||
| 4145 | __in LPCWSTR pwzElementName, | ||
| 4146 | __in LPCWSTR pwzAttributeName, | ||
| 4147 | __in LPCWSTR pwzAttributeValue | ||
| 4148 | ) | ||
| 4149 | { | ||
| 4150 | HRESULT hr = S_OK; | ||
| 4151 | |||
| 4152 | DWORD dwIndex; | ||
| 4153 | VARIANT vtIndex; | ||
| 4154 | VariantInit(&vtIndex); | ||
| 4155 | |||
| 4156 | hr = Iis7FindAppHostElementString(pCollection, pwzElementName, pwzAttributeName, pwzAttributeValue, NULL, &dwIndex); | ||
| 4157 | ExitOnFailure(hr, "Failed while finding IAppHostElement %ls/@%ls=%ls", pwzElementName, pwzAttributeName, pwzAttributeValue); | ||
| 4158 | |||
| 4159 | if (MAXDWORD != dwIndex) | ||
| 4160 | { | ||
| 4161 | vtIndex.vt = VT_UI4; | ||
| 4162 | vtIndex.ulVal = dwIndex; | ||
| 4163 | hr = pCollection->DeleteElement(vtIndex); | ||
| 4164 | ExitOnFailure(hr, "Failed to delete IAppHostElement %ls/@%ls=%ls", pwzElementName, pwzAttributeName, pwzAttributeValue); | ||
| 4165 | } | ||
| 4166 | // else : nothing to do, already deleted | ||
| 4167 | LExit: | ||
| 4168 | ReleaseVariant(vtIndex); | ||
| 4169 | |||
| 4170 | return hr; | ||
| 4171 | } | ||
| 4172 | static void ConvSecToHMS( int Sec, __out_ecount(cchDest) LPWSTR wcTime, size_t cchDest) | ||
| 4173 | { | ||
| 4174 | int ZH, ZM, ZS = 0; | ||
| 4175 | |||
| 4176 | ZH = (Sec / 3600); | ||
| 4177 | Sec = Sec - ZH * 3600; | ||
| 4178 | ZM = (Sec / 60) ; | ||
| 4179 | Sec = Sec - ZM * 60; | ||
| 4180 | ZS = Sec ; | ||
| 4181 | |||
| 4182 | HRESULT hr = ::StringCchPrintfW(wcTime, cchDest, L"%02d:%02d:%02d", ZH, ZM, ZS); | ||
| 4183 | if (S_OK != hr) | ||
| 4184 | { | ||
| 4185 | *wcTime = '\0'; | ||
| 4186 | } | ||
| 4187 | } | ||
| 4188 | static void ConvSecToDHMS( unsigned int Sec, __out_ecount(cchDest) LPWSTR wcTime, size_t cchDest) | ||
| 4189 | { | ||
| 4190 | int ZD, ZH, ZM, ZS = 0; | ||
| 4191 | |||
| 4192 | ZD = Sec / 86400; | ||
| 4193 | Sec = Sec - ZD * 86400; | ||
| 4194 | ZH = (Sec / 3600); | ||
| 4195 | Sec = Sec - ZH * 3600; | ||
| 4196 | ZM = (Sec / 60) ; | ||
| 4197 | Sec = Sec - ZM * 60; | ||
| 4198 | ZS = Sec ; | ||
| 4199 | |||
| 4200 | HRESULT hr = ::StringCchPrintfW(wcTime, cchDest, L"%d.%02d:%02d:%02d", ZD, ZH, ZM, ZS); | ||
| 4201 | if (S_OK != hr) | ||
| 4202 | { | ||
| 4203 | *wcTime = '\0'; | ||
| 4204 | } | ||
| 4205 | } | ||
diff --git a/src/ext/Iis/ca/scaexecIIS7.h b/src/ext/Iis/ca/scaexecIIS7.h new file mode 100644 index 00000000..ec31f202 --- /dev/null +++ b/src/ext/Iis/ca/scaexecIIS7.h | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT IIS7ConfigChanges(MSIHANDLE hInstall, __inout LPWSTR pwzData); | ||
diff --git a/src/ext/Iis/ca/scafilter.cpp b/src/ext/Iis/ca/scafilter.cpp new file mode 100644 index 00000000..9d9014fd --- /dev/null +++ b/src/ext/Iis/ca/scafilter.cpp | |||
| @@ -0,0 +1,510 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // prototypes | ||
| 6 | static HRESULT ReadFilterLoadOrder( | ||
| 7 | __in IMSAdminBase* piMetabase, | ||
| 8 | __in LPCWSTR wzFilterRoot, | ||
| 9 | __out LPWSTR *ppwzLoadOrder | ||
| 10 | ); | ||
| 11 | static HRESULT AddFilterToLoadOrder( | ||
| 12 | __in LPCWSTR wzFilter, | ||
| 13 | __in int iLoadOrder, | ||
| 14 | __inout LPWSTR *ppwzLoadOrder | ||
| 15 | ); | ||
| 16 | static HRESULT RemoveFilterFromLoadOrder( | ||
| 17 | __in LPCWSTR wzFilter, | ||
| 18 | __inout LPWSTR *ppwzLoadOrder | ||
| 19 | ); | ||
| 20 | |||
| 21 | |||
| 22 | UINT __stdcall ScaFiltersRead( | ||
| 23 | __in IMSAdminBase* piMetabase, | ||
| 24 | __in SCA_WEB* pswList, | ||
| 25 | __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, | ||
| 26 | __inout SCA_FILTER** ppsfList, | ||
| 27 | __inout LPWSTR *ppwzCustomActionData | ||
| 28 | ) | ||
| 29 | { | ||
| 30 | HRESULT hr = S_OK; | ||
| 31 | MSIHANDLE hRec; | ||
| 32 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
| 33 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
| 34 | |||
| 35 | LPWSTR pwzData = NULL; | ||
| 36 | |||
| 37 | SCA_FILTER* psf = NULL; | ||
| 38 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 39 | |||
| 40 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 41 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 42 | |||
| 43 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 44 | { | ||
| 45 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaFiltersRead() - no IIsFilter table"); | ||
| 46 | ExitFunction1(hr = S_FALSE); | ||
| 47 | } | ||
| 48 | |||
| 49 | // loop through all the filters | ||
| 50 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 51 | { | ||
| 52 | // Get the Component first. If the component is not being modified during | ||
| 53 | // this transaction, skip processing this whole record. | ||
| 54 | hr = WcaGetRecordString(hRec, fqComponent, &pwzData); | ||
| 55 | ExitOnFailure(hr, "failed to get IIsFilter.Component"); | ||
| 56 | |||
| 57 | hr = WcaGetRecordInteger(hRec, fqInstalled, (int *)&isInstalled); | ||
| 58 | ExitOnFailure(hr, "Failed to get Component installed state for IIs filter"); | ||
| 59 | |||
| 60 | hr = WcaGetRecordInteger(hRec, fqAction, (int *)&isAction); | ||
| 61 | ExitOnFailure(hr, "Failed to get Component action state for IIs filter"); | ||
| 62 | |||
| 63 | if (!WcaIsInstalling(isInstalled, isAction) && | ||
| 64 | !WcaIsReInstalling(isInstalled, isAction) && | ||
| 65 | !WcaIsUninstalling(isInstalled, isAction)) | ||
| 66 | { | ||
| 67 | continue; // skip this record. | ||
| 68 | } | ||
| 69 | |||
| 70 | hr = AddFilterToList(ppsfList); | ||
| 71 | ExitOnFailure(hr, "failed to add filter to list"); | ||
| 72 | |||
| 73 | psf = *ppsfList; | ||
| 74 | |||
| 75 | hr = ::StringCchCopyW(psf->wzComponent, countof(psf->wzComponent), pwzData); | ||
| 76 | ExitOnFailure(hr, "failed to copy component name: %ls", pwzData); | ||
| 77 | |||
| 78 | psf->isInstalled = isInstalled; | ||
| 79 | psf->isAction = isAction; | ||
| 80 | |||
| 81 | hr = WcaGetRecordString(hRec, fqWeb, &pwzData); | ||
| 82 | ExitOnFailure(hr, "Failed to get Web for VirtualDir"); | ||
| 83 | |||
| 84 | if (*pwzData) | ||
| 85 | { | ||
| 86 | hr = ScaWebsGetBase(piMetabase, pswList, pwzData, psf->wzWebBase, countof(psf->wzWebBase), hWebBaseQuery); | ||
| 87 | if (FAILED(hr) && WcaIsUninstalling(isInstalled, isAction)) | ||
| 88 | { | ||
| 89 | // If we're uninstalling, don't bother finding the existing web, just leave the filter root empty | ||
| 90 | hr = S_OK; | ||
| 91 | } | ||
| 92 | ExitOnFailure(hr, "Failed to get base of web for Filter"); | ||
| 93 | |||
| 94 | if (0 != lstrlenW(psf->wzWebBase)) | ||
| 95 | { | ||
| 96 | hr = ::StringCchPrintfW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"%s/Filters", psf->wzWebBase); | ||
| 97 | ExitOnFailure(hr, "Failed to allocate filter base string"); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | else | ||
| 101 | { | ||
| 102 | hr = ::StringCchCopyW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"/LM/W3SVC/Filters"); | ||
| 103 | ExitOnFailure(hr, "Failed to allocate global filter base string"); | ||
| 104 | } | ||
| 105 | |||
| 106 | // filter key | ||
| 107 | hr = WcaGetRecordString(hRec, fqFilter, &pwzData); | ||
| 108 | ExitOnFailure(hr, "Failed to get Filter.Filter"); | ||
| 109 | hr = ::StringCchCopyW(psf->wzKey, countof(psf->wzKey), pwzData); | ||
| 110 | ExitOnFailure(hr, "Failed to copy key string to filter object"); | ||
| 111 | |||
| 112 | // filter path | ||
| 113 | hr = WcaGetRecordString(hRec, fqPath, &pwzData); | ||
| 114 | ExitOnFailure(hr, "Failed to get Filter.Path"); | ||
| 115 | hr = ::StringCchCopyW(psf->wzPath, countof(psf->wzPath), pwzData); | ||
| 116 | ExitOnFailure(hr, "Failed to copy path string to filter object"); | ||
| 117 | |||
| 118 | // filter description | ||
| 119 | hr = WcaGetRecordString(hRec, fqDescription, &pwzData); | ||
| 120 | ExitOnFailure(hr, "Failed to get Filter.Description"); | ||
| 121 | hr = ::StringCchCopyW(psf->wzDescription, countof(psf->wzDescription), pwzData); | ||
| 122 | ExitOnFailure(hr, "Failed to copy description string to filter object"); | ||
| 123 | |||
| 124 | // filter flags | ||
| 125 | hr = WcaGetRecordInteger(hRec, fqFlags, &psf->iFlags); | ||
| 126 | ExitOnFailure(hr, "Failed to get Filter.Flags"); | ||
| 127 | |||
| 128 | // filter load order | ||
| 129 | hr = WcaGetRecordInteger(hRec, fqLoadOrder, &psf->iLoadOrder); | ||
| 130 | ExitOnFailure(hr, "Failed to get Filter.LoadOrder"); | ||
| 131 | } | ||
| 132 | |||
| 133 | if (E_NOMOREITEMS == hr) | ||
| 134 | { | ||
| 135 | hr = S_OK; | ||
| 136 | } | ||
| 137 | ExitOnFailure(hr, "Failure while processing filters"); | ||
| 138 | |||
| 139 | LExit: | ||
| 140 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 141 | |||
| 142 | ReleaseStr(pwzData); | ||
| 143 | return hr; | ||
| 144 | } | ||
| 145 | |||
| 146 | |||
| 147 | HRESULT ScaFiltersInstall( | ||
| 148 | __in IMSAdminBase* piMetabase, | ||
| 149 | __in SCA_FILTER* psfList | ||
| 150 | ) | ||
| 151 | { | ||
| 152 | HRESULT hr = S_OK; | ||
| 153 | SCA_FILTER* psf = psfList; | ||
| 154 | LPCWSTR wzPreviousFilterRoot = NULL; | ||
| 155 | LPWSTR pwzLoadOrder = NULL; | ||
| 156 | |||
| 157 | while (psf) | ||
| 158 | { | ||
| 159 | if (WcaIsInstalling(psf->isInstalled, psf->isAction)) | ||
| 160 | { | ||
| 161 | if (!wzPreviousFilterRoot || CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, 0, wzPreviousFilterRoot, -1, psf->wzFilterRoot, -1)) | ||
| 162 | { | ||
| 163 | if (pwzLoadOrder) | ||
| 164 | { | ||
| 165 | hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder); | ||
| 166 | ExitOnFailure(hr, "Failed to write filter load order to metabase"); | ||
| 167 | |||
| 168 | ReleaseNullStr(pwzLoadOrder); | ||
| 169 | } | ||
| 170 | |||
| 171 | hr = ReadFilterLoadOrder(piMetabase, psf->wzFilterRoot, &pwzLoadOrder); | ||
| 172 | ExitOnFailure(hr, "Failed to read filter load order."); | ||
| 173 | |||
| 174 | wzPreviousFilterRoot = psf->wzFilterRoot; | ||
| 175 | } | ||
| 176 | |||
| 177 | hr = ScaCreateMetabaseKey(piMetabase, psf->wzFilterRoot, psf->wzKey); | ||
| 178 | ExitOnFailure(hr, "Failed to create key for filter '%ls'", psf->wzKey); | ||
| 179 | |||
| 180 | hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsFilter"); | ||
| 181 | ExitOnFailure(hr, "Failed to write key type for filter '%ls'", psf->wzKey); | ||
| 182 | |||
| 183 | // filter path | ||
| 184 | hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_FILTER_IMAGE_PATH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)psf->wzPath); | ||
| 185 | ExitOnFailure(hr, "Failed to write Path for filter '%ls'", psf->wzKey); | ||
| 186 | |||
| 187 | // filter description | ||
| 188 | hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_FILTER_DESCRIPTION, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)psf->wzDescription); | ||
| 189 | ExitOnFailure(hr, "Failed to write Description for filter '%ls'", psf->wzKey); | ||
| 190 | |||
| 191 | // filter flags | ||
| 192 | if (MSI_NULL_INTEGER != psf->iFlags) | ||
| 193 | { | ||
| 194 | hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_FILTER_FLAGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psf->iFlags)); | ||
| 195 | ExitOnFailure(hr, "Failed to write Flags for filter '%ls'", psf->wzKey); | ||
| 196 | } | ||
| 197 | |||
| 198 | // filter load order | ||
| 199 | if (MSI_NULL_INTEGER != psf->iLoadOrder) | ||
| 200 | { | ||
| 201 | hr = AddFilterToLoadOrder(psf->wzKey, psf->iLoadOrder, &pwzLoadOrder); | ||
| 202 | ExitOnFailure(hr, "Failed to add filter '%ls' to load order.", psf->wzKey); | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | psf = psf->psfNext; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (pwzLoadOrder) | ||
| 210 | { | ||
| 211 | Assert(wzPreviousFilterRoot && *wzPreviousFilterRoot); | ||
| 212 | |||
| 213 | hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder); | ||
| 214 | ExitOnFailure(hr, "Failed to write filter load order to metabase"); | ||
| 215 | } | ||
| 216 | |||
| 217 | LExit: | ||
| 218 | ReleaseStr(pwzLoadOrder); | ||
| 219 | return hr; | ||
| 220 | } | ||
| 221 | |||
| 222 | |||
| 223 | HRESULT ScaFiltersUninstall( | ||
| 224 | __in IMSAdminBase* piMetabase, | ||
| 225 | __in SCA_FILTER* psfList | ||
| 226 | ) | ||
| 227 | { | ||
| 228 | HRESULT hr = S_OK; | ||
| 229 | SCA_FILTER* psf = psfList; | ||
| 230 | LPCWSTR wzPreviousFilterRoot = NULL; | ||
| 231 | LPWSTR pwzLoadOrder = NULL; | ||
| 232 | |||
| 233 | while (psf) | ||
| 234 | { | ||
| 235 | if (WcaIsUninstalling(psf->isInstalled, psf->isAction)) | ||
| 236 | { | ||
| 237 | if (!wzPreviousFilterRoot || CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, 0, wzPreviousFilterRoot, -1, psf->wzFilterRoot, -1)) | ||
| 238 | { | ||
| 239 | if (pwzLoadOrder) | ||
| 240 | { | ||
| 241 | hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder); | ||
| 242 | ExitOnFailure(hr, "Failed to write filter load order to metabase"); | ||
| 243 | |||
| 244 | ReleaseNullStr(pwzLoadOrder); | ||
| 245 | } | ||
| 246 | |||
| 247 | hr = ReadFilterLoadOrder(piMetabase, psf->wzFilterRoot, &pwzLoadOrder); | ||
| 248 | ExitOnFailure(hr, "Failed to read filter load order."); | ||
| 249 | |||
| 250 | wzPreviousFilterRoot = psf->wzFilterRoot; | ||
| 251 | } | ||
| 252 | |||
| 253 | hr = RemoveFilterFromLoadOrder(psf->wzKey, &pwzLoadOrder); | ||
| 254 | ExitOnFailure(hr, "Failed to remove filter '%ls' from load order", psf->wzKey); | ||
| 255 | |||
| 256 | // remove the filter from the load order and remove the filter's key | ||
| 257 | if (0 != lstrlenW(psf->wzFilterRoot)) | ||
| 258 | { | ||
| 259 | hr = ScaDeleteMetabaseKey(piMetabase, psf->wzFilterRoot, psf->wzKey); | ||
| 260 | ExitOnFailure(hr, "Failed to remove web '%ls' from metabase", psf->wzKey); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | psf = psf->psfNext; | ||
| 265 | } | ||
| 266 | |||
| 267 | if (pwzLoadOrder) | ||
| 268 | { | ||
| 269 | Assert(wzPreviousFilterRoot && *wzPreviousFilterRoot); | ||
| 270 | |||
| 271 | hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder); | ||
| 272 | ExitOnFailure(hr, "Failed to write filter load order to metabase"); | ||
| 273 | } | ||
| 274 | |||
| 275 | LExit: | ||
| 276 | return hr; | ||
| 277 | } | ||
| 278 | |||
| 279 | |||
| 280 | void ScaFiltersFreeList( | ||
| 281 | __in SCA_FILTER* psfList | ||
| 282 | ) | ||
| 283 | { | ||
| 284 | SCA_FILTER* psfDelete = psfList; | ||
| 285 | while (psfList) | ||
| 286 | { | ||
| 287 | psfDelete = psfList; | ||
| 288 | psfList = psfList->psfNext; | ||
| 289 | |||
| 290 | MemFree(psfDelete); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | HRESULT AddFilterToList( | ||
| 295 | __inout SCA_FILTER** ppsfList) | ||
| 296 | { | ||
| 297 | HRESULT hr = S_OK; | ||
| 298 | SCA_FILTER* psf = static_cast<SCA_FILTER*>(MemAlloc(sizeof(SCA_FILTER), TRUE)); | ||
| 299 | ExitOnNull(psf, hr, E_OUTOFMEMORY, "failed to add filter to filter list"); | ||
| 300 | |||
| 301 | psf->psfNext = *ppsfList; | ||
| 302 | *ppsfList = psf; | ||
| 303 | |||
| 304 | LExit: | ||
| 305 | return hr; | ||
| 306 | } | ||
| 307 | |||
| 308 | // private helper functions | ||
| 309 | |||
| 310 | |||
| 311 | static HRESULT ReadFilterLoadOrder( | ||
| 312 | __in IMSAdminBase* piMetabase, | ||
| 313 | __in LPCWSTR wzFilterRoot, | ||
| 314 | __out LPWSTR *ppwzLoadOrder | ||
| 315 | ) | ||
| 316 | { | ||
| 317 | HRESULT hr = S_OK; | ||
| 318 | METADATA_HANDLE mhRoot = NULL; | ||
| 319 | |||
| 320 | METADATA_RECORD mr; | ||
| 321 | DWORD dwRequired = 0; | ||
| 322 | DWORD cchData = 255; | ||
| 323 | |||
| 324 | ::ZeroMemory(&mr, sizeof(mr)); | ||
| 325 | mr.dwMDIdentifier = MD_FILTER_LOAD_ORDER; | ||
| 326 | mr.dwMDAttributes = METADATA_NO_ATTRIBUTES; | ||
| 327 | mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 328 | mr.dwMDDataType = ALL_METADATA; | ||
| 329 | mr.dwMDDataLen = cchData; | ||
| 330 | mr.pbMDData = static_cast<BYTE*>(MemAlloc(mr.dwMDDataLen * sizeof(WCHAR), TRUE)); | ||
| 331 | ExitOnNull(mr.pbMDData, hr, E_OUTOFMEMORY, "failed to allocate memory for MDData in metadata record"); | ||
| 332 | |||
| 333 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, wzFilterRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10, &mhRoot); | ||
| 334 | for (int i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--) | ||
| 335 | { | ||
| 336 | ::Sleep(1000); | ||
| 337 | WcaLog(LOGMSG_STANDARD, "Failed to open root key, retrying %d time(s)...", i); | ||
| 338 | hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, wzFilterRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10, &mhRoot); | ||
| 339 | } | ||
| 340 | |||
| 341 | if (SUCCEEDED(hr)) | ||
| 342 | { | ||
| 343 | hr = piMetabase->GetData(mhRoot, L"", &mr, &dwRequired); | ||
| 344 | if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr) | ||
| 345 | { | ||
| 346 | mr.dwMDDataLen = cchData = dwRequired; | ||
| 347 | |||
| 348 | LPVOID pv = MemReAlloc(mr.pbMDData, mr.dwMDDataLen * sizeof(WCHAR), TRUE); | ||
| 349 | ExitOnNull(pv, hr, E_OUTOFMEMORY, "failed to allocate memory for MDData in metadata record"); | ||
| 350 | mr.pbMDData = static_cast<BYTE*>(pv); | ||
| 351 | |||
| 352 | hr = piMetabase->GetData(mhRoot, L"", &mr, &dwRequired); | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | // The /Filters node or /Filters/FilterLoadOrder property might not exist (yet). | ||
| 357 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr) | ||
| 358 | { | ||
| 359 | hr = S_OK; | ||
| 360 | } | ||
| 361 | ExitOnFailure(hr, "Failed to get filter load order."); | ||
| 362 | |||
| 363 | hr = StrAllocString(ppwzLoadOrder, reinterpret_cast<LPCWSTR>(mr.pbMDData), 0); | ||
| 364 | ExitOnFailure(hr, "Failed to allocate string for filter load order."); | ||
| 365 | |||
| 366 | LExit: | ||
| 367 | ReleaseMem(mr.pbMDData); | ||
| 368 | |||
| 369 | if (mhRoot) | ||
| 370 | { | ||
| 371 | piMetabase->CloseKey(mhRoot); | ||
| 372 | } | ||
| 373 | |||
| 374 | return hr; | ||
| 375 | } | ||
| 376 | |||
| 377 | |||
| 378 | static HRESULT AddFilterToLoadOrder( | ||
| 379 | __in LPCWSTR wzFilter, | ||
| 380 | __in int iLoadOrder, | ||
| 381 | __inout LPWSTR *ppwzLoadOrder | ||
| 382 | ) | ||
| 383 | { | ||
| 384 | HRESULT hr = S_OK; | ||
| 385 | LPCWSTR wzLoadOrder = *ppwzLoadOrder; | ||
| 386 | int cchFilter = lstrlenW(wzFilter); | ||
| 387 | LPWSTR pwzTemp = NULL; | ||
| 388 | |||
| 389 | // If the filter name ends with '\0' or ',' and | ||
| 390 | // the filter name begins at the beginning of the list or with ',' | ||
| 391 | // Then we've found the exact filter by name. | ||
| 392 | // | ||
| 393 | // If the filter isn't already in the load order, add it | ||
| 394 | if (wzLoadOrder && *wzLoadOrder) | ||
| 395 | { | ||
| 396 | LPCWSTR pwz = wcsstr(wzLoadOrder, wzFilter); | ||
| 397 | |||
| 398 | if (NULL != pwz && | ||
| 399 | (L'\0' == *(pwz + cchFilter) || L',' == *(pwz + cchFilter)) && | ||
| 400 | (pwz == wzLoadOrder || L',' == *(pwz - 1))) | ||
| 401 | { | ||
| 402 | // Filter already in the load order, no work to do. | ||
| 403 | } | ||
| 404 | else | ||
| 405 | { | ||
| 406 | pwz = NULL; | ||
| 407 | if (0 <= iLoadOrder) | ||
| 408 | { | ||
| 409 | pwz = wzLoadOrder; | ||
| 410 | for (int i = 0; i < iLoadOrder && pwz; ++i) | ||
| 411 | { | ||
| 412 | pwz = wcsstr(pwz, L","); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 416 | if (NULL == pwz) // put the filter at the end of the order | ||
| 417 | { | ||
| 418 | Assert(wzLoadOrder && *wzLoadOrder); | ||
| 419 | |||
| 420 | // tack on a comma since there are other filters in the order | ||
| 421 | hr = StrAllocConcat(ppwzLoadOrder, L",", 1); | ||
| 422 | ExitOnFailure(hr, "Failed to append a comma to filter load order."); | ||
| 423 | |||
| 424 | hr = StrAllocConcat(ppwzLoadOrder, wzFilter, cchFilter); | ||
| 425 | ExitOnFailure(hr, "Failed to append the filter on to the load order."); | ||
| 426 | } | ||
| 427 | else if (L',' == *pwz) // put the filter in the middle of the order | ||
| 428 | { | ||
| 429 | hr = StrAllocString(&pwzTemp, wzLoadOrder, pwz - wzLoadOrder + 1); | ||
| 430 | ExitOnFailure(hr, "Failed to copy first half of filter load order to temp string."); | ||
| 431 | |||
| 432 | hr = StrAllocConcat(&pwzTemp, wzFilter, 0); | ||
| 433 | ExitOnFailure(hr, "Failed to copy filter into load order."); | ||
| 434 | |||
| 435 | hr = StrAllocConcat(&pwzTemp, pwz, 0); | ||
| 436 | ExitOnFailure(hr, "Failed to copy remaining filter load order back onto load order."); | ||
| 437 | |||
| 438 | hr = StrAllocString(ppwzLoadOrder, pwzTemp, 0); | ||
| 439 | ExitOnFailure(hr, "Failed to copy temp string to load order string."); | ||
| 440 | } | ||
| 441 | else // put the filter at the beginning of the order | ||
| 442 | { | ||
| 443 | hr = StrAllocPrefix(ppwzLoadOrder, L",", 1); | ||
| 444 | ExitOnFailure(hr, "Failed to prepend a comma to filter load order."); | ||
| 445 | |||
| 446 | hr = StrAllocPrefix(ppwzLoadOrder, wzFilter, cchFilter); | ||
| 447 | ExitOnFailure(hr, "Failed to prepend the filter on to the load order."); | ||
| 448 | } | ||
| 449 | } | ||
| 450 | } | ||
| 451 | else | ||
| 452 | { | ||
| 453 | hr = StrAllocString(ppwzLoadOrder, wzFilter, cchFilter); | ||
| 454 | ExitOnFailure(hr, "Failed to add filter to load order."); | ||
| 455 | } | ||
| 456 | |||
| 457 | LExit: | ||
| 458 | ReleaseStr(pwzTemp); | ||
| 459 | return hr; | ||
| 460 | } | ||
| 461 | |||
| 462 | |||
| 463 | static HRESULT RemoveFilterFromLoadOrder( | ||
| 464 | __in LPCWSTR wzFilter, | ||
| 465 | __inout LPWSTR *ppwzLoadOrder | ||
| 466 | ) | ||
| 467 | { | ||
| 468 | HRESULT hr = S_OK; | ||
| 469 | int cchFilter = lstrlenW(wzFilter); | ||
| 470 | |||
| 471 | LPCWSTR pwzStart = NULL; | ||
| 472 | LPWSTR pwzFind = NULL; | ||
| 473 | |||
| 474 | pwzStart = pwzFind = *ppwzLoadOrder; | ||
| 475 | while (NULL != (pwzFind = wcsstr(pwzFind, wzFilter))) | ||
| 476 | { | ||
| 477 | // Make sure to only match [wzFilter] and NOT foo[wzFilter]bar | ||
| 478 | if (pwzFind == pwzStart || L',' == *(pwzFind - 1)) | ||
| 479 | { | ||
| 480 | int cchRemainder = lstrlenW(pwzFind) - cchFilter + 1; // add one to include the null terminator | ||
| 481 | |||
| 482 | if (L'\0' == *(pwzFind + cchFilter)) | ||
| 483 | { | ||
| 484 | if (pwzFind == pwzStart) | ||
| 485 | { | ||
| 486 | memmove(pwzFind, pwzFind + cchFilter, cchRemainder * sizeof(WCHAR)); // copy down the null terminator | ||
| 487 | } | ||
| 488 | else | ||
| 489 | { | ||
| 490 | memmove(pwzFind - 1, pwzFind + cchFilter, cchRemainder * sizeof(WCHAR)); // copy down the null terminator over top the trailing "," | ||
| 491 | } | ||
| 492 | } | ||
| 493 | else if (L',' == *(pwzFind + cchFilter)) | ||
| 494 | { | ||
| 495 | memmove(pwzFind, pwzFind + cchFilter + 1, (cchRemainder - 1) * sizeof(WCHAR)); // skip copying the "," | ||
| 496 | } | ||
| 497 | else // skip past the partial match | ||
| 498 | { | ||
| 499 | pwzFind = pwzFind + cchFilter; | ||
| 500 | } | ||
| 501 | } | ||
| 502 | else // skip past the partial match | ||
| 503 | { | ||
| 504 | pwzFind = pwzFind + cchFilter; | ||
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 508 | //LExit: | ||
| 509 | return hr; | ||
| 510 | } | ||
diff --git a/src/ext/Iis/ca/scafilter.h b/src/ext/Iis/ca/scafilter.h new file mode 100644 index 00000000..d072bf22 --- /dev/null +++ b/src/ext/Iis/ca/scafilter.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scaweb.h" | ||
| 6 | |||
| 7 | enum eFilterQuery { fqWeb = 1, fqFilter, fqComponent , fqPath, fqDescription, fqFlags, fqLoadOrder, fqInstalled, fqAction }; | ||
| 8 | |||
| 9 | struct SCA_FILTER | ||
| 10 | { | ||
| 11 | // darwin information | ||
| 12 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 13 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 14 | INSTALLSTATE isInstalled; | ||
| 15 | INSTALLSTATE isAction; | ||
| 16 | |||
| 17 | // metabase information | ||
| 18 | WCHAR wzWebKey[MAX_DARWIN_KEY + 1]; | ||
| 19 | WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1]; | ||
| 20 | WCHAR wzFilterRoot[METADATA_MAX_NAME_LEN + 1]; | ||
| 21 | |||
| 22 | // iis configuation information | ||
| 23 | WCHAR wzPath[MAX_PATH]; | ||
| 24 | WCHAR wzDescription[MAX_DARWIN_COLUMN + 1]; | ||
| 25 | int iFlags; | ||
| 26 | int iLoadOrder; | ||
| 27 | |||
| 28 | SCA_FILTER* psfNext; | ||
| 29 | }; | ||
| 30 | |||
| 31 | |||
| 32 | // prototypes | ||
| 33 | HRESULT AddFilterToList( | ||
| 34 | __in SCA_FILTER** ppsfList | ||
| 35 | ); | ||
| 36 | |||
| 37 | UINT __stdcall ScaFiltersRead(IMSAdminBase* piMetabase, | ||
| 38 | SCA_WEB* pswList, __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, SCA_FILTER** ppsfList, | ||
| 39 | __inout LPWSTR *ppwzCustomActionData); | ||
| 40 | |||
| 41 | HRESULT ScaFiltersInstall(IMSAdminBase* piMetabase, SCA_FILTER* psfList); | ||
| 42 | |||
| 43 | HRESULT ScaFiltersUninstall(IMSAdminBase* piMetabase, SCA_FILTER* psfList); | ||
| 44 | |||
| 45 | void ScaFiltersFreeList(SCA_FILTER* psfList); | ||
| 46 | |||
diff --git a/src/ext/Iis/ca/scafilter7.cpp b/src/ext/Iis/ca/scafilter7.cpp new file mode 100644 index 00000000..dda91c4d --- /dev/null +++ b/src/ext/Iis/ca/scafilter7.cpp | |||
| @@ -0,0 +1,284 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | static HRESULT WriteFilter(const SCA_FILTER* psf); | ||
| 6 | |||
| 7 | UINT __stdcall ScaFiltersRead7( | ||
| 8 | __in SCA_WEB7* pswList, | ||
| 9 | __in WCA_WRAPQUERY_HANDLE /*hWebBaseQuery*/, | ||
| 10 | __inout SCA_FILTER** ppsfList, | ||
| 11 | __inout LPWSTR *ppwzCustomActionData | ||
| 12 | ) | ||
| 13 | { | ||
| 14 | HRESULT hr = S_OK; | ||
| 15 | MSIHANDLE hRec; | ||
| 16 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
| 17 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
| 18 | SCA_FILTER* psf; | ||
| 19 | |||
| 20 | LPWSTR pwzData = NULL; | ||
| 21 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 22 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 23 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 24 | |||
| 25 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 26 | { | ||
| 27 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaFiltersRead() - no IIsFilter table"); | ||
| 28 | ExitFunction1(hr = S_FALSE); | ||
| 29 | } | ||
| 30 | |||
| 31 | // loop through all the filters | ||
| 32 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 33 | { | ||
| 34 | // Get the Component first. If the component is not being modified during | ||
| 35 | // this transaction, skip processing this whole record. | ||
| 36 | // get the darwin information | ||
| 37 | hr = WcaGetRecordString(hRec, fqComponent, &pwzData); | ||
| 38 | ExitOnFailure(hr, "failed to get IIsFilter.Component"); | ||
| 39 | |||
| 40 | hr = WcaGetRecordInteger(hRec, fqInstalled, (int *)&isInstalled); | ||
| 41 | ExitOnFailure(hr, "Failed to get Component installed state for IIs filter"); | ||
| 42 | |||
| 43 | hr = WcaGetRecordInteger(hRec, fqAction, (int *)&isAction); | ||
| 44 | ExitOnFailure(hr, "Failed to get Component action state for IIs filter"); | ||
| 45 | |||
| 46 | if (!WcaIsInstalling(isInstalled, isAction) && | ||
| 47 | !WcaIsReInstalling(isInstalled, isAction) && | ||
| 48 | !WcaIsUninstalling(isInstalled, isAction)) | ||
| 49 | { | ||
| 50 | continue; // skip this record. | ||
| 51 | } | ||
| 52 | |||
| 53 | hr = AddFilterToList(ppsfList); | ||
| 54 | ExitOnFailure(hr, "failed to add filter to list"); | ||
| 55 | |||
| 56 | psf = *ppsfList; | ||
| 57 | |||
| 58 | hr = ::StringCchCopyW(psf->wzComponent, countof(psf->wzComponent), pwzData); | ||
| 59 | ExitOnFailure(hr, "failed to copy component name: %ls", pwzData); | ||
| 60 | |||
| 61 | psf->isInstalled = isInstalled; | ||
| 62 | psf->isAction = isAction; | ||
| 63 | |||
| 64 | hr = WcaGetRecordString(hRec, fqWeb, &pwzData); | ||
| 65 | ExitOnFailure(hr, "Failed to get Web for VirtualDir"); | ||
| 66 | |||
| 67 | if (*pwzData) | ||
| 68 | { | ||
| 69 | hr = ScaWebsGetBase7(pswList, pwzData, psf->wzFilterRoot, countof(psf->wzFilterRoot)); | ||
| 70 | if (FAILED(hr)) | ||
| 71 | { | ||
| 72 | WcaLog(LOGMSG_VERBOSE, "Could not find site for filter: %ls. Result 0x%x ", psf->wzFilterRoot, hr); | ||
| 73 | hr = S_OK; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | else | ||
| 77 | { | ||
| 78 | hr = ::StringCchCopyW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"/"); | ||
| 79 | ExitOnFailure(hr, "Failed to allocate global filter base string"); | ||
| 80 | } | ||
| 81 | |||
| 82 | // filter Name key | ||
| 83 | hr = WcaGetRecordString(hRec, fqFilter, &pwzData); | ||
| 84 | ExitOnFailure(hr, "Failed to get Filter.Filter"); | ||
| 85 | hr = ::StringCchCopyW(psf->wzKey, countof(psf->wzKey), pwzData); | ||
| 86 | ExitOnFailure(hr, "Failed to copy key string to filter object"); | ||
| 87 | |||
| 88 | // filter path | ||
| 89 | hr = WcaGetRecordString(hRec, fqPath, &pwzData); | ||
| 90 | ExitOnFailure(hr, "Failed to get Filter.Path"); | ||
| 91 | hr = ::StringCchCopyW(psf->wzPath, countof(psf->wzPath), pwzData); | ||
| 92 | ExitOnFailure(hr, "Failed to copy path string to filter object"); | ||
| 93 | |||
| 94 | // filter description -- not supported in iis 7 | ||
| 95 | hr = WcaGetRecordString(hRec, fqDescription, &pwzData); | ||
| 96 | ExitOnFailure(hr, "Failed to get Filter.Description"); | ||
| 97 | hr = ::StringCchCopyW(psf->wzDescription, countof(psf->wzDescription), pwzData); | ||
| 98 | ExitOnFailure(hr, "Failed to copy description string to filter object"); | ||
| 99 | |||
| 100 | // filter flags | ||
| 101 | //What are these | ||
| 102 | hr = WcaGetRecordInteger(hRec, fqFlags, &psf->iFlags); | ||
| 103 | ExitOnFailure(hr, "Failed to get Filter.Flags"); | ||
| 104 | |||
| 105 | // filter load order | ||
| 106 | hr = WcaGetRecordInteger(hRec, fqLoadOrder, &psf->iLoadOrder); | ||
| 107 | ExitOnFailure(hr, "Failed to get Filter.LoadOrder"); | ||
| 108 | } | ||
| 109 | |||
| 110 | if (E_NOMOREITEMS == hr) | ||
| 111 | { | ||
| 112 | hr = S_OK; | ||
| 113 | } | ||
| 114 | ExitOnFailure(hr, "Failure while processing filters"); | ||
| 115 | |||
| 116 | LExit: | ||
| 117 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 118 | |||
| 119 | ReleaseStr(pwzData); | ||
| 120 | |||
| 121 | return hr; | ||
| 122 | } | ||
| 123 | |||
| 124 | |||
| 125 | HRESULT ScaFiltersInstall7( | ||
| 126 | __in SCA_FILTER* psfList | ||
| 127 | ) | ||
| 128 | { | ||
| 129 | HRESULT hr = S_OK; | ||
| 130 | SCA_FILTER* psf = psfList; | ||
| 131 | |||
| 132 | if (!psf) | ||
| 133 | { | ||
| 134 | ExitFunction(); | ||
| 135 | } | ||
| 136 | //write global filters | ||
| 137 | hr = ScaWriteConfigID(IIS_FILTER_GLOBAL_BEGIN); | ||
| 138 | ExitOnFailure(hr, "Failed to write filter begin ID"); | ||
| 139 | while (psf) | ||
| 140 | { | ||
| 141 | if (WcaIsInstalling(psf->isInstalled, psf->isAction)) | ||
| 142 | { | ||
| 143 | if (0 == wcscmp(psf->wzFilterRoot, L"/")) | ||
| 144 | { | ||
| 145 | hr = WriteFilter(psf); | ||
| 146 | } | ||
| 147 | } | ||
| 148 | psf = psf->psfNext; | ||
| 149 | } | ||
| 150 | hr = ScaWriteConfigID(IIS_FILTER_END); | ||
| 151 | ExitOnFailure(hr, "Failed to write filter ID"); | ||
| 152 | |||
| 153 | psf = psfList; | ||
| 154 | |||
| 155 | //Write Web Site Filters | ||
| 156 | hr = ScaWriteConfigID(IIS_FILTER_BEGIN); | ||
| 157 | ExitOnFailure(hr, "Failed to write filter begin ID"); | ||
| 158 | while (psf) | ||
| 159 | { | ||
| 160 | if (WcaIsInstalling(psf->isInstalled, psf->isAction)) | ||
| 161 | { | ||
| 162 | if (0 != wcscmp(psf->wzFilterRoot, L"/")) | ||
| 163 | { | ||
| 164 | hr = WriteFilter(psf); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | psf = psf->psfNext; | ||
| 168 | } | ||
| 169 | hr = ScaWriteConfigID(IIS_FILTER_END); | ||
| 170 | ExitOnFailure(hr, "Failed to write filter ID"); | ||
| 171 | |||
| 172 | LExit: | ||
| 173 | |||
| 174 | return hr; | ||
| 175 | } | ||
| 176 | static HRESULT WriteFilter(const SCA_FILTER* psf) | ||
| 177 | { | ||
| 178 | HRESULT hr = S_OK; | ||
| 179 | |||
| 180 | hr = ScaWriteConfigID(IIS_FILTER); | ||
| 181 | ExitOnFailure(hr, "Failed to write filter begin ID"); | ||
| 182 | |||
| 183 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 184 | ExitOnFailure(hr, "Failed to write filter create ID"); | ||
| 185 | |||
| 186 | //filter Name key | ||
| 187 | hr = ScaWriteConfigString(psf->wzKey); | ||
| 188 | ExitOnFailure(hr, "Failed to write key name for filter '%ls'", psf->wzKey); | ||
| 189 | |||
| 190 | //web site name | ||
| 191 | hr = ScaWriteConfigString(psf->wzFilterRoot); | ||
| 192 | ExitOnFailure(hr, "Failed to write filter web root "); | ||
| 193 | |||
| 194 | // filter path | ||
| 195 | hr = ScaWriteConfigString(psf->wzPath); | ||
| 196 | ExitOnFailure(hr, "Failed to write Path for filter '%ls'", psf->wzKey); | ||
| 197 | |||
| 198 | //filter load order | ||
| 199 | hr = ScaWriteConfigInteger(psf->iLoadOrder); | ||
| 200 | ExitOnFailure(hr, "Failed to write load order for filter '%ls'", psf->wzKey); | ||
| 201 | |||
| 202 | LExit: | ||
| 203 | return hr; | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | HRESULT ScaFiltersUninstall7( | ||
| 208 | __in SCA_FILTER* psfList | ||
| 209 | ) | ||
| 210 | { | ||
| 211 | HRESULT hr = S_OK; | ||
| 212 | SCA_FILTER* psf = psfList; | ||
| 213 | |||
| 214 | if (!psf) | ||
| 215 | { | ||
| 216 | ExitFunction1(hr = S_OK); | ||
| 217 | } | ||
| 218 | |||
| 219 | //Uninstall global filters | ||
| 220 | hr = ScaWriteConfigID(IIS_FILTER_GLOBAL_BEGIN); | ||
| 221 | ExitOnFailure(hr, "Failed to write filter begin ID"); | ||
| 222 | |||
| 223 | while (psf) | ||
| 224 | { | ||
| 225 | if (WcaIsUninstalling(psf->isInstalled, psf->isAction)) | ||
| 226 | { | ||
| 227 | if (0 == wcscmp(psf->wzFilterRoot, L"/")) | ||
| 228 | { | ||
| 229 | hr = ScaWriteConfigID(IIS_FILTER); | ||
| 230 | ExitOnFailure(hr, "Failed to write filter begin ID"); | ||
| 231 | |||
| 232 | hr = ScaWriteConfigID(IIS_DELETE); | ||
| 233 | ExitOnFailure(hr, "Failed to write filter create ID"); | ||
| 234 | |||
| 235 | //filter Name key | ||
| 236 | hr = ScaWriteConfigString(psf->wzKey); | ||
| 237 | ExitOnFailure(hr, "Failed to write key name for filter '%ls'", psf->wzKey); | ||
| 238 | |||
| 239 | //web site name | ||
| 240 | hr = ScaWriteConfigString(psf->wzFilterRoot); | ||
| 241 | ExitOnFailure(hr, "Failed to write filter web root "); | ||
| 242 | |||
| 243 | } | ||
| 244 | } | ||
| 245 | psf = psf->psfNext; | ||
| 246 | } | ||
| 247 | |||
| 248 | hr = ScaWriteConfigID(IIS_FILTER_END); | ||
| 249 | ExitOnFailure(hr, "Failed to write filter ID"); | ||
| 250 | |||
| 251 | psf = psfList; | ||
| 252 | |||
| 253 | //Uninstall website filters | ||
| 254 | hr = ScaWriteConfigID(IIS_FILTER_BEGIN); | ||
| 255 | ExitOnFailure(hr, "Failed to write filter begin ID"); | ||
| 256 | while (psf) | ||
| 257 | { | ||
| 258 | if (WcaIsUninstalling(psf->isInstalled, psf->isAction)) | ||
| 259 | { | ||
| 260 | if (0 != wcscmp(psf->wzFilterRoot, L"/")) | ||
| 261 | { | ||
| 262 | hr = ScaWriteConfigID(IIS_FILTER); | ||
| 263 | ExitOnFailure(hr, "Failed to write filter begin ID"); | ||
| 264 | |||
| 265 | hr = ScaWriteConfigID(IIS_DELETE); | ||
| 266 | ExitOnFailure(hr, "Failed to write filter create ID"); | ||
| 267 | |||
| 268 | //filter Name key | ||
| 269 | hr = ScaWriteConfigString(psf->wzKey); | ||
| 270 | ExitOnFailure(hr, "Failed to write key name for filter '%ls'", psf->wzKey); | ||
| 271 | |||
| 272 | //web site name | ||
| 273 | hr = ScaWriteConfigString(psf->wzFilterRoot); | ||
| 274 | ExitOnFailure(hr, "Failed to write filter web root "); | ||
| 275 | } | ||
| 276 | } | ||
| 277 | psf = psf->psfNext; | ||
| 278 | } | ||
| 279 | hr = ScaWriteConfigID(IIS_FILTER_END); | ||
| 280 | ExitOnFailure(hr, "Failed to write filter ID"); | ||
| 281 | |||
| 282 | LExit: | ||
| 283 | return hr; | ||
| 284 | } | ||
diff --git a/src/ext/Iis/ca/scafilter7.h b/src/ext/Iis/ca/scafilter7.h new file mode 100644 index 00000000..50ff6652 --- /dev/null +++ b/src/ext/Iis/ca/scafilter7.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scaweb.h" | ||
| 6 | |||
| 7 | // prototypes | ||
| 8 | UINT __stdcall ScaFiltersRead7( | ||
| 9 | __in SCA_WEB7* pswList, | ||
| 10 | __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, | ||
| 11 | __inout SCA_FILTER** ppsfList, | ||
| 12 | __inout LPWSTR *ppwzCustomActionData | ||
| 13 | ); | ||
| 14 | |||
| 15 | HRESULT ScaFiltersInstall7( | ||
| 16 | SCA_FILTER* psfList | ||
| 17 | ); | ||
| 18 | |||
| 19 | HRESULT ScaFiltersUninstall7( | ||
| 20 | SCA_FILTER* psfList | ||
| 21 | ); | ||
diff --git a/src/ext/Iis/ca/scahttpheader.cpp b/src/ext/Iis/ca/scahttpheader.cpp new file mode 100644 index 00000000..1e134cea --- /dev/null +++ b/src/ext/Iis/ca/scahttpheader.cpp | |||
| @@ -0,0 +1,323 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | enum eHttpHeaderQuery { hhqName = 1, hhqParentType, hhqParentValue, hhqValue, hhqAttributes}; | ||
| 6 | |||
| 7 | static HRESULT AddHttpHeaderToList( | ||
| 8 | __in SCA_HTTP_HEADER** ppshhList | ||
| 9 | ); | ||
| 10 | |||
| 11 | |||
| 12 | void ScaHttpHeaderFreeList( | ||
| 13 | __in SCA_HTTP_HEADER* pshhList | ||
| 14 | ) | ||
| 15 | { | ||
| 16 | SCA_HTTP_HEADER* pshhDelete = pshhList; | ||
| 17 | while (pshhList) | ||
| 18 | { | ||
| 19 | pshhDelete = pshhList; | ||
| 20 | pshhList = pshhList->pshhNext; | ||
| 21 | |||
| 22 | MemFree(pshhDelete); | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | |||
| 27 | HRESULT ScaHttpHeaderRead( | ||
| 28 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 29 | __inout LPWSTR *ppwzCustomActionData | ||
| 30 | ) | ||
| 31 | { | ||
| 32 | Assert(ppshhList); | ||
| 33 | |||
| 34 | HRESULT hr = S_OK; | ||
| 35 | MSIHANDLE hRec; | ||
| 36 | LPWSTR pwzData = NULL; | ||
| 37 | SCA_HTTP_HEADER* pshh = NULL; | ||
| 38 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 39 | |||
| 40 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 41 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 42 | |||
| 43 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 44 | { | ||
| 45 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaHttpHeaderRead() - required tables not present."); | ||
| 46 | ExitFunction1(hr = S_FALSE); | ||
| 47 | } | ||
| 48 | |||
| 49 | // loop through all the HTTP headers | ||
| 50 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 51 | { | ||
| 52 | hr = AddHttpHeaderToList(ppshhList); | ||
| 53 | ExitOnFailure(hr, "failed to add http header to list"); | ||
| 54 | |||
| 55 | pshh = *ppshhList; | ||
| 56 | |||
| 57 | hr = WcaGetRecordInteger(hRec, hhqParentType, &(pshh->iParentType)); | ||
| 58 | ExitOnFailure(hr, "failed to get IIsHttpHeader.ParentType"); | ||
| 59 | |||
| 60 | hr = WcaGetRecordString(hRec, hhqParentValue, &pwzData); | ||
| 61 | ExitOnFailure(hr, "Failed to get IIsHttpHeader.ParentValue"); | ||
| 62 | hr = ::StringCchCopyW(pshh->wzParentValue, countof(pshh->wzParentValue), pwzData); | ||
| 63 | ExitOnFailure(hr, "Failed to copy IIsHttpHeader.ParentValue"); | ||
| 64 | |||
| 65 | hr = WcaGetRecordString(hRec, hhqName, &pwzData); | ||
| 66 | ExitOnFailure(hr, "Failed to get IIsHttpHeader.Name"); | ||
| 67 | hr = ::StringCchCopyW(pshh->wzName, countof(pshh->wzName), pwzData); | ||
| 68 | ExitOnFailure(hr, "Failed to copy IIsHttpHeader.Name"); | ||
| 69 | |||
| 70 | hr = WcaGetRecordString(hRec, hhqValue, &pwzData); | ||
| 71 | ExitOnFailure(hr, "Failed to get IIsHttpHeader.Value"); | ||
| 72 | hr = ::StringCchCopyW(pshh->wzValue, countof(pshh->wzValue), pwzData); | ||
| 73 | ExitOnFailure(hr, "Failed to copy IIsHttpHeader.Value"); | ||
| 74 | |||
| 75 | hr = WcaGetRecordInteger(hRec, hhqAttributes, &(pshh->iAttributes)); | ||
| 76 | ExitOnFailure(hr, "failed to get IIsHttpHeader.Attributes"); | ||
| 77 | } | ||
| 78 | |||
| 79 | if (E_NOMOREITEMS == hr) | ||
| 80 | { | ||
| 81 | hr = S_OK; | ||
| 82 | } | ||
| 83 | ExitOnFailure(hr, "Failure while processing web errors"); | ||
| 84 | |||
| 85 | LExit: | ||
| 86 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 87 | |||
| 88 | ReleaseStr(pwzData); | ||
| 89 | |||
| 90 | return hr; | ||
| 91 | } | ||
| 92 | |||
| 93 | |||
| 94 | HRESULT ScaGetHttpHeader( | ||
| 95 | __in int iParentType, | ||
| 96 | __in LPCWSTR wzParentValue, | ||
| 97 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 98 | __out SCA_HTTP_HEADER** ppshhOut | ||
| 99 | ) | ||
| 100 | { | ||
| 101 | HRESULT hr = S_OK; | ||
| 102 | SCA_HTTP_HEADER* pshhAdd = NULL; | ||
| 103 | SCA_HTTP_HEADER* pshhLast = NULL; | ||
| 104 | |||
| 105 | *ppshhOut = NULL; | ||
| 106 | |||
| 107 | if (!*ppshhList) | ||
| 108 | { | ||
| 109 | return hr; | ||
| 110 | } | ||
| 111 | |||
| 112 | SCA_HTTP_HEADER* pshh = *ppshhList; | ||
| 113 | while (pshh) | ||
| 114 | { | ||
| 115 | if (iParentType == pshh->iParentType && CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, wzParentValue, -1, pshh->wzParentValue, -1)) | ||
| 116 | { | ||
| 117 | // Found a match, take this one out of the list and add it to the matched out list | ||
| 118 | pshhAdd = pshh; | ||
| 119 | |||
| 120 | if (pshhLast) | ||
| 121 | { | ||
| 122 | // If we're not at the beginning of the list tell the last node about it's new next (since we're taking away it's current next) | ||
| 123 | pshhLast->pshhNext = pshhAdd->pshhNext; | ||
| 124 | } | ||
| 125 | else | ||
| 126 | { | ||
| 127 | // If we are at the beginning (no pshhLast) update the beginning (since we're taking it) | ||
| 128 | *ppshhList = pshh->pshhNext; | ||
| 129 | } | ||
| 130 | pshh = pshh->pshhNext; // move on | ||
| 131 | |||
| 132 | // Add the one we've removed to the beginning of the out list | ||
| 133 | pshhAdd->pshhNext = *ppshhOut; | ||
| 134 | *ppshhOut = pshhAdd; | ||
| 135 | } | ||
| 136 | else | ||
| 137 | { | ||
| 138 | pshhLast = pshh; // remember the last we that didn't match | ||
| 139 | pshh = pshh->pshhNext; // move on | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | return hr; | ||
| 144 | } | ||
| 145 | |||
| 146 | |||
| 147 | HRESULT ScaWriteHttpHeader( | ||
| 148 | __in IMSAdminBase* piMetabase, | ||
| 149 | __in LPCWSTR wzRoot, | ||
| 150 | __in SCA_HTTP_HEADER* pshhList | ||
| 151 | ) | ||
| 152 | { | ||
| 153 | Assert(piMetabase && pshhList); | ||
| 154 | |||
| 155 | HRESULT hr = S_OK; | ||
| 156 | METADATA_RECORD mr = { 0 }; | ||
| 157 | DWORD cchData = 0; | ||
| 158 | LPWSTR pwzSearchKey = NULL; | ||
| 159 | LPWSTR pwz = NULL; | ||
| 160 | LPWSTR pwzHeaders = NULL; | ||
| 161 | LPWSTR pwzNewHeader = NULL; | ||
| 162 | DWORD_PTR dwFoundHeaderIndex = 0; | ||
| 163 | LPCWSTR wzFoundHeader = NULL; | ||
| 164 | BOOL fOldValueFound = FALSE; | ||
| 165 | |||
| 166 | ExitOnNull(wzRoot, hr, E_INVALIDARG, "Failed to write HTTP header, because no root was provided"); | ||
| 167 | |||
| 168 | Assert(*wzRoot); | ||
| 169 | |||
| 170 | // Check if HTTP header already exist here. | ||
| 171 | mr.dwMDIdentifier = MD_HTTP_CUSTOM; | ||
| 172 | mr.dwMDAttributes = METADATA_INHERIT; | ||
| 173 | mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 174 | mr.dwMDDataType = ALL_METADATA; | ||
| 175 | mr.dwMDDataLen = cchData = 0; | ||
| 176 | mr.pbMDData = NULL; | ||
| 177 | |||
| 178 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzRoot, &mr); | ||
| 179 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr) | ||
| 180 | { | ||
| 181 | // | ||
| 182 | // If we don't have any HTTP Headers already, move up to get the parent headers. | ||
| 183 | // TODO: Make it configurable to not inherit HTTP Headers | ||
| 184 | // | ||
| 185 | hr = StrAllocConcat(&pwzSearchKey, wzRoot, 0); | ||
| 186 | ExitOnFailure(hr, "Failed to copy root string: %ls", wzRoot); | ||
| 187 | |||
| 188 | pwz = pwzSearchKey + lstrlenW(pwzSearchKey); | ||
| 189 | while (NULL == pwzHeaders) | ||
| 190 | { | ||
| 191 | // find the last slash | ||
| 192 | while (*pwz != '/' && pwz != pwzSearchKey) | ||
| 193 | { | ||
| 194 | --pwz; | ||
| 195 | } | ||
| 196 | |||
| 197 | if (pwz == pwzSearchKey) | ||
| 198 | { | ||
| 199 | break; | ||
| 200 | } | ||
| 201 | |||
| 202 | *pwz = L'\0'; | ||
| 203 | |||
| 204 | // Try here. If it's not found, keep walking up the path | ||
| 205 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, pwzSearchKey, &mr); | ||
| 206 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr) | ||
| 207 | { | ||
| 208 | hr = S_FALSE; | ||
| 209 | } | ||
| 210 | ExitOnFailure(hr, "Failed to find search for HTTP headers for web root: %ls while walking up the tree", wzRoot); | ||
| 211 | |||
| 212 | if (S_OK == hr) | ||
| 213 | { | ||
| 214 | hr = StrAllocString(&pwzHeaders, reinterpret_cast<LPWSTR>(mr.pbMDData), 0); | ||
| 215 | ExitOnFailure(hr, "Failed to allocate parent HTTP header string"); | ||
| 216 | break; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | } | ||
| 220 | else | ||
| 221 | { | ||
| 222 | hr = StrAllocString(&pwzHeaders, reinterpret_cast<LPWSTR>(mr.pbMDData), 0); | ||
| 223 | ExitOnFailure(hr, "Failed to allocate HTTP header string"); | ||
| 224 | } | ||
| 225 | ExitOnFailure(hr, "Failed while searching for default HTTP headers to start with for web root: %ls", wzRoot); | ||
| 226 | |||
| 227 | // Loop through the HTTP headers | ||
| 228 | for (SCA_HTTP_HEADER* pshh = pshhList; pshh; pshh = pshh->pshhNext) | ||
| 229 | { | ||
| 230 | fOldValueFound = FALSE; // assume a HTTP Header match will not be found | ||
| 231 | |||
| 232 | hr = StrAllocFormatted(&pwzNewHeader, L"%s: ", pshh->wzName); | ||
| 233 | ExitOnFailure(hr, "Failed to allocate header name"); | ||
| 234 | |||
| 235 | if (NULL != pwzHeaders && *pwzHeaders) | ||
| 236 | { | ||
| 237 | // Try to find a matching header already in the list | ||
| 238 | hr = MultiSzFindSubstring(pwzHeaders, pwzNewHeader, &dwFoundHeaderIndex, &wzFoundHeader); | ||
| 239 | ExitOnFailure(hr, "Failed while searching for existing HTTP header."); | ||
| 240 | |||
| 241 | // If there was a substring HTTP header match, make sure the match was at the beginning | ||
| 242 | // of the string because that is the HTTP header name. | ||
| 243 | if (S_OK == hr) | ||
| 244 | { | ||
| 245 | DWORD cchMatch = lstrlenW(pwzNewHeader); | ||
| 246 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, pwzNewHeader, cchMatch, wzFoundHeader, cchMatch)) | ||
| 247 | { | ||
| 248 | fOldValueFound = TRUE; | ||
| 249 | break; | ||
| 250 | } | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | // Add the value on to the header name now. | ||
| 255 | hr = StrAllocConcat(&pwzNewHeader, pshh->wzValue, 0); | ||
| 256 | ExitOnFailure(hr, "Failed to add value on to HTTP header name."); | ||
| 257 | |||
| 258 | // If we have something to replace, replace it, otherwise, put it at the beginning (order shouldn't matter) | ||
| 259 | if (fOldValueFound) | ||
| 260 | { | ||
| 261 | if (NULL == pwzHeaders) | ||
| 262 | { | ||
| 263 | ExitOnFailure(hr = E_INVALIDARG, "While attempting to replace old HTTP header with new HTTP header, it was discovered that the old HTTP header was NULL!"); | ||
| 264 | } | ||
| 265 | hr = MultiSzReplaceString(&pwzHeaders, dwFoundHeaderIndex, pwzNewHeader); | ||
| 266 | ExitOnFailure(hr, "Failed to replace old HTTP header with new HTTP header"); | ||
| 267 | } | ||
| 268 | else | ||
| 269 | { | ||
| 270 | hr = MultiSzPrepend(&pwzHeaders, NULL, pwzNewHeader); | ||
| 271 | ExitOnFailure(hr, "Failed to prepend new HTTP header"); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | // now write the HttpCustom to the metabase | ||
| 276 | hr = ScaWriteMetabaseValue(piMetabase, wzRoot, NULL, MD_HTTP_CUSTOM, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzHeaders); | ||
| 277 | ExitOnFailure(hr, "Failed to write HTTP Headers to metabase"); | ||
| 278 | |||
| 279 | LExit: | ||
| 280 | MetaFreeValue(&mr); | ||
| 281 | |||
| 282 | ReleaseStr(pwzNewHeader); | ||
| 283 | ReleaseStr(pwzHeaders); | ||
| 284 | ReleaseStr(pwzSearchKey); | ||
| 285 | |||
| 286 | return hr; | ||
| 287 | } | ||
| 288 | |||
| 289 | |||
| 290 | HRESULT ScaHttpHeaderCheckList( | ||
| 291 | __in SCA_HTTP_HEADER* pshhList | ||
| 292 | ) | ||
| 293 | { | ||
| 294 | if (!pshhList) | ||
| 295 | { | ||
| 296 | return S_OK; | ||
| 297 | } | ||
| 298 | |||
| 299 | while (pshhList) | ||
| 300 | { | ||
| 301 | WcaLog(LOGMSG_STANDARD, "Http Header: %ls for parent: %ls not used!", pshhList->wzName, pshhList->wzParentValue); | ||
| 302 | pshhList = pshhList->pshhNext; | ||
| 303 | } | ||
| 304 | |||
| 305 | return E_FAIL; | ||
| 306 | } | ||
| 307 | |||
| 308 | |||
| 309 | static HRESULT AddHttpHeaderToList( | ||
| 310 | __in SCA_HTTP_HEADER** ppshhList | ||
| 311 | ) | ||
| 312 | { | ||
| 313 | HRESULT hr = S_OK; | ||
| 314 | |||
| 315 | SCA_HTTP_HEADER* pshh = static_cast<SCA_HTTP_HEADER*>(MemAlloc(sizeof(SCA_HTTP_HEADER), TRUE)); | ||
| 316 | ExitOnNull(pshh, hr, E_OUTOFMEMORY, "failed to allocate memory for new http header list element"); | ||
| 317 | |||
| 318 | pshh->pshhNext = *ppshhList; | ||
| 319 | *ppshhList = pshh; | ||
| 320 | |||
| 321 | LExit: | ||
| 322 | return hr; | ||
| 323 | } | ||
diff --git a/src/ext/Iis/ca/scahttpheader.h b/src/ext/Iis/ca/scahttpheader.h new file mode 100644 index 00000000..a4c407a4 --- /dev/null +++ b/src/ext/Iis/ca/scahttpheader.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | enum eHttpHeaderParentType { hhptVDir = 1, hhptWeb }; | ||
| 6 | |||
| 7 | struct SCA_HTTP_HEADER | ||
| 8 | { | ||
| 9 | int iParentType; | ||
| 10 | WCHAR wzParentValue[MAX_DARWIN_KEY + 1]; | ||
| 11 | |||
| 12 | WCHAR wzName[MAX_PATH]; | ||
| 13 | WCHAR wzValue[MAX_PATH]; | ||
| 14 | int iAttributes; | ||
| 15 | |||
| 16 | SCA_HTTP_HEADER* pshhNext; | ||
| 17 | }; | ||
| 18 | |||
| 19 | // prototypes | ||
| 20 | HRESULT ScaHttpHeaderRead( | ||
| 21 | __in SCA_HTTP_HEADER **ppshhList, | ||
| 22 | __inout LPWSTR *ppwzCustomActionData | ||
| 23 | ); | ||
| 24 | void ScaHttpHeaderFreeList( | ||
| 25 | __in SCA_HTTP_HEADER *pshhList | ||
| 26 | ); | ||
| 27 | HRESULT ScaHttpHeaderCheckList( | ||
| 28 | __in SCA_HTTP_HEADER* pshhList | ||
| 29 | ); | ||
| 30 | HRESULT ScaGetHttpHeader( | ||
| 31 | __in int iParentType, | ||
| 32 | __in LPCWSTR wzParentValue, | ||
| 33 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 34 | __out SCA_HTTP_HEADER** ppshhOut | ||
| 35 | ); | ||
| 36 | HRESULT ScaWriteHttpHeader( | ||
| 37 | __in IMSAdminBase* piMetabase, | ||
| 38 | LPCWSTR wzRoot, | ||
| 39 | SCA_HTTP_HEADER* pshhList | ||
| 40 | ); | ||
diff --git a/src/ext/Iis/ca/scahttpheader7.cpp b/src/ext/Iis/ca/scahttpheader7.cpp new file mode 100644 index 00000000..645dd8d4 --- /dev/null +++ b/src/ext/Iis/ca/scahttpheader7.cpp | |||
| @@ -0,0 +1,130 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | HRESULT ScaGetHttpHeader7( | ||
| 6 | __in int iParentType, | ||
| 7 | __in_z LPCWSTR wzParentValue, | ||
| 8 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 9 | __out SCA_HTTP_HEADER** ppshhOut | ||
| 10 | ) | ||
| 11 | { | ||
| 12 | HRESULT hr = S_OK; | ||
| 13 | SCA_HTTP_HEADER* pshhAdd = NULL; | ||
| 14 | SCA_HTTP_HEADER* pshhLast = NULL; | ||
| 15 | |||
| 16 | *ppshhOut = NULL; | ||
| 17 | |||
| 18 | if (!*ppshhList) | ||
| 19 | { | ||
| 20 | return hr; | ||
| 21 | } | ||
| 22 | |||
| 23 | SCA_HTTP_HEADER* pshh = *ppshhList; | ||
| 24 | while (pshh) | ||
| 25 | { | ||
| 26 | if (iParentType == pshh->iParentType && 0 == wcscmp(wzParentValue, pshh->wzParentValue)) | ||
| 27 | { | ||
| 28 | // Found a match, take this one out of the list and add it to the matched out list | ||
| 29 | pshhAdd = pshh; | ||
| 30 | |||
| 31 | if (pshhLast) | ||
| 32 | { | ||
| 33 | // If we're not at the beginning of the list tell the last node about it's new next (since we're taking away it's current next) | ||
| 34 | pshhLast->pshhNext = pshhAdd->pshhNext; | ||
| 35 | } | ||
| 36 | else | ||
| 37 | { | ||
| 38 | // If we are at the beginning (no pshhLast) update the beginning (since we're taking it) | ||
| 39 | *ppshhList = pshh->pshhNext; | ||
| 40 | } | ||
| 41 | pshh = pshh->pshhNext; // move on | ||
| 42 | |||
| 43 | // Add the one we've removed to the beginning of the out list | ||
| 44 | pshhAdd->pshhNext = *ppshhOut; | ||
| 45 | *ppshhOut = pshhAdd; | ||
| 46 | } | ||
| 47 | else | ||
| 48 | { | ||
| 49 | pshhLast = pshh; // remember the last we that didn't match | ||
| 50 | pshh = pshh->pshhNext; // move on | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | return hr; | ||
| 55 | } | ||
| 56 | |||
| 57 | |||
| 58 | HRESULT ScaWriteHttpHeader7( | ||
| 59 | __in_z LPCWSTR wzWebName, | ||
| 60 | __in_z LPCWSTR wzRoot, | ||
| 61 | SCA_HTTP_HEADER* pshhList | ||
| 62 | ) | ||
| 63 | { | ||
| 64 | |||
| 65 | HRESULT hr = S_OK; | ||
| 66 | |||
| 67 | hr = ScaWriteConfigID(IIS_HTTP_HEADER_BEGIN); | ||
| 68 | ExitOnFailure(hr, "Fail to write httpHeader begin ID"); | ||
| 69 | |||
| 70 | hr = ScaWriteConfigString(wzWebName); | ||
| 71 | ExitOnFailure(hr, "Fail to write httpHeader Web Key"); | ||
| 72 | |||
| 73 | hr = ScaWriteConfigString(wzRoot); | ||
| 74 | ExitOnFailure(hr, "Fail to write httpHeader Vdir key"); | ||
| 75 | |||
| 76 | // Loop through the HTTP headers | ||
| 77 | for (SCA_HTTP_HEADER* pshh = pshhList; pshh; pshh = pshh->pshhNext) | ||
| 78 | { | ||
| 79 | hr = ScaWriteConfigID(IIS_HTTP_HEADER); | ||
| 80 | ExitOnFailure(hr, "Fail to write httpHeader ID"); | ||
| 81 | |||
| 82 | hr = ScaWriteConfigString(pshh->wzName); | ||
| 83 | ExitOnFailure(hr, "Fail to write httpHeader name"); | ||
| 84 | |||
| 85 | hr = ScaWriteConfigString(pshh->wzValue); | ||
| 86 | ExitOnFailure(hr, "Fail to write httpHeader value"); | ||
| 87 | } | ||
| 88 | |||
| 89 | hr = ScaWriteConfigID(IIS_HTTP_HEADER_END); | ||
| 90 | ExitOnFailure(hr, "Fail to write httpHeader end ID"); | ||
| 91 | |||
| 92 | LExit: | ||
| 93 | return hr; | ||
| 94 | } | ||
| 95 | |||
| 96 | |||
| 97 | HRESULT ScaHttpHeaderCheckList7( | ||
| 98 | __in SCA_HTTP_HEADER* pshhList | ||
| 99 | ) | ||
| 100 | { | ||
| 101 | if (!pshhList) | ||
| 102 | { | ||
| 103 | return S_OK; | ||
| 104 | } | ||
| 105 | |||
| 106 | while (pshhList) | ||
| 107 | { | ||
| 108 | WcaLog(LOGMSG_STANDARD, "Http Header: %ls for parent: %ls not used!", pshhList->wzName, pshhList->wzParentValue); | ||
| 109 | pshhList = pshhList->pshhNext; | ||
| 110 | } | ||
| 111 | |||
| 112 | return E_FAIL; | ||
| 113 | } | ||
| 114 | |||
| 115 | |||
| 116 | //static HRESULT AddHttpHeaderToList( | ||
| 117 | // __in SCA_HTTP_HEADER** ppshhList | ||
| 118 | // ) | ||
| 119 | //{ | ||
| 120 | // HRESULT hr = S_OK; | ||
| 121 | // | ||
| 122 | // SCA_HTTP_HEADER* pshh = static_cast<SCA_HTTP_HEADER*>(MemAlloc(sizeof(SCA_HTTP_HEADER), TRUE)); | ||
| 123 | // ExitOnNull(pshh, hr, E_OUTOFMEMORY, "failed to allocate memory for new http header list element"); | ||
| 124 | // | ||
| 125 | // pshh->pshhNext = *ppshhList; | ||
| 126 | // *ppshhList = pshh; | ||
| 127 | // | ||
| 128 | //LExit: | ||
| 129 | // return hr; | ||
| 130 | //} | ||
diff --git a/src/ext/Iis/ca/scahttpheader7.h b/src/ext/Iis/ca/scahttpheader7.h new file mode 100644 index 00000000..7a873c16 --- /dev/null +++ b/src/ext/Iis/ca/scahttpheader7.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaGetHttpHeader7( | ||
| 6 | __in int iParentType, | ||
| 7 | __in_z LPCWSTR wzParentValue, | ||
| 8 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 9 | __out SCA_HTTP_HEADER** ppshhOut | ||
| 10 | ); | ||
| 11 | HRESULT ScaWriteHttpHeader7( | ||
| 12 | __in_z LPCWSTR wzWebName, | ||
| 13 | __in_z LPCWSTR wzRoot, | ||
| 14 | SCA_HTTP_HEADER* pshhList | ||
| 15 | ); | ||
diff --git a/src/ext/Iis/ca/scaiis.cpp b/src/ext/Iis/ca/scaiis.cpp new file mode 100644 index 00000000..958051ed --- /dev/null +++ b/src/ext/Iis/ca/scaiis.cpp | |||
| @@ -0,0 +1,481 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // globals | ||
| 6 | LPWSTR vpwzCustomActionData = NULL; | ||
| 7 | DWORD vdwCustomActionCost = 0; | ||
| 8 | |||
| 9 | HRESULT ScaMetabaseTransaction(__in_z LPCWSTR wzBackup) | ||
| 10 | { | ||
| 11 | HRESULT hr = S_OK; | ||
| 12 | |||
| 13 | // TODO: These functions have been reported to hang IIS (O11:51709). They may have been fixed in IIS6, but if not, need to be re-written the hard way | ||
| 14 | |||
| 15 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"StartMetabaseTransaction"), wzBackup, COST_IIS_TRANSACTIONS); | ||
| 16 | ExitOnFailure(hr, "Failed to schedule StartMetabaseTransaction"); | ||
| 17 | |||
| 18 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackMetabaseTransaction"), wzBackup, 0); // rollback cost is irrelevant | ||
| 19 | ExitOnFailure(hr, "Failed to schedule RollbackMetabaseTransaction"); | ||
| 20 | |||
| 21 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CommitMetabaseTransaction"), wzBackup, 0); // commit is free | ||
| 22 | ExitOnFailure(hr, "Failed to schedule StartMetabaseTransaction"); | ||
| 23 | |||
| 24 | LExit: | ||
| 25 | return hr; | ||
| 26 | } | ||
| 27 | |||
| 28 | |||
| 29 | HRESULT ScaCreateWeb(IMSAdminBase* piMetabase, LPCWSTR /*wzWeb*/, LPCWSTR wzWebBase) | ||
| 30 | { | ||
| 31 | Assert(piMetabase); | ||
| 32 | |||
| 33 | HRESULT hr = S_OK; | ||
| 34 | UINT ui = 0; | ||
| 35 | |||
| 36 | hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L""); | ||
| 37 | ExitOnFailure(hr, "Failed to create web"); | ||
| 38 | |||
| 39 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebServer"); | ||
| 40 | ExitOnFailure(hr, "Failed to set key type for web"); | ||
| 41 | |||
| 42 | hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"Root"); | ||
| 43 | ExitOnFailure(hr, "Failed to create web root"); | ||
| 44 | |||
| 45 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Root", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebVirtualDir"); | ||
| 46 | ExitOnFailure(hr, "Failed to set key type for web root"); | ||
| 47 | |||
| 48 | ui = 0x4000003e; // 1073741886; // default directory browsing rights | ||
| 49 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Root", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui)); | ||
| 50 | ExitOnFailure(hr, "Failed to set directory browsing for web"); | ||
| 51 | |||
| 52 | hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"Filters"); | ||
| 53 | ExitOnFailure(hr, "Failed to create web filters root"); | ||
| 54 | |||
| 55 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Filters", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsFilters"); | ||
| 56 | ExitOnFailure(hr, "Failed to set key for web filters root"); | ||
| 57 | |||
| 58 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Filters", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L""); | ||
| 59 | ExitOnFailure(hr, "Failed to set empty load order for web"); | ||
| 60 | |||
| 61 | LExit: | ||
| 62 | return hr; | ||
| 63 | } | ||
| 64 | |||
| 65 | |||
| 66 | HRESULT ScaDeleteApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot) | ||
| 67 | { | ||
| 68 | Assert(piMetabase); | ||
| 69 | Unused(piMetabase); | ||
| 70 | |||
| 71 | HRESULT hr = S_OK; | ||
| 72 | WCHAR wzKey[METADATA_MAX_NAME_LEN]; | ||
| 73 | |||
| 74 | WCHAR* pwzCustomActionData = NULL; | ||
| 75 | |||
| 76 | hr = WcaWriteIntegerToCaData(MBA_DELETEAPP, &pwzCustomActionData); | ||
| 77 | ExitOnFailure(hr, "Failed to add metabase delete app directive to CustomActionData"); | ||
| 78 | |||
| 79 | hr = ::StringCchCopyW(wzKey, countof(wzKey), wzWebRoot); | ||
| 80 | ExitOnFailure(hr, "Failed to copy webroot string to key"); | ||
| 81 | hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData); | ||
| 82 | ExitOnFailure(hr, "Failed to add metabase key to CustomActionData"); | ||
| 83 | |||
| 84 | hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEAPP); | ||
| 85 | ExitOnFailure(hr, "Failed to add ScaDeleteApp action data: %ls cost: %d", pwzCustomActionData, COST_IIS_DELETEAPP); | ||
| 86 | |||
| 87 | LExit: | ||
| 88 | ReleaseStr(pwzCustomActionData); | ||
| 89 | |||
| 90 | return hr; | ||
| 91 | } | ||
| 92 | |||
| 93 | |||
| 94 | HRESULT ScaCreateApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot, | ||
| 95 | DWORD dwIsolation) | ||
| 96 | { | ||
| 97 | Assert(piMetabase); | ||
| 98 | Unused(piMetabase); | ||
| 99 | |||
| 100 | HRESULT hr = S_OK; | ||
| 101 | WCHAR wzKey[METADATA_MAX_NAME_LEN]; | ||
| 102 | BOOL fInProc = FALSE; | ||
| 103 | |||
| 104 | WCHAR* pwzCustomActionData = NULL; | ||
| 105 | |||
| 106 | hr = WcaWriteIntegerToCaData(MBA_CREATEAPP, &pwzCustomActionData); | ||
| 107 | ExitOnFailure(hr, "Failed to add metabase create app directive to CustomActionData"); | ||
| 108 | |||
| 109 | hr = ::StringCchCopyW(wzKey, countof(wzKey), wzWebRoot); | ||
| 110 | ExitOnFailure(hr, "Failed to copy webroot string to key"); | ||
| 111 | hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData); | ||
| 112 | ExitOnFailure(hr, "Failed to add metabase key to CustomActionData"); | ||
| 113 | |||
| 114 | if (0 == dwIsolation) | ||
| 115 | fInProc = TRUE; | ||
| 116 | else | ||
| 117 | fInProc = FALSE; | ||
| 118 | |||
| 119 | hr = WcaWriteIntegerToCaData(fInProc, &pwzCustomActionData); | ||
| 120 | ExitOnFailure(hr, "Failed to add isolation value to CustomActionData"); | ||
| 121 | |||
| 122 | hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_CREATEAPP); | ||
| 123 | ExitOnFailure(hr, "Failed to add ScaCreateApp action data: %ls cost: %d", pwzCustomActionData, COST_IIS_CREATEAPP); | ||
| 124 | |||
| 125 | LExit: | ||
| 126 | ReleaseStr(pwzCustomActionData); | ||
| 127 | |||
| 128 | return hr; | ||
| 129 | } | ||
| 130 | |||
| 131 | |||
| 132 | HRESULT ScaCreateMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey, | ||
| 133 | LPCWSTR wzSubKey) | ||
| 134 | { | ||
| 135 | Assert(piMetabase); | ||
| 136 | Unused(piMetabase); | ||
| 137 | |||
| 138 | HRESULT hr = S_OK; | ||
| 139 | WCHAR wzKey[METADATA_MAX_NAME_LEN]; | ||
| 140 | WCHAR* pwzCustomActionData = NULL; | ||
| 141 | |||
| 142 | hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey); | ||
| 143 | ExitOnFailure(hr, "Failed to copy root key string to key"); | ||
| 144 | if (L'/' != *(wzKey + lstrlenW(wzRootKey))) | ||
| 145 | { | ||
| 146 | hr = ::StringCchCatW(wzKey, countof(wzKey), L"/"); | ||
| 147 | ExitOnFailure(hr, "Failed to concatenate / to key string"); | ||
| 148 | } | ||
| 149 | if (wzSubKey && *wzSubKey) | ||
| 150 | { | ||
| 151 | if (L'/' == *wzSubKey) | ||
| 152 | { | ||
| 153 | hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1); | ||
| 154 | ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string"); | ||
| 155 | } | ||
| 156 | else | ||
| 157 | { | ||
| 158 | hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey); | ||
| 159 | ExitOnFailure(hr, "Failed to concatenate subkey to key string"); | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | hr = WcaWriteIntegerToCaData(MBA_CREATEKEY, &pwzCustomActionData); | ||
| 164 | ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData"); | ||
| 165 | |||
| 166 | hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData); | ||
| 167 | ExitOnFailure(hr, "Failed to add metabase key to CustomActionData"); | ||
| 168 | |||
| 169 | hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_CREATEKEY); | ||
| 170 | ExitOnFailure(hr, "Failed to add ScaCreateMetabaseKey action data: %ls cost: %d", pwzCustomActionData, COST_IIS_CREATEKEY); | ||
| 171 | |||
| 172 | LExit: | ||
| 173 | ReleaseStr(pwzCustomActionData); | ||
| 174 | |||
| 175 | return hr; | ||
| 176 | } | ||
| 177 | |||
| 178 | |||
| 179 | HRESULT ScaDeleteMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey, | ||
| 180 | LPCWSTR wzSubKey) | ||
| 181 | { | ||
| 182 | Assert(piMetabase); | ||
| 183 | Unused(piMetabase); | ||
| 184 | |||
| 185 | HRESULT hr = S_OK; | ||
| 186 | WCHAR wzKey[METADATA_MAX_NAME_LEN]; | ||
| 187 | WCHAR* pwzCustomActionData = NULL; | ||
| 188 | |||
| 189 | hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey); | ||
| 190 | ExitOnFailure(hr, "Failed to copy root key string to key"); | ||
| 191 | if (L'/' != *(wzKey + lstrlenW(wzRootKey))) | ||
| 192 | { | ||
| 193 | hr = ::StringCchCatW(wzKey, countof(wzKey), L"/"); | ||
| 194 | ExitOnFailure(hr, "Failed to concatenate / to key string"); | ||
| 195 | } | ||
| 196 | if (*wzSubKey) | ||
| 197 | { | ||
| 198 | if (L'/' == *wzSubKey) | ||
| 199 | { | ||
| 200 | hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1); | ||
| 201 | ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string"); | ||
| 202 | } | ||
| 203 | else | ||
| 204 | { | ||
| 205 | hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey); | ||
| 206 | ExitOnFailure(hr, "Failed to concatenate subkey to key string"); | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | hr = WcaWriteIntegerToCaData(MBA_DELETEKEY, &pwzCustomActionData); | ||
| 211 | ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData"); | ||
| 212 | |||
| 213 | hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData); | ||
| 214 | ExitOnFailure(hr, "Failed to add metabase key to CustomActionData"); | ||
| 215 | |||
| 216 | hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEKEY); | ||
| 217 | ExitOnFailure(hr, "Failed to add ScaDeleteMetabaseKey action data: %ls cost: %d", pwzCustomActionData, COST_IIS_DELETEKEY); | ||
| 218 | |||
| 219 | LExit: | ||
| 220 | ReleaseStr(pwzCustomActionData); | ||
| 221 | |||
| 222 | return hr; | ||
| 223 | } | ||
| 224 | |||
| 225 | |||
| 226 | HRESULT ScaDeleteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey, | ||
| 227 | LPCWSTR wzSubKey, DWORD dwIdentifier, | ||
| 228 | DWORD dwDataType) | ||
| 229 | { | ||
| 230 | Assert(piMetabase); | ||
| 231 | Unused(piMetabase); | ||
| 232 | |||
| 233 | HRESULT hr = S_OK; | ||
| 234 | WCHAR wzKey[METADATA_MAX_NAME_LEN]; | ||
| 235 | WCHAR* pwzCustomActionData = NULL; | ||
| 236 | |||
| 237 | hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey); | ||
| 238 | ExitOnFailure(hr, "Failed to copy root key string to key"); | ||
| 239 | if (L'/' != *(wzKey + lstrlenW(wzRootKey))) | ||
| 240 | { | ||
| 241 | hr = ::StringCchCatW(wzKey, countof(wzKey), L"/"); | ||
| 242 | ExitOnFailure(hr, "Failed to concatenate / to key string"); | ||
| 243 | } | ||
| 244 | |||
| 245 | if (wzSubKey && *wzSubKey) | ||
| 246 | { | ||
| 247 | if (L'/' == *wzSubKey) | ||
| 248 | { | ||
| 249 | hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1); | ||
| 250 | ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string"); | ||
| 251 | } | ||
| 252 | else | ||
| 253 | { | ||
| 254 | hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey); | ||
| 255 | ExitOnFailure(hr, "Failed to concatenate subkey to key string"); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | hr = WcaWriteIntegerToCaData(MBA_DELETEVALUE, &pwzCustomActionData); | ||
| 260 | ExitOnFailure(hr, "Failed to add metabase write value directive to CustomActionData"); | ||
| 261 | |||
| 262 | hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData); | ||
| 263 | ExitOnFailure(hr, "Failed to add metabase key to CustomActionData"); | ||
| 264 | |||
| 265 | hr = WcaWriteIntegerToCaData(dwIdentifier, &pwzCustomActionData); | ||
| 266 | ExitOnFailure(hr, "Failed to add metabase identifier to CustomActionData"); | ||
| 267 | |||
| 268 | hr = WcaWriteIntegerToCaData(dwDataType, &pwzCustomActionData); | ||
| 269 | ExitOnFailure(hr, "Failed to add metabase data type to CustomActionData"); | ||
| 270 | |||
| 271 | hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEVALUE); | ||
| 272 | ExitOnFailure(hr, "Failed to add ScaDeleteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_DELETEVALUE); | ||
| 273 | |||
| 274 | LExit: | ||
| 275 | ReleaseStr(pwzCustomActionData); | ||
| 276 | |||
| 277 | return hr; | ||
| 278 | } | ||
| 279 | |||
| 280 | |||
| 281 | #pragma prefast(push) | ||
| 282 | #pragma prefast(disable:25120) // Disable "requires count parameter" warning - we do have a way to distinguish buffer sizes in all situations, | ||
| 283 | // it just depends on the dwDataType, and there's no way to annotate the situation in SAL | ||
| 284 | HRESULT ScaWriteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey, | ||
| 285 | LPCWSTR wzSubKey, DWORD dwIdentifier, | ||
| 286 | DWORD dwAttributes, DWORD dwUserType, | ||
| 287 | DWORD dwDataType, LPVOID pvData) | ||
| 288 | #pragma prefast(pop) | ||
| 289 | { | ||
| 290 | Assert(piMetabase && (pvData || (DWORD_METADATA == dwDataType))); // pvData may be 0 if it is DWORD data | ||
| 291 | Unused(piMetabase); | ||
| 292 | |||
| 293 | HRESULT hr = S_OK; | ||
| 294 | WCHAR wzKey[METADATA_MAX_NAME_LEN]; | ||
| 295 | WCHAR* pwzCustomActionData = NULL; | ||
| 296 | |||
| 297 | if (BINARY_METADATA == dwDataType) | ||
| 298 | { | ||
| 299 | ExitOnNull(pvData, hr, E_INVALIDARG, "Failed to write binary metadata - no data available to write"); | ||
| 300 | } | ||
| 301 | |||
| 302 | hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey); | ||
| 303 | ExitOnFailure(hr, "Failed to copy root key string to key"); | ||
| 304 | if (L'/' != *(wzKey + lstrlenW(wzRootKey))) | ||
| 305 | { | ||
| 306 | hr = ::StringCchCatW(wzKey, countof(wzKey), L"/"); | ||
| 307 | ExitOnFailure(hr, "Failed to concatenate / to key string"); | ||
| 308 | } | ||
| 309 | if (wzSubKey && *wzSubKey) | ||
| 310 | { | ||
| 311 | if (L'/' == *wzSubKey) | ||
| 312 | { | ||
| 313 | hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1); | ||
| 314 | ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string"); | ||
| 315 | } | ||
| 316 | else | ||
| 317 | { | ||
| 318 | hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey); | ||
| 319 | ExitOnFailure(hr, "Failed to concatenate subkey to key string"); | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | hr = WcaWriteIntegerToCaData(MBA_WRITEVALUE, &pwzCustomActionData); | ||
| 324 | ExitOnFailure(hr, "Failed to add metabase write value directive to CustomActionData"); | ||
| 325 | |||
| 326 | hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData); | ||
| 327 | ExitOnFailure(hr, "Failed to add metabase key to CustomActionData"); | ||
| 328 | |||
| 329 | hr = WcaWriteIntegerToCaData(dwIdentifier, &pwzCustomActionData); | ||
| 330 | ExitOnFailure(hr, "Failed to add metabase identifier to CustomActionData"); | ||
| 331 | |||
| 332 | hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCustomActionData); | ||
| 333 | ExitOnFailure(hr, "Failed to add metabase attributes to CustomActionData"); | ||
| 334 | |||
| 335 | hr = WcaWriteIntegerToCaData(dwUserType, &pwzCustomActionData); | ||
| 336 | ExitOnFailure(hr, "Failed to add metabase user type to CustomActionData"); | ||
| 337 | |||
| 338 | hr = WcaWriteIntegerToCaData(dwDataType, &pwzCustomActionData); | ||
| 339 | ExitOnFailure(hr, "Failed to add metabase data type to CustomActionData"); | ||
| 340 | |||
| 341 | switch (dwDataType) | ||
| 342 | { | ||
| 343 | case DWORD_METADATA: | ||
| 344 | hr = WcaWriteIntegerToCaData((DWORD)((DWORD_PTR)pvData), &pwzCustomActionData); | ||
| 345 | break; | ||
| 346 | case STRING_METADATA: | ||
| 347 | hr = WcaWriteStringToCaData((LPCWSTR)pvData, &pwzCustomActionData); | ||
| 348 | break; | ||
| 349 | case MULTISZ_METADATA: | ||
| 350 | { | ||
| 351 | // change NULLs to unprintable character to create a 'safe' MULTISZ string | ||
| 352 | LPWSTR pwz = (LPWSTR)pvData; | ||
| 353 | for (;;) | ||
| 354 | { | ||
| 355 | if ('\0' == *pwz) | ||
| 356 | { | ||
| 357 | *pwz = MAGIC_MULTISZ_CHAR; | ||
| 358 | if ('\0' == *(pwz + 1)) // second null back to back means end of string | ||
| 359 | break; | ||
| 360 | } | ||
| 361 | |||
| 362 | ++pwz; | ||
| 363 | } | ||
| 364 | |||
| 365 | hr = WcaWriteStringToCaData((LPCWSTR)pvData, &pwzCustomActionData); | ||
| 366 | } | ||
| 367 | break; | ||
| 368 | case BINARY_METADATA: | ||
| 369 | hr = WcaWriteStreamToCaData(((BLOB*) pvData)->pBlobData, ((BLOB*) pvData)->cbSize, &pwzCustomActionData); | ||
| 370 | break; | ||
| 371 | default: | ||
| 372 | hr = E_UNEXPECTED; | ||
| 373 | } | ||
| 374 | ExitOnFailure(hr, "Failed to add metabase data to CustomActionData"); | ||
| 375 | |||
| 376 | // TODO: maybe look the key up and make sure we're not just writing the same value that already there | ||
| 377 | |||
| 378 | hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEVALUE); | ||
| 379 | ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEVALUE); | ||
| 380 | |||
| 381 | LExit: | ||
| 382 | ReleaseStr(pwzCustomActionData); | ||
| 383 | |||
| 384 | return hr; | ||
| 385 | } | ||
| 386 | |||
| 387 | |||
| 388 | HRESULT ScaAddToIisConfiguration(LPCWSTR pwzData, DWORD dwCost) | ||
| 389 | { | ||
| 390 | HRESULT hr = S_OK; | ||
| 391 | |||
| 392 | hr = WcaWriteStringToCaData(pwzData, &vpwzCustomActionData); | ||
| 393 | ExitOnFailure(hr, "failed to add to metabase configuration data string: %ls", pwzData); | ||
| 394 | |||
| 395 | vdwCustomActionCost += dwCost; | ||
| 396 | |||
| 397 | LExit: | ||
| 398 | return hr; | ||
| 399 | } | ||
| 400 | |||
| 401 | |||
| 402 | HRESULT ScaWriteConfigurationScript(__in LPCWSTR pwzCaScriptKey) | ||
| 403 | { | ||
| 404 | HRESULT hr = S_OK; | ||
| 405 | WCA_CASCRIPT_HANDLE hScript = NULL; | ||
| 406 | LPWSTR pwzHashString = NULL; | ||
| 407 | BYTE rgbActualHash[SHA1_HASH_LEN] = { }; | ||
| 408 | DWORD dwHashedBytes = SHA1_HASH_LEN; | ||
| 409 | |||
| 410 | // Create CaScript for communication with WriteMetabaseChanges | ||
| 411 | hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzCaScriptKey, FALSE, &hScript); | ||
| 412 | ExitOnFailure(hr, "Failed to write ca script for WriteMetabaseChanges script."); | ||
| 413 | |||
| 414 | if (vpwzCustomActionData && *vpwzCustomActionData) | ||
| 415 | { | ||
| 416 | // Write the actual custom action data to the ca script | ||
| 417 | WcaCaScriptWriteString(hScript, vpwzCustomActionData); | ||
| 418 | |||
| 419 | hr = CrypHashBuffer((BYTE*)vpwzCustomActionData, sizeof(vpwzCustomActionData) * sizeof(WCHAR), PROV_RSA_AES, CALG_SHA1, rgbActualHash, dwHashedBytes); | ||
| 420 | ExitOnFailure(hr, "Failed to calculate hash of CustomAction data."); | ||
| 421 | |||
| 422 | hr = StrAlloc(&pwzHashString, ((dwHashedBytes * 2) + 1)); | ||
| 423 | ExitOnFailure(hr, "Failed to allocate string for script hash"); | ||
| 424 | |||
| 425 | hr = StrHexEncode(rgbActualHash, dwHashedBytes, pwzHashString, ((dwHashedBytes * 2) + 1)); | ||
| 426 | ExitOnFailure(hr, "Failed to convert hash bytes to string."); | ||
| 427 | |||
| 428 | WcaLog(LOGMSG_VERBOSE, "Custom action data hash: %ls", pwzHashString); | ||
| 429 | WcaLog(LOGMSG_TRACEONLY, "Custom action data being written to ca script: %ls", vpwzCustomActionData); | ||
| 430 | } | ||
| 431 | else | ||
| 432 | hr = S_FALSE; | ||
| 433 | |||
| 434 | LExit: | ||
| 435 | // Release the string | ||
| 436 | ReleaseStr(vpwzCustomActionData); | ||
| 437 | ReleaseStr(pwzHashString); | ||
| 438 | |||
| 439 | // Flush the ca script to disk as best we can | ||
| 440 | WcaCaScriptFlush(hScript); | ||
| 441 | |||
| 442 | WcaCaScriptClose(hScript, WCA_CASCRIPT_CLOSE_PRESERVE); | ||
| 443 | |||
| 444 | return hr; | ||
| 445 | } | ||
| 446 | |||
| 447 | |||
| 448 | HRESULT ScaLoadMetabase(IMSAdminBase** ppiMetabase) | ||
| 449 | { | ||
| 450 | HRESULT hr = S_OK; | ||
| 451 | UINT er = ERROR_SUCCESS; | ||
| 452 | |||
| 453 | // if IIS was uninstalled (thus no IID_IMSAdminBase) allow the | ||
| 454 | // user to still uninstall this package by clicking "Ignore" | ||
| 455 | do | ||
| 456 | { | ||
| 457 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void**)ppiMetabase); | ||
| 458 | if (FAILED(hr)) | ||
| 459 | { | ||
| 460 | WcaLog(LOGMSG_STANDARD, "failed to get IID_IMSAdminBase Object"); | ||
| 461 | er = WcaErrorMessage(msierrIISCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 462 | switch (er) | ||
| 463 | { | ||
| 464 | case IDABORT: | ||
| 465 | ExitFunction(); // bail with the error result from the CoCreate to kick off a rollback | ||
| 466 | case IDRETRY: | ||
| 467 | hr = S_FALSE; // hit me, baby, one more time | ||
| 468 | break; | ||
| 469 | case IDIGNORE: | ||
| 470 | hr = S_OK; // pretend everything is okay and bail | ||
| 471 | break; | ||
| 472 | default: // For failure on uninstall continue | ||
| 473 | hr = S_OK; | ||
| 474 | break; | ||
| 475 | } | ||
| 476 | } | ||
| 477 | } while (S_FALSE == hr); | ||
| 478 | |||
| 479 | LExit: | ||
| 480 | return hr; | ||
| 481 | } | ||
diff --git a/src/ext/Iis/ca/scaiis.h b/src/ext/Iis/ca/scaiis.h new file mode 100644 index 00000000..4c743edf --- /dev/null +++ b/src/ext/Iis/ca/scaiis.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaMetabaseTransaction(__in_z LPCWSTR wzBackup); | ||
| 6 | |||
| 7 | HRESULT ScaCreateWeb(IMSAdminBase* piMetabase, LPCWSTR wzWeb, LPCWSTR wzWebBase); | ||
| 8 | |||
| 9 | HRESULT ScaDeleteApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot); | ||
| 10 | |||
| 11 | HRESULT ScaCreateApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot, | ||
| 12 | DWORD dwIsolation); | ||
| 13 | |||
| 14 | HRESULT ScaCreateMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey, | ||
| 15 | LPCWSTR wzSubKey); | ||
| 16 | |||
| 17 | HRESULT ScaDeleteMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey, | ||
| 18 | LPCWSTR wzSubKey); | ||
| 19 | |||
| 20 | HRESULT ScaWriteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey, | ||
| 21 | LPCWSTR wzSubKey, DWORD dwIdentifier, | ||
| 22 | DWORD dwAttributes, DWORD dwUserType, | ||
| 23 | DWORD dwDataType, LPVOID pvData); | ||
| 24 | |||
| 25 | HRESULT ScaDeleteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey, | ||
| 26 | LPCWSTR wzSubKey, DWORD dwIdentifier, | ||
| 27 | DWORD dwDataType); | ||
| 28 | |||
| 29 | HRESULT ScaWriteConfigurationScript(LPCWSTR pwzCaScriptKey); | ||
| 30 | |||
| 31 | HRESULT ScaAddToIisConfiguration(LPCWSTR pwzData, DWORD dwCost); | ||
| 32 | |||
| 33 | HRESULT ScaLoadMetabase(IMSAdminBase** piMetabase); | ||
diff --git a/src/ext/Iis/ca/scaiis7.cpp b/src/ext/Iis/ca/scaiis7.cpp new file mode 100644 index 00000000..aaf307d7 --- /dev/null +++ b/src/ext/Iis/ca/scaiis7.cpp | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | #define COST_IIS_WRITEKEY 10 | ||
| 6 | |||
| 7 | HRESULT ScaIIS7ConfigTransaction(LPCWSTR wzBackup) | ||
| 8 | { | ||
| 9 | HRESULT hr = S_OK; | ||
| 10 | |||
| 11 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"StartIIS7ConfigTransaction"), wzBackup, COST_IIS_TRANSACTIONS); | ||
| 12 | ExitOnFailure(hr, "Failed to schedule StartIIS7ConfigTransaction"); | ||
| 13 | |||
| 14 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackIIS7ConfigTransaction"), wzBackup, 0); // rollback cost is irrelevant | ||
| 15 | ExitOnFailure(hr, "Failed to schedule RollbackIIS7ConfigTransaction"); | ||
| 16 | |||
| 17 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CommitIIS7ConfigTransaction"), wzBackup, 0); // commit is free | ||
| 18 | ExitOnFailure(hr, "Failed to schedule StartIIS7ConfigTransaction"); | ||
| 19 | |||
| 20 | LExit: | ||
| 21 | return hr; | ||
| 22 | } | ||
| 23 | |||
| 24 | HRESULT ScaWriteConfigString(const LPCWSTR wzValue) | ||
| 25 | { | ||
| 26 | HRESULT hr = S_OK; | ||
| 27 | WCHAR* pwzCustomActionData = NULL; | ||
| 28 | |||
| 29 | hr = WcaWriteStringToCaData(wzValue, &pwzCustomActionData); | ||
| 30 | ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData"); | ||
| 31 | |||
| 32 | hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEKEY); | ||
| 33 | ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEKEY); | ||
| 34 | |||
| 35 | LExit: | ||
| 36 | ReleaseStr(pwzCustomActionData); | ||
| 37 | |||
| 38 | return hr; | ||
| 39 | } | ||
| 40 | |||
| 41 | HRESULT ScaWriteConfigInteger(DWORD dwValue) | ||
| 42 | { | ||
| 43 | HRESULT hr = S_OK; | ||
| 44 | WCHAR* pwzCustomActionData = NULL; | ||
| 45 | |||
| 46 | hr = WcaWriteIntegerToCaData(dwValue, &pwzCustomActionData); | ||
| 47 | ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData"); | ||
| 48 | |||
| 49 | hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEKEY); | ||
| 50 | ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEKEY); | ||
| 51 | |||
| 52 | LExit: | ||
| 53 | ReleaseStr(pwzCustomActionData); | ||
| 54 | |||
| 55 | return hr; | ||
| 56 | } | ||
| 57 | |||
| 58 | HRESULT ScaWriteConfigID(IIS_CONFIG_ACTION emID) | ||
| 59 | { | ||
| 60 | HRESULT hr = S_OK; | ||
| 61 | WCHAR* pwzCustomActionData = NULL; | ||
| 62 | |||
| 63 | hr = WcaWriteIntegerToCaData(emID, &pwzCustomActionData); | ||
| 64 | ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData"); | ||
| 65 | |||
| 66 | hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEKEY); | ||
| 67 | ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEKEY); | ||
| 68 | |||
| 69 | LExit: | ||
| 70 | ReleaseStr(pwzCustomActionData); | ||
| 71 | |||
| 72 | return hr; | ||
| 73 | } | ||
| 74 | |||
diff --git a/src/ext/Iis/ca/scaiis7.h b/src/ext/Iis/ca/scaiis7.h new file mode 100644 index 00000000..f398deca --- /dev/null +++ b/src/ext/Iis/ca/scaiis7.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaScheduleIIS7Configuration(); | ||
| 6 | |||
| 7 | HRESULT ScaIIS7ConfigTransaction(__in_z LPCWSTR wzBackup); | ||
| 8 | |||
| 9 | HRESULT ScaCreateApp7(__in_z LPCWSTR wzWebRoot, DWORD dwIsolation); | ||
| 10 | |||
| 11 | HRESULT ScaDeleteConfigElement(IIS_CONFIG_ACTION emElement, LPCWSTR wzSubKey); | ||
| 12 | |||
| 13 | HRESULT ScaWriteConfigString(__in_z const LPCWSTR wzValue); | ||
| 14 | |||
| 15 | HRESULT ScaWriteConfigID(IIS_CONFIG_ACTION emID); | ||
| 16 | |||
| 17 | HRESULT ScaWriteConfigInteger(DWORD dwValue); | ||
diff --git a/src/ext/Iis/ca/scamimemap.cpp b/src/ext/Iis/ca/scamimemap.cpp new file mode 100644 index 00000000..8afe99f9 --- /dev/null +++ b/src/ext/Iis/ca/scamimemap.cpp | |||
| @@ -0,0 +1,200 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | enum eMimeMapQuery { mmqMimeMap = 1, mmqParentType, mmqParentValue, | ||
| 6 | mmqMimeType, mmqExtension}; | ||
| 7 | |||
| 8 | // prototypes | ||
| 9 | static HRESULT AddMimeMapToList(SCA_MIMEMAP** ppsmmList); | ||
| 10 | |||
| 11 | |||
| 12 | void ScaMimeMapFreeList(SCA_MIMEMAP* psmmList) | ||
| 13 | { | ||
| 14 | SCA_MIMEMAP* psmmDelete = psmmList; | ||
| 15 | while (psmmList) | ||
| 16 | { | ||
| 17 | psmmDelete = psmmList; | ||
| 18 | psmmList = psmmList->psmmNext; | ||
| 19 | |||
| 20 | MemFree(psmmDelete); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | |||
| 25 | HRESULT __stdcall ScaMimeMapRead( | ||
| 26 | SCA_MIMEMAP** ppsmmList, | ||
| 27 | __inout LPWSTR *ppwzCustomActionData | ||
| 28 | ) | ||
| 29 | { | ||
| 30 | HRESULT hr = S_OK; | ||
| 31 | MSIHANDLE hRec; | ||
| 32 | LPWSTR pwzData = NULL; | ||
| 33 | SCA_MIMEMAP* psmm; | ||
| 34 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 35 | |||
| 36 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 37 | ExitOnFailure(hr, "Failed to unwrap query for ScaMimeMapRead"); | ||
| 38 | |||
| 39 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 40 | { | ||
| 41 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaMimeMapRead() - required table not present"); | ||
| 42 | ExitFunction1(hr = S_FALSE); | ||
| 43 | } | ||
| 44 | |||
| 45 | // loop through all the mimemappings | ||
| 46 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 47 | { | ||
| 48 | hr = AddMimeMapToList(ppsmmList); | ||
| 49 | ExitOnFailure(hr, "failed to add mime map to list"); | ||
| 50 | |||
| 51 | psmm = *ppsmmList; | ||
| 52 | |||
| 53 | hr = WcaGetRecordString(hRec, mmqMimeMap, &pwzData); | ||
| 54 | ExitOnFailure(hr, "Failed to get MimeMap.MimeMap"); | ||
| 55 | hr = ::StringCchCopyW(psmm->wzMimeMap, countof(psmm->wzMimeMap), pwzData); | ||
| 56 | ExitOnFailure(hr, "Failed to copy mimemap string to mimemap object"); | ||
| 57 | |||
| 58 | hr = WcaGetRecordInteger(hRec, mmqParentType, &psmm->iParentType); | ||
| 59 | ExitOnFailure(hr, "Failed to get MimeMap.iParentType"); | ||
| 60 | |||
| 61 | hr = WcaGetRecordString(hRec, mmqParentValue, &pwzData); | ||
| 62 | ExitOnFailure(hr, "Failed to get MimeMap.ParentValue"); | ||
| 63 | hr = ::StringCchCopyW(psmm->wzParentValue, countof(psmm->wzParentValue), pwzData); | ||
| 64 | ExitOnFailure(hr, "Failed to copy parent value string to mimemap object"); | ||
| 65 | |||
| 66 | hr = WcaGetRecordString(hRec, mmqExtension, &pwzData); | ||
| 67 | ExitOnFailure(hr, "Failed to get MimeMap.Extension"); | ||
| 68 | hr = ::StringCchCopyW(psmm->wzExtension, countof(psmm->wzExtension), pwzData); | ||
| 69 | ExitOnFailure(hr, "Failed to copy extension string to mimemap object"); | ||
| 70 | |||
| 71 | hr = WcaGetRecordString(hRec, mmqMimeType, &pwzData); | ||
| 72 | ExitOnFailure(hr, "Failed to get MimeMap.MimeType"); | ||
| 73 | hr = ::StringCchCopyW(psmm->wzMimeType, countof(psmm->wzMimeType), pwzData); | ||
| 74 | ExitOnFailure(hr, "Failed to copy mimetype string to mimemap object"); | ||
| 75 | } | ||
| 76 | |||
| 77 | if (E_NOMOREITEMS == hr) | ||
| 78 | hr = S_OK; | ||
| 79 | ExitOnFailure(hr, "Failure while processing mimemappings"); | ||
| 80 | |||
| 81 | LExit: | ||
| 82 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 83 | |||
| 84 | ReleaseStr(pwzData); | ||
| 85 | |||
| 86 | return hr; | ||
| 87 | } | ||
| 88 | |||
| 89 | |||
| 90 | HRESULT ScaGetMimeMap(int iParentType, LPCWSTR wzParentValue, SCA_MIMEMAP **ppsmmList, SCA_MIMEMAP **ppsmmOut) | ||
| 91 | { | ||
| 92 | HRESULT hr = S_OK; | ||
| 93 | SCA_MIMEMAP* psmmAdd = NULL; | ||
| 94 | SCA_MIMEMAP* psmmLast = NULL; | ||
| 95 | |||
| 96 | *ppsmmOut = NULL; | ||
| 97 | |||
| 98 | if (!*ppsmmList) | ||
| 99 | return hr; | ||
| 100 | |||
| 101 | SCA_MIMEMAP* psmm = *ppsmmList; | ||
| 102 | while (psmm) | ||
| 103 | { | ||
| 104 | if (iParentType == psmm->iParentType && 0 == lstrcmpW(wzParentValue, psmm->wzParentValue)) | ||
| 105 | { | ||
| 106 | // Found a match, take this one out of the list and add it to the matched out list | ||
| 107 | psmmAdd = psmm; | ||
| 108 | |||
| 109 | if (psmmLast) | ||
| 110 | { | ||
| 111 | // If we're not at the beginning of the list tell the last node about it's new next (since we're taking away it's current next) | ||
| 112 | psmmLast->psmmNext = psmmAdd->psmmNext; | ||
| 113 | } | ||
| 114 | else | ||
| 115 | { | ||
| 116 | // If we are at the beginning (no psmmLast) update the beginning (since we're taking it) | ||
| 117 | *ppsmmList = psmm->psmmNext; | ||
| 118 | } | ||
| 119 | psmm = psmm->psmmNext; // move on | ||
| 120 | |||
| 121 | // Add the one we've removed to the beginning of the out list | ||
| 122 | psmmAdd->psmmNext = *ppsmmOut; | ||
| 123 | *ppsmmOut = psmmAdd; | ||
| 124 | } | ||
| 125 | else | ||
| 126 | { | ||
| 127 | psmmLast = psmm; // remember the last we that didn't match | ||
| 128 | psmm = psmm->psmmNext; // move on | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | return hr; | ||
| 133 | } | ||
| 134 | |||
| 135 | HRESULT ScaMimeMapCheckList(SCA_MIMEMAP* psmmList) | ||
| 136 | { | ||
| 137 | if (!psmmList) | ||
| 138 | return S_OK; | ||
| 139 | |||
| 140 | while (psmmList) | ||
| 141 | { | ||
| 142 | WcaLog(LOGMSG_STANDARD, "MimeMapping of %ls with ParentType=%d and ParentValue=%ls not used!", psmmList->wzMimeMap, psmmList->iParentType, psmmList->wzParentValue); | ||
| 143 | psmmList = psmmList->psmmNext; | ||
| 144 | } | ||
| 145 | |||
| 146 | return E_FAIL; | ||
| 147 | } | ||
| 148 | |||
| 149 | |||
| 150 | HRESULT ScaWriteMimeMap(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, | ||
| 151 | SCA_MIMEMAP* psmmList) | ||
| 152 | { | ||
| 153 | HRESULT hr = S_OK; | ||
| 154 | |||
| 155 | WCHAR wzMimeMap[8192]; | ||
| 156 | WCHAR *pwzNext = wzMimeMap; | ||
| 157 | const WCHAR *pwzMac = wzMimeMap + countof(wzMimeMap); // used to properly create the MULTI_SZ | ||
| 158 | |||
| 159 | // fill the MULTI_SZ wzMimeMap buffer for the MimeMap attribute | ||
| 160 | ::ZeroMemory(wzMimeMap, sizeof(wzMimeMap)); | ||
| 161 | |||
| 162 | for (SCA_MIMEMAP* psmm = psmmList; psmm; psmm = psmm->psmmNext) | ||
| 163 | { | ||
| 164 | hr = ::StringCchPrintfW(pwzNext, max(0, pwzMac - pwzNext), L"%s,%s", psmm->wzExtension, psmm->wzMimeType); | ||
| 165 | ExitOnFailure(hr, "Failed to set MimeMap string"); | ||
| 166 | |||
| 167 | pwzNext += lstrlenW(pwzNext) + 1; // reserve space for null | ||
| 168 | Assert(pwzNext <= pwzMac); | ||
| 169 | } | ||
| 170 | |||
| 171 | if (pwzNext != wzMimeMap) | ||
| 172 | { | ||
| 173 | // now write the CustomErrors to the metabase | ||
| 174 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_MIME_MAP, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzMimeMap); | ||
| 175 | ExitOnFailure(hr, "Failed to write MimeMap"); | ||
| 176 | } | ||
| 177 | else | ||
| 178 | { | ||
| 179 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaWriteMimeMap() - no mappings found."); | ||
| 180 | ExitFunction1(hr = S_FALSE); | ||
| 181 | } | ||
| 182 | |||
| 183 | LExit: | ||
| 184 | return hr; | ||
| 185 | } | ||
| 186 | |||
| 187 | |||
| 188 | static HRESULT AddMimeMapToList(SCA_MIMEMAP** ppsmmList) | ||
| 189 | { | ||
| 190 | HRESULT hr = S_OK; | ||
| 191 | |||
| 192 | SCA_MIMEMAP* psmm = static_cast<SCA_MIMEMAP*>(MemAlloc(sizeof(SCA_MIMEMAP), TRUE)); | ||
| 193 | ExitOnNull(psmm, hr, E_OUTOFMEMORY, "failed to allocate memory for new mime map list element"); | ||
| 194 | |||
| 195 | psmm->psmmNext = *ppsmmList; | ||
| 196 | *ppsmmList = psmm; | ||
| 197 | |||
| 198 | LExit: | ||
| 199 | return hr; | ||
| 200 | } | ||
diff --git a/src/ext/Iis/ca/scamimemap.h b/src/ext/Iis/ca/scamimemap.h new file mode 100644 index 00000000..b50e82e9 --- /dev/null +++ b/src/ext/Iis/ca/scamimemap.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | enum eMimeMapParentType { mmptVDir = 1, mmptWeb = 2 }; | ||
| 6 | |||
| 7 | struct SCA_MIMEMAP | ||
| 8 | { | ||
| 9 | // iis configuation information | ||
| 10 | WCHAR wzMimeMap[MAX_DARWIN_KEY + 1]; | ||
| 11 | int iParentType; | ||
| 12 | WCHAR wzParentValue[MAX_DARWIN_KEY + 1]; | ||
| 13 | WCHAR wzMimeType[MAX_DARWIN_KEY + 1]; | ||
| 14 | WCHAR wzExtension[MAX_DARWIN_KEY + 1]; | ||
| 15 | |||
| 16 | |||
| 17 | SCA_MIMEMAP* psmmNext; | ||
| 18 | }; | ||
| 19 | |||
| 20 | |||
| 21 | // prototypes | ||
| 22 | |||
| 23 | HRESULT __stdcall ScaMimeMapRead(SCA_MIMEMAP** ppsmmList, __inout LPWSTR *ppwzCustomActionData); | ||
| 24 | |||
| 25 | HRESULT ScaGetMimeMap(int iParentType, LPCWSTR wzParentValue, SCA_MIMEMAP **psmmList, SCA_MIMEMAP **ppsmmOut); | ||
| 26 | |||
| 27 | HRESULT ScaMimeMapCheckList(SCA_MIMEMAP* psmmList); | ||
| 28 | |||
| 29 | void ScaMimeMapFreeList(SCA_MIMEMAP* psmmList); | ||
| 30 | |||
| 31 | HRESULT ScaWriteMimeMap(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, | ||
| 32 | SCA_MIMEMAP* psmmList); | ||
| 33 | |||
diff --git a/src/ext/Iis/ca/scamimemap7.cpp b/src/ext/Iis/ca/scamimemap7.cpp new file mode 100644 index 00000000..f6689720 --- /dev/null +++ b/src/ext/Iis/ca/scamimemap7.cpp | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // prototypes | ||
| 6 | HRESULT ScaWriteMimeMap7( | ||
| 7 | __in_z LPCWSTR wzWebName, | ||
| 8 | __in_z LPCWSTR wzRootOfWeb, | ||
| 9 | SCA_MIMEMAP* psmmList | ||
| 10 | ) | ||
| 11 | { | ||
| 12 | HRESULT hr = S_OK; | ||
| 13 | SCA_MIMEMAP* psmm; | ||
| 14 | |||
| 15 | //create the mimemap list for this vdir application | ||
| 16 | //all go to same web/root location tag | ||
| 17 | hr = ScaWriteConfigID(IIS_MIMEMAP_BEGIN); | ||
| 18 | ExitOnFailure(hr, "Failed to write mimemap begin id"); | ||
| 19 | hr = ScaWriteConfigString(wzWebName); //site name key | ||
| 20 | ExitOnFailure(hr, "Failed to write mimemap web key"); | ||
| 21 | hr = ScaWriteConfigString(wzRootOfWeb); //app path key | ||
| 22 | ExitOnFailure(hr, "Failed to write mimemap app key"); | ||
| 23 | |||
| 24 | psmm = psmmList; | ||
| 25 | |||
| 26 | while (psmm) | ||
| 27 | { | ||
| 28 | //create the Extension for this vdir application | ||
| 29 | hr = ScaWriteConfigID(IIS_MIMEMAP); | ||
| 30 | ExitOnFailure(hr, "Failed to write mimemap id"); | ||
| 31 | |||
| 32 | if (*psmm->wzExtension) | ||
| 33 | { | ||
| 34 | hr = ScaWriteConfigString(psmm->wzExtension); | ||
| 35 | } | ||
| 36 | else // blank means "*" (all) | ||
| 37 | { | ||
| 38 | hr = ScaWriteConfigString(L"*"); | ||
| 39 | } | ||
| 40 | ExitOnFailure(hr, "Failed to write mimemap extension"); | ||
| 41 | |||
| 42 | hr = ScaWriteConfigString(psmm->wzMimeType); | ||
| 43 | ExitOnFailure(hr, "Failed to write mimemap type"); | ||
| 44 | |||
| 45 | psmm = psmm->psmmNext; | ||
| 46 | } | ||
| 47 | |||
| 48 | hr = ScaWriteConfigID(IIS_MIMEMAP_END); | ||
| 49 | ExitOnFailure(hr, "Failed to write mimemap end id"); | ||
| 50 | |||
| 51 | LExit: | ||
| 52 | return hr; | ||
| 53 | } | ||
| 54 | |||
| 55 | |||
| 56 | //static HRESULT AddMimeMapToList(SCA_MIMEMAP** ppsmmList) | ||
| 57 | //{ | ||
| 58 | // HRESULT hr = S_OK; | ||
| 59 | // | ||
| 60 | // SCA_MIMEMAP* psmm = static_cast<SCA_MIMEMAP*>(MemAlloc(sizeof(SCA_MIMEMAP), TRUE)); | ||
| 61 | // ExitOnNull(psmm, hr, E_OUTOFMEMORY, "failed to allocate memory for new mime map list element"); | ||
| 62 | // | ||
| 63 | // psmm->psmmNext = *ppsmmList; | ||
| 64 | // *ppsmmList = psmm; | ||
| 65 | // | ||
| 66 | //LExit: | ||
| 67 | // return hr; | ||
| 68 | //} | ||
diff --git a/src/ext/Iis/ca/scamimemap7.h b/src/ext/Iis/ca/scamimemap7.h new file mode 100644 index 00000000..88fcdc39 --- /dev/null +++ b/src/ext/Iis/ca/scamimemap7.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaWriteMimeMap7( | ||
| 6 | __in_z LPCWSTR wzWebName, | ||
| 7 | __in_z LPCWSTR wzRootOfWeb, | ||
| 8 | SCA_MIMEMAP* psmmList | ||
| 9 | ); | ||
| 10 | |||
diff --git a/src/ext/Iis/ca/scaproperty.cpp b/src/ext/Iis/ca/scaproperty.cpp new file mode 100644 index 00000000..d0e0d8a4 --- /dev/null +++ b/src/ext/Iis/ca/scaproperty.cpp | |||
| @@ -0,0 +1,252 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | /*------------------------------------------------------------------ | ||
| 6 | IIsProperty table: | ||
| 7 | |||
| 8 | Property Component_ Attributes Value | ||
| 9 | s72 s72 i4 s255 | ||
| 10 | ------------------------------------------------------------------*/ | ||
| 11 | |||
| 12 | // sql queries | ||
| 13 | enum ePropertyQuery { pqProperty = 1, pqComponent, pqAttributes, pqValue, pqInstalled, pqAction }; | ||
| 14 | |||
| 15 | |||
| 16 | // prototypes | ||
| 17 | static HRESULT AddPropertyToList( | ||
| 18 | SCA_PROPERTY** ppspList | ||
| 19 | ); | ||
| 20 | |||
| 21 | |||
| 22 | // functions | ||
| 23 | void ScaPropertyFreeList( | ||
| 24 | SCA_PROPERTY* pspList | ||
| 25 | ) | ||
| 26 | { | ||
| 27 | SCA_PROPERTY* pspDelete = pspList; | ||
| 28 | while (pspList) | ||
| 29 | { | ||
| 30 | pspDelete = pspList; | ||
| 31 | pspList = pspList->pspNext; | ||
| 32 | |||
| 33 | MemFree(pspDelete); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | |||
| 38 | HRESULT ScaPropertyRead( | ||
| 39 | SCA_PROPERTY** ppspList, | ||
| 40 | __inout LPWSTR *ppwzCustomActionData | ||
| 41 | ) | ||
| 42 | { | ||
| 43 | HRESULT hr = S_OK; | ||
| 44 | MSIHANDLE hRec; | ||
| 45 | |||
| 46 | LPWSTR pwzData = NULL; | ||
| 47 | SCA_PROPERTY* pss; | ||
| 48 | |||
| 49 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 50 | |||
| 51 | ExitOnNull(ppspList, hr, E_INVALIDARG, "Failed to read property, because no property to read was provided"); | ||
| 52 | |||
| 53 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 54 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 55 | |||
| 56 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 57 | { | ||
| 58 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallProperty() - required table not present"); | ||
| 59 | ExitFunction1(hr = S_FALSE); | ||
| 60 | } | ||
| 61 | |||
| 62 | // loop through all the Settings | ||
| 63 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 64 | { | ||
| 65 | hr = AddPropertyToList(ppspList); | ||
| 66 | ExitOnFailure(hr, "failed to add property to list"); | ||
| 67 | |||
| 68 | pss = *ppspList; | ||
| 69 | |||
| 70 | hr = WcaGetRecordString(hRec, pqProperty, &pwzData); | ||
| 71 | ExitOnFailure(hr, "failed to get IIsProperty.Property"); | ||
| 72 | hr = ::StringCchCopyW(pss->wzProperty, countof(pss->wzProperty), pwzData); | ||
| 73 | ExitOnFailure(hr, "failed to copy Property name: %ls", pwzData); | ||
| 74 | |||
| 75 | hr = WcaGetRecordString(hRec, pqValue, &pwzData); | ||
| 76 | ExitOnFailure(hr, "failed to get IIsProperty.Value"); | ||
| 77 | hr = ::StringCchCopyW(pss->wzValue, countof(pss->wzValue), pwzData); | ||
| 78 | ExitOnFailure(hr, "failed to copy Property value: %ls", pwzData); | ||
| 79 | |||
| 80 | hr = WcaGetRecordInteger(hRec, pqAttributes, &pss->iAttributes); | ||
| 81 | ExitOnFailure(hr, "failed to get IIsProperty.Attributes"); | ||
| 82 | |||
| 83 | hr = WcaGetRecordString(hRec, pqComponent, &pwzData); | ||
| 84 | ExitOnFailure(hr, "failed to get IIsProperty.Component"); | ||
| 85 | hr = ::StringCchCopyW(pss->wzComponent, countof(pss->wzComponent), pwzData); | ||
| 86 | ExitOnFailure(hr, "failed to copy component name: %ls", pwzData); | ||
| 87 | |||
| 88 | hr = WcaGetRecordInteger(hRec, pqInstalled, (int *)&pss->isInstalled); | ||
| 89 | ExitOnFailure(hr, "Failed to get Component installed state for filter"); | ||
| 90 | |||
| 91 | hr = WcaGetRecordInteger(hRec, pqAction, (int *)&pss->isAction); | ||
| 92 | ExitOnFailure(hr, "Failed to get Component action state for filter"); | ||
| 93 | } | ||
| 94 | |||
| 95 | if (E_NOMOREITEMS == hr) | ||
| 96 | { | ||
| 97 | hr = S_OK; | ||
| 98 | } | ||
| 99 | ExitOnFailure(hr, "failure while processing IIsProperty table"); | ||
| 100 | |||
| 101 | LExit: | ||
| 102 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 103 | |||
| 104 | ReleaseStr(pwzData); | ||
| 105 | |||
| 106 | return hr; | ||
| 107 | } | ||
| 108 | |||
| 109 | |||
| 110 | HRESULT ScaPropertyInstall( | ||
| 111 | IMSAdminBase* piMetabase, | ||
| 112 | SCA_PROPERTY* pspList | ||
| 113 | ) | ||
| 114 | { | ||
| 115 | Assert(piMetabase); | ||
| 116 | |||
| 117 | HRESULT hr = S_OK; | ||
| 118 | |||
| 119 | for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext) | ||
| 120 | { | ||
| 121 | // if we are installing the web site | ||
| 122 | if (WcaIsInstalling(psp->isInstalled, psp->isAction)) | ||
| 123 | { | ||
| 124 | hr = ScaWriteProperty(piMetabase, psp); | ||
| 125 | ExitOnFailure(hr, "failed to write Property '%ls' to metabase", psp->wzProperty); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | LExit: | ||
| 130 | return hr; | ||
| 131 | } | ||
| 132 | |||
| 133 | |||
| 134 | HRESULT ScaPropertyUninstall( | ||
| 135 | IMSAdminBase* piMetabase, | ||
| 136 | SCA_PROPERTY* pspList | ||
| 137 | ) | ||
| 138 | { | ||
| 139 | Assert(piMetabase); | ||
| 140 | |||
| 141 | HRESULT hr = S_OK; | ||
| 142 | |||
| 143 | for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext) | ||
| 144 | { | ||
| 145 | // if we are uninstalling the web site | ||
| 146 | if (WcaIsUninstalling(psp->isInstalled, psp->isAction)) | ||
| 147 | { | ||
| 148 | hr = ScaRemoveProperty(piMetabase, psp); | ||
| 149 | ExitOnFailure(hr, "Failed to remove Property '%ls' from metabase", psp->wzProperty); | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | LExit: | ||
| 154 | return hr; | ||
| 155 | } | ||
| 156 | |||
| 157 | |||
| 158 | HRESULT ScaWriteProperty( | ||
| 159 | IMSAdminBase* piMetabase, | ||
| 160 | SCA_PROPERTY* psp | ||
| 161 | ) | ||
| 162 | { | ||
| 163 | Assert(piMetabase); | ||
| 164 | |||
| 165 | HRESULT hr = S_OK; | ||
| 166 | DWORD dwValue; | ||
| 167 | LPWSTR wz = NULL; | ||
| 168 | |||
| 169 | ExitOnNull(psp, hr, E_INVALIDARG, "Failed to write property because no property to write was given"); | ||
| 170 | |||
| 171 | // | ||
| 172 | // Figure out what setting we're writing and write it | ||
| 173 | // | ||
| 174 | if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_IIS5_ISOLATION_MODE)) | ||
| 175 | { | ||
| 176 | dwValue = 1; | ||
| 177 | hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_GLOBAL_STANDARD_APP_MODE_ENABLED, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue)); | ||
| 178 | ExitOnFailure(hr, "failed to set IIs5IsolationMode"); | ||
| 179 | } | ||
| 180 | else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH)) | ||
| 181 | { | ||
| 182 | dwValue = wcstoul(psp->wzValue, &wz, 10) * 1024; // remember, the value shown is in kilobytes, the value saved is in bytes | ||
| 183 | hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_MAX_GLOBAL_BANDWIDTH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue)); | ||
| 184 | ExitOnFailure(hr, "failed to set MaxGlobalBandwidth"); | ||
| 185 | } | ||
| 186 | else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_LOG_IN_UTF8)) | ||
| 187 | { | ||
| 188 | dwValue = 1; | ||
| 189 | hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_GLOBAL_LOG_IN_UTF_8, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue)); | ||
| 190 | ExitOnFailure(hr, "failed to set LogInUTF8"); | ||
| 191 | } | ||
| 192 | else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_ETAG_CHANGENUMBER)) | ||
| 193 | { | ||
| 194 | dwValue = wcstoul(psp->wzValue, &wz, 10); | ||
| 195 | hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, /*MD_ETAG_CHANGENUMBER*/ 2039, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue)); | ||
| 196 | ExitOnFailure(hr, "failed to set EtagChangenumber"); | ||
| 197 | } | ||
| 198 | LExit: | ||
| 199 | return hr; | ||
| 200 | } | ||
| 201 | |||
| 202 | |||
| 203 | HRESULT ScaRemoveProperty( | ||
| 204 | IMSAdminBase* piMetabase, | ||
| 205 | SCA_PROPERTY* psp | ||
| 206 | ) | ||
| 207 | { | ||
| 208 | Assert(piMetabase); | ||
| 209 | |||
| 210 | HRESULT hr = S_OK; | ||
| 211 | DWORD dwValue; | ||
| 212 | |||
| 213 | ExitOnNull(psp, hr, E_INVALIDARG, "Failed to remove property because no property to remove was given"); | ||
| 214 | |||
| 215 | if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_IIS5_ISOLATION_MODE)) | ||
| 216 | { | ||
| 217 | dwValue = 0; | ||
| 218 | hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_GLOBAL_STANDARD_APP_MODE_ENABLED, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue)); | ||
| 219 | ExitOnFailure(hr, "failed to clear IIs5IsolationMode"); | ||
| 220 | } | ||
| 221 | else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH)) | ||
| 222 | { | ||
| 223 | dwValue = 0xFFFFFFFF; // This unchecks the box | ||
| 224 | hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_MAX_GLOBAL_BANDWIDTH, METADATA_NO_ATTRIBUTES , IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue)); | ||
| 225 | ExitOnFailure(hr, "failed to clear MaxGlobalBandwidth"); | ||
| 226 | } | ||
| 227 | else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_LOG_IN_UTF8)) | ||
| 228 | { | ||
| 229 | dwValue = 0; | ||
| 230 | hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_GLOBAL_LOG_IN_UTF_8, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue)); | ||
| 231 | ExitOnFailure(hr, "failed to clear LogInUTF8"); | ||
| 232 | } | ||
| 233 | |||
| 234 | LExit: | ||
| 235 | return hr; | ||
| 236 | } | ||
| 237 | |||
| 238 | |||
| 239 | static HRESULT AddPropertyToList( | ||
| 240 | SCA_PROPERTY** ppspList | ||
| 241 | ) | ||
| 242 | { | ||
| 243 | HRESULT hr = S_OK; | ||
| 244 | SCA_PROPERTY* psp = static_cast<SCA_PROPERTY*>(MemAlloc(sizeof(SCA_PROPERTY), TRUE)); | ||
| 245 | ExitOnNull(psp, hr, E_OUTOFMEMORY, "failed to allocate memory for new property list element"); | ||
| 246 | |||
| 247 | psp->pspNext = *ppspList; | ||
| 248 | *ppspList = psp; | ||
| 249 | |||
| 250 | LExit: | ||
| 251 | return hr; | ||
| 252 | } | ||
diff --git a/src/ext/Iis/ca/scaproperty.h b/src/ext/Iis/ca/scaproperty.h new file mode 100644 index 00000000..21e7cfc7 --- /dev/null +++ b/src/ext/Iis/ca/scaproperty.h | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #define wzIISPROPERTY_IIS5_ISOLATION_MODE L"IIs5IsolationMode" | ||
| 6 | #define wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH L"MaxGlobalBandwidth" | ||
| 7 | #define wzIISPROPERTY_LOG_IN_UTF8 L"LogInUTF8" | ||
| 8 | #define wzIISPROPERTY_ETAG_CHANGENUMBER L"ETagChangeNumber" | ||
| 9 | |||
| 10 | struct SCA_PROPERTY | ||
| 11 | { | ||
| 12 | // iis configuation information | ||
| 13 | WCHAR wzProperty[MAX_DARWIN_KEY + 1]; | ||
| 14 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 15 | INSTALLSTATE isInstalled; | ||
| 16 | INSTALLSTATE isAction; | ||
| 17 | INT iAttributes; | ||
| 18 | WCHAR wzValue[MAX_DARWIN_COLUMN + 1]; | ||
| 19 | |||
| 20 | SCA_PROPERTY *pspNext; | ||
| 21 | }; | ||
| 22 | |||
| 23 | |||
| 24 | // prototypes | ||
| 25 | |||
| 26 | HRESULT ScaPropertyRead( | ||
| 27 | SCA_PROPERTY** ppspList, | ||
| 28 | __inout LPWSTR *ppwzCustomActionData | ||
| 29 | ); | ||
| 30 | |||
| 31 | void ScaPropertyFreeList( | ||
| 32 | SCA_PROPERTY* pspList | ||
| 33 | ); | ||
| 34 | |||
| 35 | HRESULT ScaPropertyInstall( | ||
| 36 | IMSAdminBase* piMetabase, | ||
| 37 | SCA_PROPERTY* pspList | ||
| 38 | ); | ||
| 39 | |||
| 40 | HRESULT ScaPropertyUninstall( | ||
| 41 | IMSAdminBase* piMetabase, | ||
| 42 | SCA_PROPERTY* pspList | ||
| 43 | ); | ||
| 44 | |||
| 45 | HRESULT ScaWriteProperty( | ||
| 46 | IMSAdminBase* piMetabase, | ||
| 47 | SCA_PROPERTY* psp | ||
| 48 | ); | ||
| 49 | |||
| 50 | HRESULT ScaRemoveProperty( | ||
| 51 | IMSAdminBase* piMetabase, | ||
| 52 | SCA_PROPERTY* psp | ||
| 53 | ); | ||
| 54 | |||
diff --git a/src/ext/Iis/ca/scaproperty7.cpp b/src/ext/Iis/ca/scaproperty7.cpp new file mode 100644 index 00000000..d17eeb68 --- /dev/null +++ b/src/ext/Iis/ca/scaproperty7.cpp | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | HRESULT ScaPropertyInstall7( | ||
| 6 | SCA_PROPERTY* pspList | ||
| 7 | ) | ||
| 8 | { | ||
| 9 | HRESULT hr = S_OK; | ||
| 10 | |||
| 11 | for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext) | ||
| 12 | { | ||
| 13 | // if we are installing the web site | ||
| 14 | if (WcaIsInstalling(psp->isInstalled, psp->isAction)) | ||
| 15 | { | ||
| 16 | hr = ScaWriteProperty7(psp); | ||
| 17 | ExitOnFailure(hr, "failed to write Property '%ls' ", psp->wzProperty); | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | LExit: | ||
| 22 | return hr; | ||
| 23 | } | ||
| 24 | |||
| 25 | |||
| 26 | HRESULT ScaPropertyUninstall7( | ||
| 27 | SCA_PROPERTY* pspList | ||
| 28 | ) | ||
| 29 | { | ||
| 30 | HRESULT hr = S_OK; | ||
| 31 | |||
| 32 | for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext) | ||
| 33 | { | ||
| 34 | // if we are uninstalling the web site | ||
| 35 | if (WcaIsUninstalling(psp->isInstalled, psp->isAction)) | ||
| 36 | { | ||
| 37 | hr = ScaRemoveProperty7(psp); | ||
| 38 | ExitOnFailure(hr, "Failed to remove Property '%ls'", psp->wzProperty); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | LExit: | ||
| 43 | return hr; | ||
| 44 | } | ||
| 45 | |||
| 46 | |||
| 47 | HRESULT ScaWriteProperty7( | ||
| 48 | const SCA_PROPERTY* psp | ||
| 49 | ) | ||
| 50 | { | ||
| 51 | HRESULT hr = S_OK; | ||
| 52 | DWORD dwValue; | ||
| 53 | LPWSTR wz = NULL; | ||
| 54 | |||
| 55 | ExitOnNull(psp, hr, E_INVALIDARG, "Failed to write property because no property to write was given"); | ||
| 56 | // | ||
| 57 | // Figure out what setting we're writing and write it | ||
| 58 | // | ||
| 59 | if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_IIS5_ISOLATION_MODE)) | ||
| 60 | { | ||
| 61 | // IIs5IsolationMode not supported | ||
| 62 | WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: IIs5IsolationMode, ignoring"); | ||
| 63 | } | ||
| 64 | else if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH)) | ||
| 65 | { | ||
| 66 | dwValue = wcstoul(psp->wzValue, &wz, 10) * 1024; // remember, the value shown is in kilobytes, the value saved is in bytes | ||
| 67 | hr = ScaWriteConfigID(IIS_PROPERTY); | ||
| 68 | ExitOnFailure(hr, "failed to set Property ID"); | ||
| 69 | hr = ScaWriteConfigID(IIS_PROPERTY_MAXBAND); | ||
| 70 | ExitOnFailure(hr, "failed to set Property MSXBAND ID"); | ||
| 71 | hr = ScaWriteConfigInteger(dwValue); | ||
| 72 | ExitOnFailure(hr, "failed to set Property MSXBAND value"); | ||
| 73 | } | ||
| 74 | else if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_LOG_IN_UTF8)) | ||
| 75 | { | ||
| 76 | dwValue = 1; | ||
| 77 | hr = ScaWriteConfigID(IIS_PROPERTY); | ||
| 78 | ExitOnFailure(hr, "failed to set Property ID"); | ||
| 79 | hr = ScaWriteConfigID(IIS_PROPERTY_LOGUTF8); | ||
| 80 | ExitOnFailure(hr, "failed to set Property LOG ID"); | ||
| 81 | hr = ScaWriteConfigInteger(dwValue); | ||
| 82 | ExitOnFailure(hr, "failed to set Property Log value"); | ||
| 83 | } | ||
| 84 | else if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_ETAG_CHANGENUMBER)) | ||
| 85 | { | ||
| 86 | //EtagChangenumber not supported | ||
| 87 | WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: EtagChangenumber, ignoring"); | ||
| 88 | } | ||
| 89 | |||
| 90 | LExit: | ||
| 91 | return hr; | ||
| 92 | } | ||
| 93 | |||
| 94 | HRESULT ScaRemoveProperty7( | ||
| 95 | __in SCA_PROPERTY* /*psp*/ | ||
| 96 | ) | ||
| 97 | { | ||
| 98 | |||
| 99 | // NOP function for now | ||
| 100 | //The two global values being set by WebProperty: | ||
| 101 | // <iis:WebProperty Id="MaxGlobalBandwidth" Value="1024" /> | ||
| 102 | // <iis:WebProperty Id ="LogInUTF8" /> | ||
| 103 | // should should not be removed on uninstall. | ||
| 104 | |||
| 105 | HRESULT hr = S_OK; | ||
| 106 | |||
| 107 | return hr; | ||
| 108 | } | ||
diff --git a/src/ext/Iis/ca/scaproperty7.h b/src/ext/Iis/ca/scaproperty7.h new file mode 100644 index 00000000..bbf811e8 --- /dev/null +++ b/src/ext/Iis/ca/scaproperty7.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #define wzIISPROPERTY_IIS5_ISOLATION_MODE L"IIs5IsolationMode" | ||
| 6 | #define wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH L"MaxGlobalBandwidth" | ||
| 7 | #define wzIISPROPERTY_LOG_IN_UTF8 L"LogInUTF8" | ||
| 8 | #define wzIISPROPERTY_ETAG_CHANGENUMBER L"ETagChangeNumber" | ||
| 9 | |||
| 10 | // prototypes | ||
| 11 | HRESULT ScaPropertyInstall7( | ||
| 12 | SCA_PROPERTY* pspList | ||
| 13 | ); | ||
| 14 | |||
| 15 | HRESULT ScaPropertyUninstall7( | ||
| 16 | SCA_PROPERTY* pspList | ||
| 17 | ); | ||
| 18 | |||
| 19 | HRESULT ScaWriteProperty7( | ||
| 20 | const SCA_PROPERTY* psp | ||
| 21 | ); | ||
| 22 | |||
| 23 | HRESULT ScaRemoveProperty7( | ||
| 24 | SCA_PROPERTY* psp | ||
| 25 | ); | ||
| 26 | |||
diff --git a/src/ext/Iis/ca/scasched.cpp b/src/ext/Iis/ca/scasched.cpp new file mode 100644 index 00000000..de021275 --- /dev/null +++ b/src/ext/Iis/ca/scasched.cpp | |||
| @@ -0,0 +1,823 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | const int ConfigureIIsCost = 8; | ||
| 6 | const int WriteMetabaseChangesCost = 20; | ||
| 7 | const int WriteIIS7ConfigChangesCost = 20; | ||
| 8 | |||
| 9 | // sql queries | ||
| 10 | LPCWSTR vcsUserDeferredQuery = L"SELECT `User`, `Component_`, `Name`, `Domain`, `Password` FROM `User`"; | ||
| 11 | |||
| 12 | LPCWSTR vcsWebSvcExtQuery = L"SELECT `Component_`, `File`, `Description`, `Group`, `Attributes` FROM `IIsWebServiceExtension`"; | ||
| 13 | |||
| 14 | LPCWSTR vcsAppPoolQuery = L"SELECT `AppPool`, `Name`, `Component_`, `Attributes`, `User_`, `RecycleMinutes`, `RecycleRequests`, `RecycleTimes`, `VirtualMemory`, `PrivateMemory`, `IdleTimeout`, `QueueLimit`, `CPUMon`, `MaxProc`, `ManagedRuntimeVersion`, `ManagedPipelineMode` FROM `IIsAppPool`"; | ||
| 15 | |||
| 16 | LPCWSTR vcsComponentAttrQuery = L"SELECT `Component`,`Attributes` FROM `Component`"; | ||
| 17 | |||
| 18 | LPCWSTR vcsMimeMapQuery = L"SELECT `MimeMap`, `ParentType`, `ParentValue`, `MimeType`, `Extension` FROM `IIsMimeMap`"; | ||
| 19 | |||
| 20 | LPCWSTR vcsHttpHeaderQuery = L"SELECT `Name`, `ParentType`, `ParentValue`, `Value`, `Attributes` FROM `IIsHttpHeader` ORDER BY `Sequence`"; | ||
| 21 | |||
| 22 | LPCWSTR vcsWebErrorQuery = | ||
| 23 | L"SELECT `ErrorCode`, `SubCode`, `ParentType`, `ParentValue`, `File`, `URL` " | ||
| 24 | L"FROM `IIsWebError` ORDER BY `ErrorCode`, `SubCode`"; | ||
| 25 | |||
| 26 | LPCWSTR vcsWebDirPropertiesQuery = L"SELECT `DirProperties`, `Access`, `Authorization`, `AnonymousUser_`, `IIsControlledPassword`, `LogVisits`, `Index`, `DefaultDoc`, `AspDetailedError`, `HttpExpires`, `CacheControlMaxAge`, `CacheControlCustom`, `NoCustomError`, `AccessSSLFlags`, `AuthenticationProviders` " | ||
| 27 | L"FROM `IIsWebDirProperties`"; | ||
| 28 | |||
| 29 | LPCWSTR vcsSslCertificateQuery = L"SELECT `Certificate`.`StoreName`, `CertificateHash`.`Hash`, `IIsWebSiteCertificates`.`Web_` FROM `Certificate`, `CertificateHash`, `IIsWebSiteCertificates` WHERE `Certificate`.`Certificate`=`CertificateHash`.`Certificate_` AND `CertificateHash`.`Certificate_`=`IIsWebSiteCertificates`.`Certificate_`"; | ||
| 30 | |||
| 31 | LPCWSTR vcsWebLogQuery = L"SELECT `Log`, `Format` " | ||
| 32 | L"FROM `IIsWebLog`"; | ||
| 33 | |||
| 34 | LPCWSTR vcsWebApplicationQuery = L"SELECT `Name`, `Isolation`, `AllowSessions`, `SessionTimeout`, " | ||
| 35 | L"`Buffer`, `ParentPaths`, `DefaultScript`, `ScriptTimeout`, " | ||
| 36 | L"`ServerDebugging`, `ClientDebugging`, `AppPool_`, `Application` " | ||
| 37 | L"FROM `IIsWebApplication`"; | ||
| 38 | |||
| 39 | LPCWSTR vcsWebAppExtensionQuery = L"SELECT `Extension`, `Verbs`, `Executable`, `Attributes`, `Application_` FROM `IIsWebApplicationExtension`"; | ||
| 40 | |||
| 41 | LPCWSTR vcsWebQuery = L"SELECT `Web`, `Component_`, `Id`, `Description`, `ConnectionTimeout`, `Directory_`, `State`, `Attributes`, `DirProperties_`, `Application_`, " | ||
| 42 | L"`Address`, `IP`, `Port`, `Header`, `Secure`, `Log_` FROM `IIsWebSite`, `IIsWebAddress` " | ||
| 43 | L"WHERE `KeyAddress_`=`Address` ORDER BY `Sequence`"; | ||
| 44 | |||
| 45 | LPCWSTR vcsWebAddressQuery = L"SELECT `Address`, `Web_`, `IP`, `Port`, `Header`, `Secure` " | ||
| 46 | L"FROM `IIsWebAddress`"; | ||
| 47 | |||
| 48 | LPCWSTR vcsWebBaseQuery = L"SELECT `Web`, `Id`, `IP`, `Port`, `Header`, `Secure`, `Description` " | ||
| 49 | L"FROM `IIsWebSite`, `IIsWebAddress` " | ||
| 50 | L"WHERE `KeyAddress_`=`Address`"; | ||
| 51 | |||
| 52 | LPCWSTR vcsWebDirQuery = L"SELECT `Web_`, `WebDir`, `Component_`, `Path`, `DirProperties_`, `Application_` " | ||
| 53 | L"FROM `IIsWebDir`"; | ||
| 54 | |||
| 55 | LPCWSTR vcsVDirQuery = L"SELECT `Web_`, `VirtualDir`, `Component_`, `Alias`, `Directory_`, `DirProperties_`, `Application_` " | ||
| 56 | L"FROM `IIsWebVirtualDir`"; | ||
| 57 | |||
| 58 | LPCWSTR vcsFilterQuery = L"SELECT `Web_`, `Name`, `Component_`, `Path`, `Description`, `Flags`, `LoadOrder` FROM `IIsFilter` ORDER BY `Web_`"; | ||
| 59 | |||
| 60 | LPCWSTR vcsPropertyQuery = L"SELECT `Property`, `Component_`, `Attributes`, `Value` " | ||
| 61 | L"FROM `IIsProperty`"; | ||
| 62 | |||
| 63 | #define IIS7CONDITION L"VersionNT >= 600" | ||
| 64 | #define USEIIS7CONDITION IIS7CONDITION L"AND NOT UseIis6Compatibility" | ||
| 65 | |||
| 66 | /******************************************************************** | ||
| 67 | ConfigureIIs - CUSTOM ACTION ENTRY POINT for installing IIs settings | ||
| 68 | |||
| 69 | ********************************************************************/ | ||
| 70 | extern "C" UINT __stdcall ConfigureIIs( | ||
| 71 | __in MSIHANDLE hInstall | ||
| 72 | ) | ||
| 73 | { | ||
| 74 | //AssertSz(FALSE, "debug ConfigureIIs here"); | ||
| 75 | HRESULT hr = S_OK; | ||
| 76 | UINT er = ERROR_SUCCESS; | ||
| 77 | LPWSTR pwzScriptKey = NULL; | ||
| 78 | LPWSTR pwzBackupId = NULL; | ||
| 79 | LPWSTR pwzCustomActionData = NULL; // CustomActionData for ConfigureIIs custom action | ||
| 80 | |||
| 81 | // initialize | ||
| 82 | hr = WcaInitialize(hInstall, "ConfigureIIs"); | ||
| 83 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 84 | |||
| 85 | // check for the prerequsite tables | ||
| 86 | if (S_OK != WcaTableExists(L"IIsWebSite") && S_OK != WcaTableExists(L"IIsFilter") && S_OK != WcaTableExists(L"IIsProperty") && | ||
| 87 | S_OK != WcaTableExists(L"IIsWebServiceExtension") && S_OK != WcaTableExists(L"IIsAppPool")) | ||
| 88 | { | ||
| 89 | WcaLog(LOGMSG_VERBOSE, "skipping IIs CustomAction, no IIsWebSite table, no IIsFilter table, no IIsProperty table, no IIsWebServiceExtension, and no IIsAppPool table"); | ||
| 90 | ExitFunction1(hr = S_FALSE); | ||
| 91 | } | ||
| 92 | |||
| 93 | // Get a CaScript key | ||
| 94 | hr = WcaCaScriptCreateKey(&pwzScriptKey); | ||
| 95 | ExitOnFailure(hr, "Failed to get encoding key."); | ||
| 96 | |||
| 97 | // Generate a unique string to be used for this product's transaction | ||
| 98 | // This prevents a name collision when doing a major upgrade | ||
| 99 | hr = WcaGetProperty(L"ProductCode", &pwzBackupId); | ||
| 100 | ExitOnFailure(hr, "failed to get ProductCode"); | ||
| 101 | |||
| 102 | hr = StrAllocConcat(&pwzBackupId, L"ScaConfigureIIs", 0); | ||
| 103 | ExitOnFailure(hr, "failed to concat ScaConfigureIIs"); | ||
| 104 | |||
| 105 | // make sure the operations below are wrapped in a "transaction" | ||
| 106 | // use IIS7 transaction logic even if using Iis6 compat because Backup/Restore don't work with metabase compatibility | ||
| 107 | if (MSICONDITION_TRUE == ::MsiEvaluateConditionW(hInstall, IIS7CONDITION)) | ||
| 108 | { | ||
| 109 | hr = ScaIIS7ConfigTransaction(pwzBackupId); | ||
| 110 | MessageExitOnFailure(hr, msierrIISFailedSchedTransaction, "failed to start IIS7 transaction"); | ||
| 111 | } | ||
| 112 | else | ||
| 113 | { | ||
| 114 | hr = ScaMetabaseTransaction(pwzBackupId); | ||
| 115 | MessageExitOnFailure(hr, msierrIISFailedSchedTransaction, "failed to start IIS transaction"); | ||
| 116 | } | ||
| 117 | |||
| 118 | // Write the CaScript key to the ConfigureIIS custom action data | ||
| 119 | hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData); | ||
| 120 | ExitOnFailure(hr, "Failed to add encoding key to CustomActionData."); | ||
| 121 | |||
| 122 | // Wrap vcsUserDeferredQuery to send to deferred CA | ||
| 123 | if (S_OK == WcaTableExists(L"User")) | ||
| 124 | { | ||
| 125 | hr = WcaWrapQuery(vcsUserDeferredQuery, &pwzCustomActionData, efmcColumn3 | efmcColumn4 | efmcColumn5, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 126 | ExitOnFailure(hr, "Failed to wrap User query"); | ||
| 127 | } | ||
| 128 | else | ||
| 129 | { | ||
| 130 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 131 | ExitOnFailure(hr, "Failed to wrap User empty query"); | ||
| 132 | } | ||
| 133 | |||
| 134 | // Wrap vcsWebSvcExtQuery to send to deferred CA | ||
| 135 | if (S_OK == WcaTableExists(L"IIsWebServiceExtension")) | ||
| 136 | { | ||
| 137 | hr = WcaWrapQuery(vcsWebSvcExtQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn3 | efmcColumn4, 1, 0xFFFFFFFF); | ||
| 138 | ExitOnFailure(hr, "Failed to wrap IIsWebServiceExtension query"); | ||
| 139 | } | ||
| 140 | else | ||
| 141 | { | ||
| 142 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 143 | ExitOnFailure(hr, "Failed to wrap IIsWebServiceExtension empty query"); | ||
| 144 | } | ||
| 145 | |||
| 146 | // Wrap vcsAppPoolQuery to send to deferred CA | ||
| 147 | if (S_OK == WcaTableExists(L"IIsAppPool")) | ||
| 148 | { | ||
| 149 | hr = WcaWrapQuery(vcsAppPoolQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn15 | efmcColumn16, 3, 0xFFFFFFFF); | ||
| 150 | ExitOnFailure(hr, "Failed to wrap IIsAppPool query"); | ||
| 151 | |||
| 152 | hr = WcaWrapQuery(vcsComponentAttrQuery, &pwzCustomActionData, 0, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 153 | ExitOnFailure(hr, "Failed to wrap Component query"); | ||
| 154 | } | ||
| 155 | else | ||
| 156 | { | ||
| 157 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 158 | ExitOnFailure(hr, "Failed to wrap IIsAppPool empty query"); | ||
| 159 | } | ||
| 160 | |||
| 161 | // Wrap vcsMimeMapQuery to send to deferred CA | ||
| 162 | if (S_OK == WcaTableExists(L"IIsMimeMap")) | ||
| 163 | { | ||
| 164 | hr = WcaWrapQuery(vcsMimeMapQuery, &pwzCustomActionData, efmcColumn4 | efmcColumn5, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 165 | ExitOnFailure(hr, "Failed to wrap IIsMimeMap query"); | ||
| 166 | } | ||
| 167 | else | ||
| 168 | { | ||
| 169 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 170 | ExitOnFailure(hr, "Failed to wrap IIsMimeMap empty query"); | ||
| 171 | } | ||
| 172 | |||
| 173 | // Wrap vcsHttpHeaderQuery to send to deferred CA | ||
| 174 | if (S_OK == WcaTableExists(L"IIsHttpHeader")) | ||
| 175 | { | ||
| 176 | hr = WcaWrapQuery(vcsHttpHeaderQuery, &pwzCustomActionData, efmcColumn1 | efmcColumn4, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 177 | ExitOnFailure(hr, "Failed to wrap IIsHttpHeader query"); | ||
| 178 | } | ||
| 179 | else | ||
| 180 | { | ||
| 181 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 182 | ExitOnFailure(hr, "Failed to wrap IIsHttpHeader empty query"); | ||
| 183 | } | ||
| 184 | |||
| 185 | // Wrap vcsWebErrorQuery to send to deferred CA | ||
| 186 | if (S_OK == WcaTableExists(L"IIsWebError")) | ||
| 187 | { | ||
| 188 | hr = WcaWrapQuery(vcsWebErrorQuery, &pwzCustomActionData, efmcColumn5 | efmcColumn6, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 189 | ExitOnFailure(hr, "Failed to wrap IIsWebError query"); | ||
| 190 | } | ||
| 191 | else | ||
| 192 | { | ||
| 193 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 194 | ExitOnFailure(hr, "Failed to wrap IIsWebError empty query"); | ||
| 195 | } | ||
| 196 | |||
| 197 | // Wrap vcsWebDirPropertiesQuery to send to deferred CA | ||
| 198 | if (S_OK == WcaTableExists(L"IIsWebDirProperties")) | ||
| 199 | { | ||
| 200 | hr = WcaWrapQuery(vcsWebDirPropertiesQuery, &pwzCustomActionData, efmcColumn8 | efmcColumn10 | efmcColumn12 | efmcColumn15, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 201 | ExitOnFailure(hr, "Failed to wrap IIsWebDirProperties query"); | ||
| 202 | } | ||
| 203 | else | ||
| 204 | { | ||
| 205 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 206 | ExitOnFailure(hr, "Failed to wrap IIsWebDirProperties empty query"); | ||
| 207 | } | ||
| 208 | |||
| 209 | // Wrap vcsSslCertificateQuery to send to deferred CA | ||
| 210 | if (S_OK == WcaTableExists(L"Certificate") && S_OK == WcaTableExists(L"CertificateHash") && S_OK == WcaTableExists(L"IIsWebSiteCertificates")) | ||
| 211 | { | ||
| 212 | hr = WcaWrapQuery(vcsSslCertificateQuery, &pwzCustomActionData, 0, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 213 | ExitOnFailure(hr, "Failed to wrap SslCertificate query"); | ||
| 214 | } | ||
| 215 | else | ||
| 216 | { | ||
| 217 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 218 | ExitOnFailure(hr, "Failed to wrap SslCertificate empty query"); | ||
| 219 | } | ||
| 220 | |||
| 221 | // Wrap vcsWebLogQuery to send to deferred CA | ||
| 222 | if (S_OK == WcaTableExists(L"IIsWebLog")) | ||
| 223 | { | ||
| 224 | hr = WcaWrapQuery(vcsWebLogQuery, &pwzCustomActionData, efmcColumn2, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 225 | ExitOnFailure(hr, "Failed to wrap IIsWebLog query"); | ||
| 226 | } | ||
| 227 | else | ||
| 228 | { | ||
| 229 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 230 | ExitOnFailure(hr, "Failed to wrap IIsWebLog empty query"); | ||
| 231 | } | ||
| 232 | |||
| 233 | // Wrap vcsWebApplicationQuery to send to deferred CA | ||
| 234 | if (S_OK == WcaTableExists(L"IIsWebApplication")) | ||
| 235 | { | ||
| 236 | hr = WcaWrapQuery(vcsWebApplicationQuery, &pwzCustomActionData, efmcColumn1, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 237 | ExitOnFailure(hr, "Failed to wrap IIsWebApplication query"); | ||
| 238 | } | ||
| 239 | else | ||
| 240 | { | ||
| 241 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 242 | ExitOnFailure(hr, "Failed to wrap IIsWebApplication empty query"); | ||
| 243 | } | ||
| 244 | |||
| 245 | // Wrap vcsWebAppExtensionQuery to send to deferred CA | ||
| 246 | if (S_OK == WcaTableExists(L"IIsWebApplicationExtension")) | ||
| 247 | { | ||
| 248 | hr = WcaWrapQuery(vcsWebAppExtensionQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn3, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 249 | ExitOnFailure(hr, "Failed to wrap IIsWebApplicationExtension query"); | ||
| 250 | } | ||
| 251 | else | ||
| 252 | { | ||
| 253 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 254 | ExitOnFailure(hr, "Failed to wrap IIsWebApplicationExtension empty query"); | ||
| 255 | } | ||
| 256 | |||
| 257 | // Wrap vcsWebQuery, vcsWebAddressQuery, and vcsWebBaseQuery to send to deferred CA | ||
| 258 | if (S_OK == WcaTableExists(L"IIsWebAddress") && S_OK == WcaTableExists(L"IIsWebSite")) | ||
| 259 | { | ||
| 260 | hr = WcaWrapQuery(vcsWebQuery, &pwzCustomActionData, efmcColumn3 | efmcColumn4 | efmcColumn12 | efmcColumn13 | efmcColumn14, 2, 6); | ||
| 261 | ExitOnFailure(hr, "Failed to wrap IIsWebSite query"); | ||
| 262 | |||
| 263 | hr = WcaWrapQuery(vcsWebAddressQuery, &pwzCustomActionData, efmcColumn3 | efmcColumn4 | efmcColumn5, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 264 | ExitOnFailure(hr, "Failed to wrap IIsWebAddress query"); | ||
| 265 | |||
| 266 | hr = WcaWrapQuery(vcsWebBaseQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn3 | efmcColumn4 | efmcColumn5 | efmcColumn7, 0xFFFFFFFF, 0xFFFFFFFF); | ||
| 267 | ExitOnFailure(hr, "Failed to wrap IIsWebBase query"); | ||
| 268 | } | ||
| 269 | else | ||
| 270 | { | ||
| 271 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 272 | ExitOnFailure(hr, "Failed to wrap IIsWebSite empty query"); | ||
| 273 | |||
| 274 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 275 | ExitOnFailure(hr, "Failed to wrap IIsWebAddress empty query"); | ||
| 276 | |||
| 277 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 278 | ExitOnFailure(hr, "Failed to wrap IIsWebBase empty query"); | ||
| 279 | } | ||
| 280 | |||
| 281 | // Wrap vcsWebDirQuery to send to deferred CA | ||
| 282 | if (S_OK == WcaTableExists(L"IIsWebDir")) | ||
| 283 | { | ||
| 284 | hr = WcaWrapQuery(vcsWebDirQuery, &pwzCustomActionData, efmcColumn4, 3, 0xFFFFFFFF); | ||
| 285 | ExitOnFailure(hr, "Failed to wrap IIsWebDir query"); | ||
| 286 | } | ||
| 287 | else | ||
| 288 | { | ||
| 289 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 290 | ExitOnFailure(hr, "Failed to wrap IIsWebDir empty query"); | ||
| 291 | } | ||
| 292 | |||
| 293 | // Wrap vcsVDirQuery to send to deferred CA | ||
| 294 | if (S_OK == WcaTableExists(L"IIsWebVirtualDir")) | ||
| 295 | { | ||
| 296 | hr = WcaWrapQuery(vcsVDirQuery, &pwzCustomActionData, efmcColumn4, 3, 5); | ||
| 297 | ExitOnFailure(hr, "Failed to wrap IIsWebVirtualDir query"); | ||
| 298 | } | ||
| 299 | else | ||
| 300 | { | ||
| 301 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 302 | ExitOnFailure(hr, "Failed to wrap IIsWebVirtualDir empty query"); | ||
| 303 | } | ||
| 304 | |||
| 305 | // Wrap vcsFilterQuery to send to deferred CA | ||
| 306 | if (S_OK == WcaTableExists(L"IIsFilter")) | ||
| 307 | { | ||
| 308 | hr = WcaWrapQuery(vcsFilterQuery, &pwzCustomActionData, efmcColumn4 | efmcColumn5, 3, 0xFFFFFFFF); | ||
| 309 | ExitOnFailure(hr, "Failed to wrap IIsFilter query"); | ||
| 310 | } | ||
| 311 | else | ||
| 312 | { | ||
| 313 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 314 | ExitOnFailure(hr, "Failed to wrap IIsFilter empty query"); | ||
| 315 | } | ||
| 316 | |||
| 317 | // Wrap vcsPropertyQuery to send to deferred CA | ||
| 318 | if (S_OK == WcaTableExists(L"IIsProperty")) | ||
| 319 | { | ||
| 320 | hr = WcaWrapQuery(vcsPropertyQuery, &pwzCustomActionData, efmcColumn4, 2, 0xFFFFFFFF); | ||
| 321 | ExitOnFailure(hr, "Failed to wrap IIsProperty query"); | ||
| 322 | } | ||
| 323 | else | ||
| 324 | { | ||
| 325 | hr = WcaWrapEmptyQuery(&pwzCustomActionData); | ||
| 326 | ExitOnFailure(hr, "Failed to wrap IIsProperty empty query"); | ||
| 327 | } | ||
| 328 | |||
| 329 | if (MSICONDITION_TRUE == ::MsiEvaluateConditionW(hInstall, USEIIS7CONDITION)) | ||
| 330 | { | ||
| 331 | // This must remain trace only, CA data may contain password | ||
| 332 | WcaLog(LOGMSG_TRACEONLY, "Custom Action Data for ConfigureIIS7Exec will be: %ls", pwzCustomActionData); | ||
| 333 | |||
| 334 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ConfigureIIs7Exec"), pwzCustomActionData, ConfigureIIsCost); | ||
| 335 | ExitOnFailure(hr, "Failed to schedule ConfigureIIs7Exec custom action"); | ||
| 336 | |||
| 337 | ReleaseNullStr(pwzCustomActionData); | ||
| 338 | |||
| 339 | // Write the CaScript key to the ConfigureIIS custom action data | ||
| 340 | hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData); | ||
| 341 | ExitOnFailure(hr, "Failed to add script key to CustomActionData."); | ||
| 342 | |||
| 343 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"WriteIIS7ConfigChanges"), pwzCustomActionData, WriteIIS7ConfigChangesCost); | ||
| 344 | ExitOnFailure(hr, "Failed to schedule WriteMetabaseChanges custom action"); | ||
| 345 | } | ||
| 346 | else | ||
| 347 | { | ||
| 348 | // This must remain trace only, CA data may contain password | ||
| 349 | WcaLog(LOGMSG_TRACEONLY, "Custom Action Data for ConfigureIISExec will be: %ls", pwzCustomActionData); | ||
| 350 | |||
| 351 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ConfigureIIsExec"), pwzCustomActionData, ConfigureIIsCost); | ||
| 352 | ExitOnFailure(hr, "Failed to schedule ConfigureIISExec custom action"); | ||
| 353 | |||
| 354 | ReleaseNullStr(pwzCustomActionData); | ||
| 355 | |||
| 356 | // Write the CaScript key to the ConfigureIIS custom action data | ||
| 357 | hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData); | ||
| 358 | ExitOnFailure(hr, "Failed to add script key to CustomActionData."); | ||
| 359 | |||
| 360 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"WriteMetabaseChanges"), pwzCustomActionData, WriteMetabaseChangesCost); | ||
| 361 | ExitOnFailure(hr, "Failed to schedule WriteMetabaseChanges custom action"); | ||
| 362 | } | ||
| 363 | |||
| 364 | LExit: | ||
| 365 | ReleaseStr(pwzScriptKey); | ||
| 366 | ReleaseStr(pwzBackupId); | ||
| 367 | ReleaseStr(pwzCustomActionData); | ||
| 368 | |||
| 369 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 370 | return WcaFinalize(er); | ||
| 371 | } | ||
| 372 | |||
| 373 | /******************************************************************** | ||
| 374 | ConfigureIIsExec - custom action for installing IIs settings - table | ||
| 375 | data will be wrapped and passed in from immediate CA | ||
| 376 | ReadIIsTables | ||
| 377 | |||
| 378 | ********************************************************************/ | ||
| 379 | extern "C" UINT __stdcall ConfigureIIsExec( | ||
| 380 | __in MSIHANDLE hInstall | ||
| 381 | ) | ||
| 382 | { | ||
| 383 | //AssertSz(FALSE, "debug ConfigureIIsExec here"); | ||
| 384 | HRESULT hr = S_OK; | ||
| 385 | UINT er = ERROR_SUCCESS; | ||
| 386 | |||
| 387 | BOOL fInitializedCom = FALSE; | ||
| 388 | IMSAdminBase* piMetabase = NULL; | ||
| 389 | |||
| 390 | SCA_WEB* pswList = NULL; | ||
| 391 | SCA_WEBDIR* pswdList = NULL; | ||
| 392 | SCA_VDIR* psvdList = NULL; | ||
| 393 | SCA_FILTER* psfList = NULL; | ||
| 394 | SCA_APPPOOL *psapList = NULL; | ||
| 395 | SCA_MIMEMAP* psmmList = NULL; | ||
| 396 | SCA_HTTP_HEADER* pshhList = NULL; | ||
| 397 | SCA_PROPERTY *pspList = NULL; | ||
| 398 | SCA_WEBSVCEXT* psWseList = NULL; | ||
| 399 | SCA_WEB_ERROR* psweList = NULL; | ||
| 400 | |||
| 401 | LPWSTR pwzScriptKey = NULL; | ||
| 402 | LPWSTR pwzCustomActionData = NULL; | ||
| 403 | |||
| 404 | WCA_WRAPQUERY_HANDLE hUserQuery = NULL; | ||
| 405 | WCA_WRAPQUERY_HANDLE hWebBaseQuery = NULL; | ||
| 406 | WCA_WRAPQUERY_HANDLE hWebDirPropQuery = NULL; | ||
| 407 | WCA_WRAPQUERY_HANDLE hSslCertQuery = NULL; | ||
| 408 | WCA_WRAPQUERY_HANDLE hWebLogQuery = NULL; | ||
| 409 | WCA_WRAPQUERY_HANDLE hWebAppQuery = NULL; | ||
| 410 | WCA_WRAPQUERY_HANDLE hWebAppExtQuery = NULL; | ||
| 411 | |||
| 412 | // initialize | ||
| 413 | hr = WcaInitialize(hInstall, "ConfigureIIsExec"); | ||
| 414 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 415 | |||
| 416 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
| 417 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 418 | |||
| 419 | // Get the CaScript key | ||
| 420 | hr = WcaReadStringFromCaData(&pwzCustomActionData, &pwzScriptKey); | ||
| 421 | ExitOnFailure(hr, "Failed to get CaScript key from custom action data"); | ||
| 422 | |||
| 423 | hr = ::CoInitialize(NULL); | ||
| 424 | ExitOnFailure(hr, "failed to initialize COM"); | ||
| 425 | fInitializedCom = TRUE; | ||
| 426 | |||
| 427 | // if IIS was uninstalled (thus no IID_IMSAdminBase) allow the | ||
| 428 | // user to still uninstall this package by clicking "Ignore" | ||
| 429 | do | ||
| 430 | { | ||
| 431 | hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void**)&piMetabase); | ||
| 432 | if (FAILED(hr)) | ||
| 433 | { | ||
| 434 | WcaLog(LOGMSG_STANDARD, "failed to get IID_IMSAdminBase Object"); | ||
| 435 | er = WcaErrorMessage(msierrIISCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 436 | switch (er) | ||
| 437 | { | ||
| 438 | case IDABORT: | ||
| 439 | ExitFunction(); // bail with the error result from the CoCreate to kick off a rollback | ||
| 440 | case IDRETRY: | ||
| 441 | hr = S_FALSE; // hit me, baby, one more time | ||
| 442 | break; | ||
| 443 | case IDIGNORE: | ||
| 444 | __fallthrough; | ||
| 445 | default: | ||
| 446 | WcaLog(LOGMSG_STANDARD, "ignoring absent IIS"); | ||
| 447 | // We need to write the empty script to communicate to other deferred CA that there is noting to do. | ||
| 448 | hr = ScaWriteConfigurationScript(pwzScriptKey); | ||
| 449 | ExitOnFailure(hr, "failed to schedule metabase configuration"); | ||
| 450 | |||
| 451 | ExitFunction1(hr = S_OK); // pretend everything is okay | ||
| 452 | break; | ||
| 453 | } | ||
| 454 | } | ||
| 455 | } while (S_FALSE == hr); | ||
| 456 | |||
| 457 | // read the msi tables | ||
| 458 | hr = WcaBeginUnwrapQuery(&hUserQuery, &pwzCustomActionData); | ||
| 459 | ExitOnFailure(hr, "Failed to unwrap user query"); | ||
| 460 | |||
| 461 | hr = ScaWebSvcExtRead(&psWseList, &pwzCustomActionData); | ||
| 462 | MessageExitOnFailure(hr, msierrIISFailedReadWebSvcExt, "failed while processing WebServiceExtensions"); | ||
| 463 | |||
| 464 | hr = ScaAppPoolRead(&psapList, hUserQuery, &pwzCustomActionData); | ||
| 465 | MessageExitOnFailure(hr, msierrIISFailedReadAppPool, "failed while processing WebAppPools"); | ||
| 466 | |||
| 467 | // MimeMap, Error and HttpHeader need to be read before the virtual directory and web read | ||
| 468 | hr = ScaMimeMapRead(&psmmList, &pwzCustomActionData); | ||
| 469 | MessageExitOnFailure(hr, msierrIISFailedReadMimeMap, "failed while processing MimeMaps"); | ||
| 470 | |||
| 471 | hr = ScaHttpHeaderRead(&pshhList, &pwzCustomActionData); | ||
| 472 | MessageExitOnFailure(hr, msierrIISFailedReadHttpHeader, "failed while processing HttpHeaders"); | ||
| 473 | |||
| 474 | hr = ScaWebErrorRead(&psweList, &pwzCustomActionData); | ||
| 475 | MessageExitOnFailure(hr, msierrIISFailedReadWebError, "failed while processing WebErrors"); | ||
| 476 | |||
| 477 | hr = WcaBeginUnwrapQuery(&hWebDirPropQuery, &pwzCustomActionData); | ||
| 478 | ExitOnFailure(hr, "Failed to unwrap web dir properties query"); | ||
| 479 | |||
| 480 | hr = WcaBeginUnwrapQuery(&hSslCertQuery, &pwzCustomActionData); | ||
| 481 | ExitOnFailure(hr, "Failed to unwrap ssl certificate query"); | ||
| 482 | |||
| 483 | hr = WcaBeginUnwrapQuery(&hWebLogQuery, &pwzCustomActionData); | ||
| 484 | ExitOnFailure(hr, "Failed to unwrap web log query"); | ||
| 485 | |||
| 486 | hr = WcaBeginUnwrapQuery(&hWebAppQuery, &pwzCustomActionData); | ||
| 487 | ExitOnFailure(hr, "Failed to unwrap web application query"); | ||
| 488 | |||
| 489 | hr = WcaBeginUnwrapQuery(&hWebAppExtQuery, &pwzCustomActionData); | ||
| 490 | ExitOnFailure(hr, "Failed to unwrap web application extension query"); | ||
| 491 | |||
| 492 | hr = ScaWebsRead(piMetabase, &psmmList, &pswList, &pshhList, &psweList, hUserQuery, hWebDirPropQuery, hSslCertQuery, hWebLogQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData); | ||
| 493 | MessageExitOnFailure(hr, msierrIISFailedReadWebSite, "failed while processing WebSites"); | ||
| 494 | |||
| 495 | hr = WcaBeginUnwrapQuery(&hWebBaseQuery, &pwzCustomActionData); | ||
| 496 | ExitOnFailure(hr, "Failed to unwrap web base query"); | ||
| 497 | |||
| 498 | hr = ScaWebDirsRead(piMetabase, pswList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData, &pswdList); | ||
| 499 | MessageExitOnFailure(hr, msierrIISFailedReadWebDirs, "failed while processing WebDirs"); | ||
| 500 | |||
| 501 | hr = ScaVirtualDirsRead(piMetabase, pswList, &psvdList, &psmmList, &pshhList, &psweList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData); | ||
| 502 | MessageExitOnFailure(hr, msierrIISFailedReadVDirs, "failed while processing WebVirtualDirs"); | ||
| 503 | |||
| 504 | hr = ScaFiltersRead(piMetabase, pswList, hWebBaseQuery, &psfList, &pwzCustomActionData); | ||
| 505 | MessageExitOnFailure(hr, msierrIISFailedReadFilters, "failed while processing WebFilters"); | ||
| 506 | |||
| 507 | hr = ScaPropertyRead(&pspList, &pwzCustomActionData); | ||
| 508 | MessageExitOnFailure(hr, msierrIISFailedReadProp, "failed while processing WebProperties"); | ||
| 509 | |||
| 510 | // do uninstall actions (order is important!) | ||
| 511 | hr = ScaPropertyUninstall(piMetabase, pspList); | ||
| 512 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallProp, "failed to uninstall IIS properties"); | ||
| 513 | |||
| 514 | hr = ScaFiltersUninstall(piMetabase, psfList); | ||
| 515 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallFilters, "failed to schedule uninstall of filters"); | ||
| 516 | |||
| 517 | hr = ScaVirtualDirsUninstall(piMetabase, psvdList); | ||
| 518 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallVDirs, "failed to schedule uninstall of virtual directories"); | ||
| 519 | |||
| 520 | hr = ScaWebDirsUninstall(piMetabase, pswdList); | ||
| 521 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebDirs, "failed to schedule uninstall of web directories"); | ||
| 522 | |||
| 523 | hr = ScaWebsUninstall(piMetabase, pswList); | ||
| 524 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebs, "failed to schedule uninstall of webs"); | ||
| 525 | |||
| 526 | hr = ScaAppPoolUninstall(piMetabase, psapList); | ||
| 527 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallAppPool, "failed to schedule uninstall of AppPools"); | ||
| 528 | |||
| 529 | |||
| 530 | // do install actions (order is important!) | ||
| 531 | // ScaWebSvcExtCommit contains both uninstall and install actions. | ||
| 532 | hr = ScaWebSvcExtCommit(piMetabase, psWseList); | ||
| 533 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebSvcExt, "failed to schedule install/uninstall of WebSvcExt"); | ||
| 534 | |||
| 535 | hr = ScaAppPoolInstall(piMetabase, psapList); | ||
| 536 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallAppPool, "failed to schedule install of AppPools"); | ||
| 537 | |||
| 538 | hr = ScaWebsInstall(piMetabase, pswList, psapList); | ||
| 539 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebs, "failed to schedule install of webs"); | ||
| 540 | |||
| 541 | hr = ScaWebDirsInstall(piMetabase, pswdList, psapList); | ||
| 542 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebDirs, "failed to schedule install of web directories"); | ||
| 543 | |||
| 544 | hr = ScaVirtualDirsInstall(piMetabase, psvdList, psapList); | ||
| 545 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallVDirs, "failed to schedule install of virtual directories"); | ||
| 546 | |||
| 547 | hr = ScaFiltersInstall(piMetabase, psfList); | ||
| 548 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallFilters, "failed to schedule install of filters"); | ||
| 549 | |||
| 550 | hr = ScaPropertyInstall(piMetabase, pspList); | ||
| 551 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallProp, "failed to schedule install of properties"); | ||
| 552 | |||
| 553 | hr = ScaWriteConfigurationScript(pwzScriptKey); | ||
| 554 | ExitOnFailure(hr, "failed to schedule metabase configuration"); | ||
| 555 | |||
| 556 | LExit: | ||
| 557 | ReleaseStr(pwzScriptKey); | ||
| 558 | ReleaseStr(pwzCustomActionData); | ||
| 559 | |||
| 560 | WcaFinishUnwrapQuery(hUserQuery); | ||
| 561 | WcaFinishUnwrapQuery(hWebBaseQuery); | ||
| 562 | WcaFinishUnwrapQuery(hWebDirPropQuery); | ||
| 563 | WcaFinishUnwrapQuery(hSslCertQuery); | ||
| 564 | WcaFinishUnwrapQuery(hWebLogQuery); | ||
| 565 | WcaFinishUnwrapQuery(hWebAppQuery); | ||
| 566 | WcaFinishUnwrapQuery(hWebAppExtQuery); | ||
| 567 | |||
| 568 | if (psWseList) | ||
| 569 | { | ||
| 570 | ScaWebSvcExtFreeList(psWseList); | ||
| 571 | } | ||
| 572 | |||
| 573 | if (psfList) | ||
| 574 | { | ||
| 575 | ScaFiltersFreeList(psfList); | ||
| 576 | } | ||
| 577 | |||
| 578 | if (psvdList) | ||
| 579 | { | ||
| 580 | ScaVirtualDirsFreeList(psvdList); | ||
| 581 | } | ||
| 582 | |||
| 583 | if (pswdList) | ||
| 584 | { | ||
| 585 | ScaWebDirsFreeList(pswdList); | ||
| 586 | } | ||
| 587 | |||
| 588 | if (pswList) | ||
| 589 | { | ||
| 590 | ScaWebsFreeList(pswList); | ||
| 591 | } | ||
| 592 | |||
| 593 | if (psmmList) | ||
| 594 | { | ||
| 595 | ScaMimeMapCheckList(psmmList); | ||
| 596 | ScaMimeMapFreeList(psmmList); | ||
| 597 | } | ||
| 598 | |||
| 599 | if (pshhList) | ||
| 600 | { | ||
| 601 | ScaHttpHeaderCheckList(pshhList); | ||
| 602 | ScaHttpHeaderFreeList(pshhList); | ||
| 603 | } | ||
| 604 | |||
| 605 | if (psweList) | ||
| 606 | { | ||
| 607 | ScaWebErrorCheckList(psweList); | ||
| 608 | ScaWebErrorFreeList(psweList); | ||
| 609 | } | ||
| 610 | |||
| 611 | ReleaseObject(piMetabase); | ||
| 612 | |||
| 613 | if (fInitializedCom) | ||
| 614 | { | ||
| 615 | ::CoUninitialize(); | ||
| 616 | } | ||
| 617 | |||
| 618 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 619 | return WcaFinalize(er); | ||
| 620 | } | ||
| 621 | |||
| 622 | |||
| 623 | /******************************************************************** | ||
| 624 | ConfigureIIs - CUSTOM ACTION ENTRY POINT for installing IIs settings | ||
| 625 | |||
| 626 | ********************************************************************/ | ||
| 627 | extern "C" UINT __stdcall ConfigureIIs7Exec( | ||
| 628 | __in MSIHANDLE hInstall | ||
| 629 | ) | ||
| 630 | { | ||
| 631 | //AssertSz(FALSE, "debug ConfigureIIs7Exec here"); | ||
| 632 | HRESULT hr = S_OK; | ||
| 633 | UINT er = ERROR_SUCCESS; | ||
| 634 | |||
| 635 | LPWSTR pwzScriptKey = NULL; | ||
| 636 | LPWSTR pwzCustomActionData = NULL; | ||
| 637 | |||
| 638 | SCA_WEB7* pswList = NULL; | ||
| 639 | SCA_WEBDIR7* pswdList = NULL; | ||
| 640 | SCA_VDIR7* psvdList = NULL; | ||
| 641 | SCA_FILTER* psfList = NULL; | ||
| 642 | SCA_APPPOOL *psapList = NULL; | ||
| 643 | SCA_MIMEMAP* psmmList = NULL; | ||
| 644 | SCA_HTTP_HEADER* pshhList = NULL; | ||
| 645 | SCA_PROPERTY *pspList = NULL; | ||
| 646 | SCA_WEBSVCEXT* psWseList = NULL; | ||
| 647 | SCA_WEB_ERROR* psweList = NULL; | ||
| 648 | |||
| 649 | WCA_WRAPQUERY_HANDLE hUserQuery = NULL; | ||
| 650 | WCA_WRAPQUERY_HANDLE hWebBaseQuery = NULL; | ||
| 651 | WCA_WRAPQUERY_HANDLE hWebDirPropQuery = NULL; | ||
| 652 | WCA_WRAPQUERY_HANDLE hSslCertQuery = NULL; | ||
| 653 | WCA_WRAPQUERY_HANDLE hWebLogQuery = NULL; | ||
| 654 | WCA_WRAPQUERY_HANDLE hWebAppQuery = NULL; | ||
| 655 | WCA_WRAPQUERY_HANDLE hWebAppExtQuery = NULL; | ||
| 656 | |||
| 657 | // initialize | ||
| 658 | hr = WcaInitialize(hInstall, "ConfigureIIs7Exec"); | ||
| 659 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 660 | |||
| 661 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
| 662 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 663 | |||
| 664 | // Get the CaScript key | ||
| 665 | hr = WcaReadStringFromCaData(&pwzCustomActionData, &pwzScriptKey); | ||
| 666 | ExitOnFailure(hr, "Failed to get CaScript key from custom action data"); | ||
| 667 | |||
| 668 | // read the msi tables | ||
| 669 | hr = WcaBeginUnwrapQuery(&hUserQuery, &pwzCustomActionData); | ||
| 670 | ExitOnFailure(hr, "Failed to unwrap user query"); | ||
| 671 | |||
| 672 | hr = ScaWebSvcExtRead(&psWseList, &pwzCustomActionData); | ||
| 673 | MessageExitOnFailure(hr, msierrIISFailedReadWebSvcExt, "failed while processing WebServiceExtensions"); | ||
| 674 | |||
| 675 | hr = ScaAppPoolRead(&psapList, hUserQuery, &pwzCustomActionData); | ||
| 676 | MessageExitOnFailure(hr, msierrIISFailedReadAppPool, "failed while processing WebAppPools"); | ||
| 677 | |||
| 678 | // MimeMap, Error and HttpHeader need to be read before the virtual directory and web read | ||
| 679 | hr = ScaMimeMapRead(&psmmList, &pwzCustomActionData); | ||
| 680 | MessageExitOnFailure(hr, msierrIISFailedReadMimeMap, "failed while processing MimeMaps"); | ||
| 681 | |||
| 682 | hr = ScaHttpHeaderRead(&pshhList, &pwzCustomActionData); | ||
| 683 | MessageExitOnFailure(hr, msierrIISFailedReadHttpHeader, "failed while processing HttpHeaders"); | ||
| 684 | |||
| 685 | hr = ScaWebErrorRead(&psweList, &pwzCustomActionData); | ||
| 686 | MessageExitOnFailure(hr, msierrIISFailedReadWebError, "failed while processing WebErrors"); | ||
| 687 | |||
| 688 | hr = WcaBeginUnwrapQuery(&hWebDirPropQuery, &pwzCustomActionData); | ||
| 689 | ExitOnFailure(hr, "Failed to unwrap web dir properties query"); | ||
| 690 | |||
| 691 | hr = WcaBeginUnwrapQuery(&hSslCertQuery, &pwzCustomActionData); | ||
| 692 | ExitOnFailure(hr, "Failed to unwrap ssl certificate query"); | ||
| 693 | |||
| 694 | hr = WcaBeginUnwrapQuery(&hWebLogQuery, &pwzCustomActionData); | ||
| 695 | ExitOnFailure(hr, "Failed to unwrap web log query"); | ||
| 696 | |||
| 697 | hr = WcaBeginUnwrapQuery(&hWebAppQuery, &pwzCustomActionData); | ||
| 698 | ExitOnFailure(hr, "Failed to unwrap web application query"); | ||
| 699 | |||
| 700 | hr = WcaBeginUnwrapQuery(&hWebAppExtQuery, &pwzCustomActionData); | ||
| 701 | ExitOnFailure(hr, "Failed to unwrap web application extension query"); | ||
| 702 | |||
| 703 | hr = ScaWebsRead7(&pswList, &pshhList, &psweList, hUserQuery, hWebDirPropQuery, hSslCertQuery, hWebLogQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData); | ||
| 704 | MessageExitOnFailure(hr, msierrIISFailedReadWebSite, "failed while processing WebSites"); | ||
| 705 | |||
| 706 | hr = WcaBeginUnwrapQuery(&hWebBaseQuery, &pwzCustomActionData); | ||
| 707 | ExitOnFailure(hr, "Failed to unwrap web base query"); | ||
| 708 | |||
| 709 | hr = ScaWebDirsRead7(pswList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData, &pswdList); | ||
| 710 | MessageExitOnFailure(hr, msierrIISFailedReadWebDirs, "failed while processing WebDirs"); | ||
| 711 | |||
| 712 | hr = ScaVirtualDirsRead7(pswList, &psvdList, &psmmList, &pshhList, &psweList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData); | ||
| 713 | MessageExitOnFailure(hr, msierrIISFailedReadVDirs, "failed while processing WebVirtualDirs"); | ||
| 714 | |||
| 715 | hr = ScaFiltersRead7(pswList, hWebBaseQuery, &psfList, &pwzCustomActionData); | ||
| 716 | MessageExitOnFailure(hr, msierrIISFailedReadFilters, "failed while processing WebFilters"); | ||
| 717 | |||
| 718 | hr = ScaPropertyRead(&pspList, &pwzCustomActionData); | ||
| 719 | MessageExitOnFailure(hr, msierrIISFailedReadProp, "failed while processing WebProperties"); | ||
| 720 | |||
| 721 | // do uninstall actions (order is important!) | ||
| 722 | hr = ScaPropertyUninstall7(pspList); | ||
| 723 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallProp, "failed to uninstall IIS properties"); | ||
| 724 | |||
| 725 | hr = ScaFiltersUninstall7(psfList); | ||
| 726 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallFilters, "failed to schedule uninstall of filters"); | ||
| 727 | |||
| 728 | hr = ScaVirtualDirsUninstall7(psvdList); | ||
| 729 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallVDirs, "failed to schedule uninstall of virtual directories"); | ||
| 730 | |||
| 731 | hr = ScaWebDirsUninstall7(pswdList); | ||
| 732 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebDirs, "failed to schedule uninstall of web directories"); | ||
| 733 | |||
| 734 | hr = ScaWebsUninstall7(pswList); | ||
| 735 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebs, "failed to schedule uninstall of webs"); | ||
| 736 | |||
| 737 | hr = ScaAppPoolUninstall7(psapList); | ||
| 738 | MessageExitOnFailure(hr, msierrIISFailedSchedUninstallAppPool, "failed to schedule uninstall of AppPools"); | ||
| 739 | |||
| 740 | |||
| 741 | // do install actions (order is important!) | ||
| 742 | // ScaWebSvcExtCommit contains both uninstall and install actions. | ||
| 743 | hr = ScaWebSvcExtCommit7(psWseList); | ||
| 744 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebSvcExt, "failed to schedule install/uninstall of WebSvcExt"); | ||
| 745 | |||
| 746 | hr = ScaAppPoolInstall7(psapList); | ||
| 747 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallAppPool, "failed to schedule install of AppPools"); | ||
| 748 | |||
| 749 | hr = ScaWebsInstall7(pswList, psapList); | ||
| 750 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebs, "failed to schedule install of webs"); | ||
| 751 | |||
| 752 | hr = ScaWebDirsInstall7(pswdList, psapList); | ||
| 753 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebDirs, "failed to schedule install of web directories"); | ||
| 754 | |||
| 755 | hr = ScaVirtualDirsInstall7(psvdList, psapList); | ||
| 756 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallVDirs, "failed to schedule install of virtual directories"); | ||
| 757 | |||
| 758 | hr = ScaFiltersInstall7(psfList); | ||
| 759 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallFilters, "failed to schedule install of filters"); | ||
| 760 | |||
| 761 | hr = ScaPropertyInstall7(pspList); | ||
| 762 | MessageExitOnFailure(hr, msierrIISFailedSchedInstallProp, "failed to schedule install of properties"); | ||
| 763 | |||
| 764 | hr = ScaWriteConfigurationScript(pwzScriptKey); | ||
| 765 | ExitOnFailure(hr, "failed to schedule metabase configuration"); | ||
| 766 | |||
| 767 | LExit: | ||
| 768 | ReleaseNullStr(pwzScriptKey); | ||
| 769 | ReleaseNullStr(pwzCustomActionData); | ||
| 770 | |||
| 771 | WcaFinishUnwrapQuery(hUserQuery); | ||
| 772 | WcaFinishUnwrapQuery(hWebBaseQuery); | ||
| 773 | WcaFinishUnwrapQuery(hWebDirPropQuery); | ||
| 774 | WcaFinishUnwrapQuery(hSslCertQuery); | ||
| 775 | WcaFinishUnwrapQuery(hWebLogQuery); | ||
| 776 | WcaFinishUnwrapQuery(hWebAppQuery); | ||
| 777 | WcaFinishUnwrapQuery(hWebAppExtQuery); | ||
| 778 | |||
| 779 | if (psWseList) | ||
| 780 | { | ||
| 781 | ScaWebSvcExtFreeList(psWseList); | ||
| 782 | } | ||
| 783 | |||
| 784 | if (psfList) | ||
| 785 | { | ||
| 786 | ScaFiltersFreeList(psfList); | ||
| 787 | } | ||
| 788 | |||
| 789 | if (psvdList) | ||
| 790 | { | ||
| 791 | ScaVirtualDirsFreeList7(psvdList); | ||
| 792 | } | ||
| 793 | |||
| 794 | if (pswdList) | ||
| 795 | { | ||
| 796 | ScaWebDirsFreeList7(pswdList); | ||
| 797 | } | ||
| 798 | |||
| 799 | if (pswList) | ||
| 800 | { | ||
| 801 | ScaWebsFreeList7(pswList); | ||
| 802 | } | ||
| 803 | |||
| 804 | if (psmmList) | ||
| 805 | { | ||
| 806 | ScaMimeMapFreeList(psmmList); | ||
| 807 | } | ||
| 808 | |||
| 809 | if (pshhList) | ||
| 810 | { | ||
| 811 | ScaHttpHeaderCheckList(pshhList); | ||
| 812 | ScaHttpHeaderFreeList(pshhList); | ||
| 813 | } | ||
| 814 | |||
| 815 | if (psweList) | ||
| 816 | { | ||
| 817 | ScaWebErrorCheckList(psweList); | ||
| 818 | ScaWebErrorFreeList(psweList); | ||
| 819 | } | ||
| 820 | |||
| 821 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 822 | return WcaFinalize(er); | ||
| 823 | } | ||
diff --git a/src/ext/Iis/ca/scassl.cpp b/src/ext/Iis/ca/scassl.cpp new file mode 100644 index 00000000..4a06b77e --- /dev/null +++ b/src/ext/Iis/ca/scassl.cpp | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | enum eSslCertificateQuery { scqStoreName = 1, scqHash, scqWeb }; | ||
| 6 | |||
| 7 | static HRESULT AddSslCertificateToList( | ||
| 8 | __in SCA_WEB_SSL_CERTIFICATE** ppswscList | ||
| 9 | ); | ||
| 10 | |||
| 11 | |||
| 12 | HRESULT ScaSslCertificateRead( | ||
| 13 | __in LPCWSTR wzWebId, | ||
| 14 | __in WCA_WRAPQUERY_HANDLE hSslCertQuery, | ||
| 15 | __inout SCA_WEB_SSL_CERTIFICATE** ppswscList | ||
| 16 | ) | ||
| 17 | { | ||
| 18 | HRESULT hr = S_OK; | ||
| 19 | |||
| 20 | MSIHANDLE hRec; | ||
| 21 | SCA_WEB_SSL_CERTIFICATE* pswsc = NULL; | ||
| 22 | LPWSTR pwzData = NULL; | ||
| 23 | |||
| 24 | WcaFetchWrappedReset(hSslCertQuery); | ||
| 25 | |||
| 26 | // Get the certificate information. | ||
| 27 | while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hSslCertQuery, scqWeb, wzWebId, &hRec))) | ||
| 28 | { | ||
| 29 | hr = AddSslCertificateToList(ppswscList); | ||
| 30 | ExitOnFailure(hr, "failed to add ssl certificate to list"); | ||
| 31 | |||
| 32 | pswsc = *ppswscList; | ||
| 33 | |||
| 34 | hr = WcaGetRecordString(hRec, scqStoreName, &pwzData); | ||
| 35 | ExitOnFailure(hr, "Failed to get web ssl certificate store name."); | ||
| 36 | |||
| 37 | hr = ::StringCchCopyW(pswsc->wzStoreName, countof(pswsc->wzStoreName), pwzData); | ||
| 38 | ExitOnFailure(hr, "Failed to copy web ssl certificate store name."); | ||
| 39 | |||
| 40 | hr = WcaGetRecordString(hRec, scqHash, &pwzData); | ||
| 41 | ExitOnFailure(hr, "Failed to get hash for web ssl certificate."); | ||
| 42 | |||
| 43 | hr = StrHexDecode(pwzData, pswsc->rgbSHA1Hash, countof(pswsc->rgbSHA1Hash)); | ||
| 44 | ExitOnFailure(hr, "Failed to decode certificate hash for web: %ls, data: %ls", wzWebId, pwzData); | ||
| 45 | } | ||
| 46 | |||
| 47 | if (E_NOMOREITEMS == hr) | ||
| 48 | { | ||
| 49 | hr = S_OK; | ||
| 50 | } | ||
| 51 | ExitOnFailure(hr, "Failed to read IIsWebSiteCertificates table."); | ||
| 52 | |||
| 53 | LExit: | ||
| 54 | ReleaseStr(pwzData); | ||
| 55 | return hr; | ||
| 56 | } | ||
| 57 | |||
| 58 | |||
| 59 | HRESULT ScaSslCertificateWriteMetabase( | ||
| 60 | __in IMSAdminBase* piMetabase, | ||
| 61 | __in LPCWSTR wzWebBase, | ||
| 62 | __in SCA_WEB_SSL_CERTIFICATE* pswscList | ||
| 63 | ) | ||
| 64 | { | ||
| 65 | HRESULT hr = S_OK; | ||
| 66 | BLOB blob; | ||
| 67 | |||
| 68 | for (SCA_WEB_SSL_CERTIFICATE* pswsc = pswscList; pswsc; pswsc = pswsc->pNext) | ||
| 69 | { | ||
| 70 | // Write: /W3SVC/1:SslCertStoreName = "MY", "CA", "Root", etc. | ||
| 71 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_SSL_CERT_STORE_NAME, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, static_cast<LPVOID>(pswsc->wzStoreName)); | ||
| 72 | ExitOnFailure(hr, "Failed to write SslCertStoreName"); | ||
| 73 | |||
| 74 | // Write: /W3SVC/1:SslCertHash = <blob> | ||
| 75 | blob.pBlobData = pswsc->rgbSHA1Hash; | ||
| 76 | blob.cbSize = countof(pswsc->rgbSHA1Hash); | ||
| 77 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_SSL_CERT_HASH, METADATA_INHERIT, IIS_MD_UT_SERVER, BINARY_METADATA, static_cast<LPVOID>(&blob)); | ||
| 78 | ExitOnFailure(hr, "Failed to write SslCertHash"); | ||
| 79 | } | ||
| 80 | |||
| 81 | LExit: | ||
| 82 | return hr; | ||
| 83 | } | ||
| 84 | |||
| 85 | |||
| 86 | void ScaSslCertificateFreeList( | ||
| 87 | __in SCA_WEB_SSL_CERTIFICATE* pswscList | ||
| 88 | ) | ||
| 89 | { | ||
| 90 | SCA_WEB_SSL_CERTIFICATE* pswscDelete = pswscList; | ||
| 91 | while (pswscList) | ||
| 92 | { | ||
| 93 | pswscDelete = pswscList; | ||
| 94 | pswscList = pswscList->pNext; | ||
| 95 | |||
| 96 | MemFree(pswscDelete); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | |||
| 101 | static HRESULT AddSslCertificateToList( | ||
| 102 | __in SCA_WEB_SSL_CERTIFICATE** ppswscList | ||
| 103 | ) | ||
| 104 | { | ||
| 105 | HRESULT hr = S_OK; | ||
| 106 | |||
| 107 | SCA_WEB_SSL_CERTIFICATE* pswsc = static_cast<SCA_WEB_SSL_CERTIFICATE*>(MemAlloc(sizeof(SCA_WEB_SSL_CERTIFICATE), TRUE)); | ||
| 108 | ExitOnNull(pswsc, hr, E_OUTOFMEMORY, "failed to allocate memory for new SSL certificate list element"); | ||
| 109 | |||
| 110 | pswsc->pNext = *ppswscList; | ||
| 111 | *ppswscList = pswsc; | ||
| 112 | |||
| 113 | LExit: | ||
| 114 | return hr; | ||
| 115 | } | ||
diff --git a/src/ext/Iis/ca/scassl.h b/src/ext/Iis/ca/scassl.h new file mode 100644 index 00000000..df7c473d --- /dev/null +++ b/src/ext/Iis/ca/scassl.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #define MD_SSL_CERT_HASH ( IIS_MD_SSL_BASE+6 ) | ||
| 6 | #define MD_SSL_CERT_STORE_NAME ( IIS_MD_SSL_BASE+11 ) | ||
| 7 | //#define WIDE(x) WIDE2(x) | ||
| 8 | //#define WIDE2(x) L ## x | ||
| 9 | |||
| 10 | |||
| 11 | // structs | ||
| 12 | struct SCA_WEB_SSL_CERTIFICATE | ||
| 13 | { | ||
| 14 | WCHAR wzStoreName[65]; | ||
| 15 | BYTE rgbSHA1Hash[CB_CERTIFICATE_HASH]; | ||
| 16 | |||
| 17 | SCA_WEB_SSL_CERTIFICATE* pNext; | ||
| 18 | }; | ||
| 19 | |||
| 20 | |||
| 21 | // prototypes | ||
| 22 | HRESULT ScaSslCertificateRead( | ||
| 23 | __in LPCWSTR wzWebId, | ||
| 24 | __in WCA_WRAPQUERY_HANDLE hSslCertQuery, | ||
| 25 | __inout SCA_WEB_SSL_CERTIFICATE** ppswscList | ||
| 26 | ); | ||
| 27 | |||
| 28 | HRESULT ScaSslCertificateWriteMetabase( | ||
| 29 | __in IMSAdminBase* piMetabase, | ||
| 30 | __in LPCWSTR wzWebBase, | ||
| 31 | __in SCA_WEB_SSL_CERTIFICATE* pswscList | ||
| 32 | ); | ||
| 33 | |||
| 34 | void ScaSslCertificateFreeList( | ||
| 35 | __in SCA_WEB_SSL_CERTIFICATE* pswscList | ||
| 36 | ); | ||
diff --git a/src/ext/Iis/ca/scassl7.cpp b/src/ext/Iis/ca/scassl7.cpp new file mode 100644 index 00000000..47c16a9d --- /dev/null +++ b/src/ext/Iis/ca/scassl7.cpp | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | HRESULT ScaSslCertificateWrite7( | ||
| 6 | __in_z LPCWSTR wzWebBase, | ||
| 7 | __in SCA_WEB_SSL_CERTIFICATE* pswscList | ||
| 8 | ) | ||
| 9 | { | ||
| 10 | HRESULT hr = S_OK; | ||
| 11 | WCHAR wzEncodedCertificateHash[CB_CERTIFICATE_HASH * 2 + 1] = { 0 }; | ||
| 12 | |||
| 13 | for (SCA_WEB_SSL_CERTIFICATE* pswsc = pswscList; pswsc; pswsc = pswsc->pNext) | ||
| 14 | { | ||
| 15 | hr = ScaWriteConfigID(IIS_SSL_BINDING); | ||
| 16 | ExitOnFailure(hr, "Failed write SSL binding ID"); | ||
| 17 | hr = ScaWriteConfigID(IIS_CREATE); // Need to determine site action | ||
| 18 | ExitOnFailure(hr, "Failed write binding action"); | ||
| 19 | |||
| 20 | hr = ScaWriteConfigString(wzWebBase); //site name key | ||
| 21 | ExitOnFailure(hr, "Failed to write SSL website"); | ||
| 22 | hr = ScaWriteConfigString(pswsc->wzStoreName); //ssl store name | ||
| 23 | ExitOnFailure(hr, "Failed to write SSL store name"); | ||
| 24 | |||
| 25 | hr = StrHexEncode(pswsc->rgbSHA1Hash, countof(pswsc->rgbSHA1Hash), wzEncodedCertificateHash, countof(wzEncodedCertificateHash)); | ||
| 26 | ExitOnFailure(hr, "Failed to encode SSL hash"); | ||
| 27 | |||
| 28 | hr = ScaWriteConfigString(wzEncodedCertificateHash); //ssl hash | ||
| 29 | ExitOnFailure(hr, "Failed to write SSL hash"); | ||
| 30 | } | ||
| 31 | LExit: | ||
| 32 | |||
| 33 | return hr; | ||
| 34 | } | ||
diff --git a/src/ext/Iis/ca/scassl7.h b/src/ext/Iis/ca/scassl7.h new file mode 100644 index 00000000..1a4b09af --- /dev/null +++ b/src/ext/Iis/ca/scassl7.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaSslCertificateWrite7( | ||
| 6 | __in_z LPCWSTR wzWebBase, | ||
| 7 | __in SCA_WEB_SSL_CERTIFICATE* pswscList | ||
| 8 | ); | ||
diff --git a/src/ext/Iis/ca/scauser.cpp b/src/ext/Iis/ca/scauser.cpp new file mode 100644 index 00000000..0b99edff --- /dev/null +++ b/src/ext/Iis/ca/scauser.cpp | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | LPCWSTR vcsUserQuery = L"SELECT `User`, `Component_`, `Name`, `Domain`, `Password` FROM `User` WHERE `User`=?"; | ||
| 6 | enum eUserQuery { vuqUser = 1, vuqComponent, vuqName, vuqDomain, vuqPassword }; | ||
| 7 | |||
| 8 | LPCWSTR vcsGroupQuery = L"SELECT `Group`, `Component_`, `Name`, `Domain` FROM `Group` WHERE `Group`=?"; | ||
| 9 | enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain }; | ||
| 10 | |||
| 11 | LPCWSTR vcsUserGroupQuery = L"SELECT `User_`, `Group_` FROM `UserGroup` WHERE `User_`=?"; | ||
| 12 | enum eUserGroupQuery { vugqUser = 1, vugqGroup }; | ||
| 13 | |||
| 14 | LPCWSTR vActionableQuery = L"SELECT `User`,`Component_`,`Name`,`Domain`,`Password`,`Attributes` FROM `User` WHERE `Component_` IS NOT NULL"; | ||
| 15 | enum eActionableQuery { vaqUser = 1, vaqComponent, vaqName, vaqDomain, vaqPassword, vaqAttributes }; | ||
| 16 | |||
| 17 | HRESULT __stdcall ScaGetUserDeferred( | ||
| 18 | __in LPCWSTR wzUser, | ||
| 19 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 20 | __out SCA_USER* pscau | ||
| 21 | ) | ||
| 22 | { | ||
| 23 | if (!wzUser || !pscau) | ||
| 24 | { | ||
| 25 | return E_INVALIDARG; | ||
| 26 | } | ||
| 27 | |||
| 28 | HRESULT hr = S_OK; | ||
| 29 | MSIHANDLE hRec, hRecTest; | ||
| 30 | |||
| 31 | LPWSTR pwzData = NULL; | ||
| 32 | |||
| 33 | // clear struct and bail right away if no user key was passed to search for | ||
| 34 | ::ZeroMemory(pscau, sizeof(*pscau)); | ||
| 35 | if (!*wzUser) | ||
| 36 | { | ||
| 37 | ExitFunction1(hr = S_OK); | ||
| 38 | } | ||
| 39 | |||
| 40 | // Reset back to the first record | ||
| 41 | WcaFetchWrappedReset(hUserQuery); | ||
| 42 | |||
| 43 | hr = WcaFetchWrappedRecordWhereString(hUserQuery, vuqUser, wzUser, &hRec); | ||
| 44 | if (S_OK == hr) | ||
| 45 | { | ||
| 46 | hr = WcaFetchWrappedRecordWhereString(hUserQuery, vuqUser, wzUser, &hRecTest); | ||
| 47 | if (S_OK == hr) | ||
| 48 | { | ||
| 49 | AssertSz(FALSE, "Found multiple matching User rows"); | ||
| 50 | } | ||
| 51 | |||
| 52 | hr = WcaGetRecordString(hRec, vuqUser, &pwzData); | ||
| 53 | ExitOnFailure(hr, "Failed to get User.User"); | ||
| 54 | hr = ::StringCchCopyW(pscau->wzKey, countof(pscau->wzKey), pwzData); | ||
| 55 | ExitOnFailure(hr, "Failed to copy key string to user object (in deferred CA)"); | ||
| 56 | |||
| 57 | hr = WcaGetRecordString(hRec, vuqComponent, &pwzData); | ||
| 58 | ExitOnFailure(hr, "Failed to get User.Component_"); | ||
| 59 | hr = ::StringCchCopyW(pscau->wzComponent, countof(pscau->wzComponent), pwzData); | ||
| 60 | ExitOnFailure(hr, "Failed to copy component string to user object (in deferred CA)"); | ||
| 61 | |||
| 62 | hr = WcaGetRecordString(hRec, vuqName, &pwzData); | ||
| 63 | ExitOnFailure(hr, "Failed to get User.Name"); | ||
| 64 | hr = ::StringCchCopyW(pscau->wzName, countof(pscau->wzName), pwzData); | ||
| 65 | ExitOnFailure(hr, "Failed to copy name string to user object (in deferred CA)"); | ||
| 66 | |||
| 67 | hr = WcaGetRecordString(hRec, vuqDomain, &pwzData); | ||
| 68 | ExitOnFailure(hr, "Failed to get User.Domain"); | ||
| 69 | hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData); | ||
| 70 | ExitOnFailure(hr, "Failed to copy domain string to user object (in deferred CA)"); | ||
| 71 | |||
| 72 | hr = WcaGetRecordString(hRec, vuqPassword, &pwzData); | ||
| 73 | ExitOnFailure(hr, "Failed to get User.Password"); | ||
| 74 | hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData); | ||
| 75 | ExitOnFailure(hr, "Failed to copy password string to user object (in deferred CA)"); | ||
| 76 | } | ||
| 77 | else if (E_NOMOREITEMS == hr) | ||
| 78 | { | ||
| 79 | WcaLog(LOGMSG_STANDARD, "Error: Cannot locate User.User='%ls'", wzUser); | ||
| 80 | hr = E_FAIL; | ||
| 81 | } | ||
| 82 | else | ||
| 83 | { | ||
| 84 | ExitOnFailure(hr, "Error fetching single User row"); | ||
| 85 | } | ||
| 86 | |||
| 87 | LExit: | ||
| 88 | ReleaseStr(pwzData); | ||
| 89 | |||
| 90 | return hr; | ||
| 91 | } | ||
diff --git a/src/ext/Iis/ca/scauser.h b/src/ext/Iis/ca/scauser.h new file mode 100644 index 00000000..b2b94650 --- /dev/null +++ b/src/ext/Iis/ca/scauser.h | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | // structs | ||
| 5 | struct SCA_GROUP | ||
| 6 | { | ||
| 7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 8 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 9 | |||
| 10 | WCHAR wzDomain[MAX_DARWIN_COLUMN + 1]; | ||
| 11 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 12 | |||
| 13 | SCA_GROUP *psgNext; | ||
| 14 | }; | ||
| 15 | |||
| 16 | struct SCA_USER | ||
| 17 | { | ||
| 18 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 19 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 20 | INSTALLSTATE isInstalled; | ||
| 21 | INSTALLSTATE isAction; | ||
| 22 | |||
| 23 | WCHAR wzDomain[MAX_DARWIN_COLUMN + 1]; | ||
| 24 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 25 | WCHAR wzPassword[MAX_DARWIN_COLUMN + 1]; | ||
| 26 | INT iAttributes; | ||
| 27 | |||
| 28 | SCA_GROUP *psgGroups; | ||
| 29 | |||
| 30 | SCA_USER *psuNext; | ||
| 31 | }; | ||
| 32 | |||
| 33 | |||
| 34 | // prototypes | ||
| 35 | HRESULT __stdcall ScaGetUserDeferred( | ||
| 36 | __in LPCWSTR wzUser, | ||
| 37 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 38 | __out SCA_USER* pscau | ||
| 39 | ); | ||
diff --git a/src/ext/Iis/ca/scavdir.cpp b/src/ext/Iis/ca/scavdir.cpp new file mode 100644 index 00000000..d388ce97 --- /dev/null +++ b/src/ext/Iis/ca/scavdir.cpp | |||
| @@ -0,0 +1,331 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // prototypes | ||
| 6 | static HRESULT AddVirtualDirToList( | ||
| 7 | __in SCA_VDIR** psvdList | ||
| 8 | ); | ||
| 9 | |||
| 10 | |||
| 11 | HRESULT __stdcall ScaVirtualDirsRead( | ||
| 12 | __in IMSAdminBase* piMetabase, | ||
| 13 | __in SCA_WEB* pswList, | ||
| 14 | __in SCA_VDIR** ppsvdList, | ||
| 15 | __in SCA_MIMEMAP** ppsmmList, | ||
| 16 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 17 | __in SCA_WEB_ERROR** ppsweList, | ||
| 18 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 19 | __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, | ||
| 20 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 21 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 22 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 23 | __inout LPWSTR *ppwzCustomActionData | ||
| 24 | ) | ||
| 25 | { | ||
| 26 | Assert(piMetabase && ppsvdList); | ||
| 27 | |||
| 28 | HRESULT hr = S_OK; | ||
| 29 | MSIHANDLE hRec; | ||
| 30 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
| 31 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
| 32 | |||
| 33 | SCA_VDIR* pvdir = NULL; | ||
| 34 | LPWSTR pwzData = NULL; | ||
| 35 | |||
| 36 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 37 | |||
| 38 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 39 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 40 | |||
| 41 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 42 | { | ||
| 43 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaVirtualDirsRead() because IIsWebVirtualDir table not present"); | ||
| 44 | ExitFunction1(hr = S_FALSE); | ||
| 45 | } | ||
| 46 | |||
| 47 | // loop through all the vdirs | ||
| 48 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 49 | { | ||
| 50 | // Get the Component first. If there is a Component and it is not being modified during | ||
| 51 | // this transaction, skip processing this whole record. | ||
| 52 | hr = WcaGetRecordString(hRec, vdqComponent, &pwzData); | ||
| 53 | ExitOnFailure(hr, "failed to get IIsWebVirtualDir.Component"); | ||
| 54 | |||
| 55 | hr = WcaGetRecordInteger(hRec, vdqInstalled, (int *)&isInstalled); | ||
| 56 | ExitOnFailure(hr, "Failed to get Component installed state for virtual dir"); | ||
| 57 | |||
| 58 | hr = WcaGetRecordInteger(hRec, vdqAction, (int *)&isAction); | ||
| 59 | ExitOnFailure(hr, "Failed to get Component action state for virtual dir"); | ||
| 60 | |||
| 61 | if (!WcaIsInstalling(isInstalled, isAction) && | ||
| 62 | !WcaIsReInstalling(isInstalled, isAction) && | ||
| 63 | !WcaIsUninstalling(isInstalled, isAction)) | ||
| 64 | { | ||
| 65 | continue; // skip this record. | ||
| 66 | } | ||
| 67 | |||
| 68 | hr = AddVirtualDirToList(ppsvdList); | ||
| 69 | ExitOnFailure(hr, "failed to add virtual dir to list"); | ||
| 70 | |||
| 71 | pvdir = *ppsvdList; | ||
| 72 | |||
| 73 | hr = ::StringCchCopyW(pvdir->wzComponent, countof(pvdir->wzComponent), pwzData); | ||
| 74 | ExitOnFailure(hr, "failed to copy component name: %ls", pwzData); | ||
| 75 | |||
| 76 | pvdir->isInstalled = isInstalled; | ||
| 77 | pvdir->isAction = isAction; | ||
| 78 | |||
| 79 | // get the web key | ||
| 80 | hr = WcaGetRecordString(hRec, vdqWeb, &pwzData); | ||
| 81 | ExitOnFailure(hr, "Failed to get Web for VirtualDir"); | ||
| 82 | |||
| 83 | hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pvdir->wzWebBase, countof(pvdir->wzWebBase), hWebBaseQuery); | ||
| 84 | if (WcaIsUninstalling(isInstalled, isAction)) | ||
| 85 | { | ||
| 86 | // If we're uninstalling, ignore any failure to find the existing web | ||
| 87 | hr = S_OK; | ||
| 88 | } | ||
| 89 | ExitOnFailure(hr, "Failed to get base of web: %ls for VirtualDir", pwzData); | ||
| 90 | |||
| 91 | hr = WcaGetRecordString(hRec, vdqAlias, &pwzData); | ||
| 92 | ExitOnFailure(hr, "Failed to get Alias for VirtualDir"); | ||
| 93 | |||
| 94 | if (0 != lstrlenW(pvdir->wzWebBase)) | ||
| 95 | { | ||
| 96 | hr = ::StringCchPrintfW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), L"%s/Root/%s", pvdir->wzWebBase, pwzData); | ||
| 97 | ExitOnFailure(hr, "Failed to set VDirRoot for VirtualDir"); | ||
| 98 | } | ||
| 99 | |||
| 100 | // get the vdir's directory | ||
| 101 | hr = WcaGetRecordString(hRec, vdqDirectory, &pwzData); | ||
| 102 | ExitOnFailure(hr, "Failed to get Directory for VirtualDir"); | ||
| 103 | |||
| 104 | // get the web's directory | ||
| 105 | if (INSTALLSTATE_SOURCE == pvdir->isAction) | ||
| 106 | { | ||
| 107 | hr = WcaGetRecordString(hRec, vdqSourcePath, &pwzData); | ||
| 108 | } | ||
| 109 | else | ||
| 110 | { | ||
| 111 | hr = WcaGetRecordString(hRec, vdqTargetPath, &pwzData); | ||
| 112 | } | ||
| 113 | ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); | ||
| 114 | |||
| 115 | // remove trailing backslash(es) | ||
| 116 | while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\') | ||
| 117 | { | ||
| 118 | pwzData[lstrlenW(pwzData)-1] = 0; | ||
| 119 | } | ||
| 120 | hr = ::StringCchCopyW(pvdir->wzDirectory, countof(pvdir->wzDirectory), pwzData); | ||
| 121 | ExitOnFailure(hr, "Failed to copy directory string to vdir object"); | ||
| 122 | |||
| 123 | // get the security information for this web | ||
| 124 | hr = WcaGetRecordString(hRec, vdqProperties, &pwzData); | ||
| 125 | ExitOnFailure(hr, "Failed to get web directory identifier for VirtualDir"); | ||
| 126 | if (*pwzData) | ||
| 127 | { | ||
| 128 | hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pvdir->swp); | ||
| 129 | ExitOnFailure(hr, "Failed to get web directory for VirtualDir"); | ||
| 130 | |||
| 131 | pvdir->fHasProperties = TRUE; | ||
| 132 | } | ||
| 133 | |||
| 134 | // get the application information for this web | ||
| 135 | hr = WcaGetRecordString(hRec, vdqApplication, &pwzData); | ||
| 136 | ExitOnFailure(hr, "Failed to get application identifier for VirtualDir"); | ||
| 137 | if (*pwzData) | ||
| 138 | { | ||
| 139 | hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pvdir->swapp); | ||
| 140 | ExitOnFailure(hr, "Failed to get application for VirtualDir"); | ||
| 141 | |||
| 142 | pvdir->fHasApplication = TRUE; | ||
| 143 | } | ||
| 144 | |||
| 145 | hr = WcaGetRecordString(hRec, vdqVDir, &pwzData); | ||
| 146 | ExitOnFailure(hr, "Failed to get VDir for VirtualDir"); | ||
| 147 | |||
| 148 | if (*pwzData && *ppsmmList) | ||
| 149 | { | ||
| 150 | hr = ScaGetMimeMap(mmptVDir, pwzData, ppsmmList, &pvdir->psmm); | ||
| 151 | ExitOnFailure(hr, "Failed to get mimemap for VirtualDir"); | ||
| 152 | } | ||
| 153 | |||
| 154 | if (*pwzData && *ppshhList) | ||
| 155 | { | ||
| 156 | hr = ScaGetHttpHeader(hhptVDir, pwzData, ppshhList, &pvdir->pshh); | ||
| 157 | ExitOnFailure(hr, "Failed to get custom HTTP headers for VirtualDir: %ls", pwzData); | ||
| 158 | } | ||
| 159 | |||
| 160 | if (*pwzData && *ppsweList) | ||
| 161 | { | ||
| 162 | hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe); | ||
| 163 | ExitOnFailure(hr, "Failed to get custom web errors for VirtualDir: %ls", pwzData); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | if (E_NOMOREITEMS == hr) | ||
| 168 | { | ||
| 169 | hr = S_OK; | ||
| 170 | } | ||
| 171 | ExitOnFailure(hr, "Failure while processing VirtualDirs"); | ||
| 172 | |||
| 173 | LExit: | ||
| 174 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 175 | |||
| 176 | ReleaseStr(pwzData); | ||
| 177 | return hr; | ||
| 178 | } | ||
| 179 | |||
| 180 | |||
| 181 | HRESULT ScaVirtualDirsInstall( | ||
| 182 | __in IMSAdminBase* piMetabase, | ||
| 183 | __in SCA_VDIR* psvdList, | ||
| 184 | __in SCA_APPPOOL * psapList | ||
| 185 | ) | ||
| 186 | { | ||
| 187 | Assert(piMetabase); | ||
| 188 | |||
| 189 | HRESULT hr = S_OK; | ||
| 190 | SCA_VDIR* psvd = psvdList; | ||
| 191 | int i; | ||
| 192 | |||
| 193 | while (psvd) | ||
| 194 | { | ||
| 195 | // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created | ||
| 196 | if (WcaIsReInstalling(psvd->isInstalled, psvd->isAction)) | ||
| 197 | { | ||
| 198 | if (psvd->fHasApplication) | ||
| 199 | { | ||
| 200 | hr = ScaDeleteApp(piMetabase, psvd->wzVDirRoot); | ||
| 201 | ExitOnFailure(hr, "Failed to remove application for WebVDir as part of a reinstall"); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | if (WcaIsInstalling(psvd->isInstalled, psvd->isAction)) | ||
| 206 | { | ||
| 207 | hr = ScaCreateMetabaseKey(piMetabase, psvd->wzVDirRoot, L""); | ||
| 208 | ExitOnFailure(hr, "Failed to create key for VirtualDir"); | ||
| 209 | hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebVirtualDir"); | ||
| 210 | ExitOnFailure(hr, "Failed to write key type for for VirtualDir"); | ||
| 211 | i = 0x4000003e; // 1073741886; // default directory browsing rights | ||
| 212 | hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)i)); | ||
| 213 | ExitOnFailure(hr, "Failed to set directory browsing for VirtualDir"); | ||
| 214 | |||
| 215 | hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)psvd->wzDirectory); | ||
| 216 | ExitOnFailure(hr, "Failed to write Directory for VirtualDir"); | ||
| 217 | |||
| 218 | if (psvd->fHasProperties) | ||
| 219 | { | ||
| 220 | ScaWriteWebDirProperties(piMetabase, psvd->wzVDirRoot, &psvd->swp); | ||
| 221 | ExitOnFailure(hr, "Failed to write directory properties for VirtualDir"); | ||
| 222 | } | ||
| 223 | |||
| 224 | if (psvd->fHasApplication) | ||
| 225 | { | ||
| 226 | hr = ScaWriteWebApplication(piMetabase, psvd->wzVDirRoot, &psvd->swapp, psapList); | ||
| 227 | ExitOnFailure(hr, "Failed to write application for VirtualDir"); | ||
| 228 | } | ||
| 229 | |||
| 230 | if (psvd->psmm) | ||
| 231 | { | ||
| 232 | hr = ScaWriteMimeMap(piMetabase, psvd->wzVDirRoot, psvd->psmm); | ||
| 233 | ExitOnFailure(hr, "Failed to write mimemap for VirtualDir"); | ||
| 234 | } | ||
| 235 | |||
| 236 | if (psvd->pshh) | ||
| 237 | { | ||
| 238 | hr = ScaWriteHttpHeader(piMetabase, psvd->wzVDirRoot, psvd->pshh); | ||
| 239 | ExitOnFailure(hr, "Failed to write custom HTTP headers for VirtualDir"); | ||
| 240 | } | ||
| 241 | |||
| 242 | if (psvd->pswe) | ||
| 243 | { | ||
| 244 | hr = ScaWriteWebError(piMetabase, weptVDir, psvd->wzVDirRoot, psvd->pswe); | ||
| 245 | ExitOnFailure(hr, "Failed to write custom web errors for VirtualDir"); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | psvd = psvd->psvdNext; | ||
| 250 | } | ||
| 251 | |||
| 252 | LExit: | ||
| 253 | return hr; | ||
| 254 | } | ||
| 255 | |||
| 256 | |||
| 257 | HRESULT ScaVirtualDirsUninstall( | ||
| 258 | __in IMSAdminBase* piMetabase, | ||
| 259 | __in SCA_VDIR* psvdList | ||
| 260 | ) | ||
| 261 | { | ||
| 262 | Assert(piMetabase); | ||
| 263 | |||
| 264 | HRESULT hr = S_OK; | ||
| 265 | SCA_VDIR* psvd = psvdList; | ||
| 266 | |||
| 267 | while (psvd) | ||
| 268 | { | ||
| 269 | if (WcaIsUninstalling(psvd->isInstalled, psvd->isAction)) | ||
| 270 | { | ||
| 271 | // delete the application for this virtual directory | ||
| 272 | if (psvd->fHasApplication) | ||
| 273 | { | ||
| 274 | hr = ScaDeleteApp(piMetabase, psvd->wzVDirRoot); | ||
| 275 | ExitOnFailure(hr, "Failed to remove application for WebVDir"); | ||
| 276 | } | ||
| 277 | |||
| 278 | if (0 != lstrlenW(psvd->wzVDirRoot)) | ||
| 279 | { | ||
| 280 | hr = ScaDeleteMetabaseKey(piMetabase, psvd->wzVDirRoot, L""); | ||
| 281 | ExitOnFailure(hr, "Failed to remove VirtualDir '%ls' from metabase", psvd->wzKey); | ||
| 282 | } | ||
| 283 | } | ||
| 284 | |||
| 285 | psvd = psvd->psvdNext; | ||
| 286 | } | ||
| 287 | |||
| 288 | LExit: | ||
| 289 | return hr; | ||
| 290 | } | ||
| 291 | |||
| 292 | |||
| 293 | void ScaVirtualDirsFreeList( | ||
| 294 | __in SCA_VDIR* psvdList | ||
| 295 | ) | ||
| 296 | { | ||
| 297 | SCA_VDIR* psvdDelete = psvdList; | ||
| 298 | while (psvdList) | ||
| 299 | { | ||
| 300 | psvdDelete = psvdList; | ||
| 301 | psvdList = psvdList->psvdNext; | ||
| 302 | |||
| 303 | if (psvdDelete->psmm) | ||
| 304 | { | ||
| 305 | ScaMimeMapFreeList(psvdDelete->psmm); | ||
| 306 | } | ||
| 307 | |||
| 308 | if (psvdDelete->pswe) | ||
| 309 | { | ||
| 310 | ScaWebErrorFreeList(psvdDelete->pswe); | ||
| 311 | } | ||
| 312 | |||
| 313 | MemFree(psvdDelete); | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 317 | |||
| 318 | static HRESULT AddVirtualDirToList( | ||
| 319 | __in SCA_VDIR** ppsvdList | ||
| 320 | ) | ||
| 321 | { | ||
| 322 | HRESULT hr = S_OK; | ||
| 323 | SCA_VDIR* psvd = static_cast<SCA_VDIR*>(MemAlloc(sizeof(SCA_VDIR), TRUE)); | ||
| 324 | ExitOnNull(psvd, hr, E_OUTOFMEMORY, "failed to allocate memory for new vdir list element"); | ||
| 325 | |||
| 326 | psvd->psvdNext= *ppsvdList; | ||
| 327 | *ppsvdList = psvd; | ||
| 328 | |||
| 329 | LExit: | ||
| 330 | return hr; | ||
| 331 | } | ||
diff --git a/src/ext/Iis/ca/scavdir.h b/src/ext/Iis/ca/scavdir.h new file mode 100644 index 00000000..c7e9661b --- /dev/null +++ b/src/ext/Iis/ca/scavdir.h | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scawebprop.h" | ||
| 6 | #include "scawebapp.h" | ||
| 7 | #include "scamimemap.h" | ||
| 8 | #include "scaapppool.h" | ||
| 9 | |||
| 10 | enum eVDirQuery { vdqWeb = 1, vdqVDir, vdqComponent , vdqAlias, vdqDirectory, vdqProperties, vdqApplication, vdqInstalled, vdqAction, vdqSourcePath, vdqTargetPath }; | ||
| 11 | |||
| 12 | struct SCA_VDIR | ||
| 13 | { | ||
| 14 | // darwin information | ||
| 15 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 16 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 17 | INSTALLSTATE isInstalled; | ||
| 18 | INSTALLSTATE isAction; | ||
| 19 | |||
| 20 | // metabase information | ||
| 21 | WCHAR wzWebKey[MAX_DARWIN_KEY + 1]; | ||
| 22 | WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1]; | ||
| 23 | WCHAR wzVDirRoot[METADATA_MAX_NAME_LEN + 1]; | ||
| 24 | |||
| 25 | // iis configuation information | ||
| 26 | WCHAR wzDirectory[MAX_PATH]; | ||
| 27 | |||
| 28 | BOOL fHasProperties; | ||
| 29 | SCA_WEB_PROPERTIES swp; | ||
| 30 | |||
| 31 | BOOL fHasApplication; | ||
| 32 | SCA_WEB_APPLICATION swapp; | ||
| 33 | |||
| 34 | SCA_MIMEMAP* psmm; // mime mappings | ||
| 35 | SCA_HTTP_HEADER* pshh; // custom web errors | ||
| 36 | SCA_WEB_ERROR* pswe; // custom web errors | ||
| 37 | |||
| 38 | SCA_VDIR* psvdNext; | ||
| 39 | }; | ||
| 40 | |||
| 41 | |||
| 42 | // prototypes | ||
| 43 | HRESULT __stdcall ScaVirtualDirsRead( | ||
| 44 | __in IMSAdminBase* piMetabase, | ||
| 45 | __in SCA_WEB* pswList, | ||
| 46 | __in SCA_VDIR** ppsvdList, | ||
| 47 | __in SCA_MIMEMAP** ppsmmList, | ||
| 48 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 49 | __in SCA_WEB_ERROR** ppsweList, | ||
| 50 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 51 | __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, | ||
| 52 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 53 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 54 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 55 | __inout LPWSTR *ppwzCustomActionData | ||
| 56 | ); | ||
| 57 | |||
| 58 | HRESULT ScaVirtualDirsInstall( | ||
| 59 | __in IMSAdminBase* piMetabase, | ||
| 60 | __in SCA_VDIR* psvdList, | ||
| 61 | __in SCA_APPPOOL * psapList | ||
| 62 | ); | ||
| 63 | |||
| 64 | HRESULT ScaVirtualDirsUninstall( | ||
| 65 | __in IMSAdminBase* piMetabase, | ||
| 66 | __in SCA_VDIR* psvdList | ||
| 67 | ); | ||
| 68 | |||
| 69 | void ScaVirtualDirsFreeList( | ||
| 70 | __in SCA_VDIR* psvdList | ||
| 71 | ); | ||
diff --git a/src/ext/Iis/ca/scavdir7.cpp b/src/ext/Iis/ca/scavdir7.cpp new file mode 100644 index 00000000..3f675357 --- /dev/null +++ b/src/ext/Iis/ca/scavdir7.cpp | |||
| @@ -0,0 +1,380 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // prototypes | ||
| 6 | static HRESULT AddVirtualDirToList7( | ||
| 7 | __in SCA_VDIR7** psvdList | ||
| 8 | ); | ||
| 9 | |||
| 10 | |||
| 11 | HRESULT __stdcall ScaVirtualDirsRead7( | ||
| 12 | __in SCA_WEB7* pswList, | ||
| 13 | __in SCA_VDIR7** ppsvdList, | ||
| 14 | __in SCA_MIMEMAP** ppsmmList, | ||
| 15 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 16 | __in SCA_WEB_ERROR** ppsweList, | ||
| 17 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 18 | __in WCA_WRAPQUERY_HANDLE /*hWebBaseQuery*/, | ||
| 19 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 20 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 21 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 22 | __inout LPWSTR *ppwzCustomActionData | ||
| 23 | ) | ||
| 24 | { | ||
| 25 | Assert(ppsvdList); | ||
| 26 | |||
| 27 | HRESULT hr = S_OK; | ||
| 28 | MSIHANDLE hRec; | ||
| 29 | |||
| 30 | SCA_VDIR7* pvdir = NULL; | ||
| 31 | LPWSTR pwzData = NULL; | ||
| 32 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 33 | |||
| 34 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 35 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 36 | |||
| 37 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 38 | { | ||
| 39 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaVirtualDirsRead() because IIsWebVirtualDir table not present"); | ||
| 40 | ExitFunction1(hr = S_FALSE); | ||
| 41 | } | ||
| 42 | |||
| 43 | // loop through all the vdirs | ||
| 44 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 45 | { | ||
| 46 | // Add this record's information into the list of things to process. | ||
| 47 | hr = AddVirtualDirToList7(ppsvdList); | ||
| 48 | ExitOnFailure(hr, "failed to add vdir to vdir list"); | ||
| 49 | |||
| 50 | pvdir = *ppsvdList; | ||
| 51 | |||
| 52 | // get the darwin information | ||
| 53 | hr = WcaGetRecordString(hRec, vdqComponent, &pwzData); | ||
| 54 | ExitOnFailure(hr, "failed to get IIsWebVirtualDir.Component"); | ||
| 55 | |||
| 56 | hr = WcaGetRecordInteger(hRec, vdqInstalled, (int *)&pvdir->isInstalled); | ||
| 57 | ExitOnFailure(hr, "Failed to get Component installed state for virtual dir"); | ||
| 58 | |||
| 59 | hr = WcaGetRecordInteger(hRec, vdqAction, (int *)&pvdir->isAction); | ||
| 60 | ExitOnFailure(hr, "Failed to get Component action state for virtual dir"); | ||
| 61 | |||
| 62 | // get vdir properties | ||
| 63 | hr = ::StringCchCopyW(pvdir->wzComponent, countof(pvdir->wzComponent), pwzData); | ||
| 64 | ExitOnFailure(hr, "failed to copy vdir component name: %ls", pwzData); | ||
| 65 | |||
| 66 | hr = WcaGetRecordString(hRec, vdqWeb, &pwzData); | ||
| 67 | ExitOnFailure(hr, "Failed to get Web for VirtualDir"); | ||
| 68 | |||
| 69 | hr = ScaWebsGetBase7(pswList, pwzData, pvdir->wzWebName , countof(pvdir->wzWebName)); | ||
| 70 | if (S_FALSE == hr) | ||
| 71 | { | ||
| 72 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 73 | ExitOnFailure(hr, "Failed to get Web Base for VirtualDir"); | ||
| 74 | } | ||
| 75 | if (WcaIsUninstalling(pvdir->isInstalled, pvdir->isAction)) | ||
| 76 | { | ||
| 77 | // If we're uninstalling, ignore any failure to find the existing web | ||
| 78 | hr = S_OK; | ||
| 79 | } | ||
| 80 | |||
| 81 | hr = WcaGetRecordString(hRec, vdqAlias, &pwzData); | ||
| 82 | ExitOnFailure(hr, "Failed to get Alias for VirtualDir"); | ||
| 83 | |||
| 84 | hr = ::StringCchCopyW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), pwzData); | ||
| 85 | ExitOnFailure(hr, "Failed to set VDirRoot for VirtualDir"); | ||
| 86 | |||
| 87 | // get the vdir's directory | ||
| 88 | hr = WcaGetRecordString(hRec, vdqDirectory, &pwzData); | ||
| 89 | ExitOnFailure(hr, "Failed to get Directory for VirtualDir"); | ||
| 90 | |||
| 91 | // get the web's directory | ||
| 92 | if (INSTALLSTATE_SOURCE == pvdir->isAction) | ||
| 93 | { | ||
| 94 | hr = WcaGetRecordString(hRec, vdqSourcePath, &pwzData); | ||
| 95 | } | ||
| 96 | else | ||
| 97 | { | ||
| 98 | hr = WcaGetRecordString(hRec, vdqTargetPath, &pwzData); | ||
| 99 | } | ||
| 100 | ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); | ||
| 101 | |||
| 102 | // remove trailing backslash(es) | ||
| 103 | while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\') | ||
| 104 | { | ||
| 105 | pwzData[lstrlenW(pwzData)-1] = 0; | ||
| 106 | } | ||
| 107 | hr = ::StringCchCopyW(pvdir->wzDirectory, countof(pvdir->wzDirectory), pwzData); | ||
| 108 | ExitOnFailure(hr, "Failed to copy directory string to vdir object"); | ||
| 109 | |||
| 110 | // get the security information for this web | ||
| 111 | hr = WcaGetRecordString(hRec, vdqProperties, &pwzData); | ||
| 112 | ExitOnFailure(hr, "Failed to get web directory identifier for VirtualDir"); | ||
| 113 | if (*pwzData) | ||
| 114 | { | ||
| 115 | hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pvdir->swp); | ||
| 116 | ExitOnFailure(hr, "Failed to get web directory for VirtualDir"); | ||
| 117 | |||
| 118 | pvdir->fHasProperties = TRUE; | ||
| 119 | } | ||
| 120 | |||
| 121 | // get the application information for this web | ||
| 122 | hr = WcaGetRecordString(hRec, vdqApplication, &pwzData); | ||
| 123 | ExitOnFailure(hr, "Failed to get application identifier for VirtualDir"); | ||
| 124 | if (*pwzData) | ||
| 125 | { | ||
| 126 | hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pvdir->swapp); | ||
| 127 | ExitOnFailure(hr, "Failed to get application for VirtualDir"); | ||
| 128 | |||
| 129 | pvdir->fHasApplication = TRUE; | ||
| 130 | } | ||
| 131 | |||
| 132 | hr = WcaGetRecordString(hRec, vdqVDir, &pwzData); | ||
| 133 | ExitOnFailure(hr, "Failed to get VDir for VirtualDir"); | ||
| 134 | |||
| 135 | if (*pwzData && *ppsmmList) | ||
| 136 | { | ||
| 137 | hr = ScaGetMimeMap(mmptVDir, pwzData, ppsmmList, &pvdir->psmm); | ||
| 138 | ExitOnFailure(hr, "Failed to get mimemap for VirtualDir"); | ||
| 139 | } | ||
| 140 | |||
| 141 | if (*pwzData && *ppshhList) | ||
| 142 | { | ||
| 143 | hr = ScaGetHttpHeader(hhptVDir, pwzData, ppshhList, &pvdir->pshh); | ||
| 144 | ExitOnFailure(hr, "Failed to get custom HTTP headers for VirtualDir: %ls", pwzData); | ||
| 145 | } | ||
| 146 | |||
| 147 | if (*pwzData && *ppsweList) | ||
| 148 | { | ||
| 149 | hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe); | ||
| 150 | ExitOnFailure(hr, "Failed to get custom web errors for VirtualDir: %ls", pwzData); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | if (E_NOMOREITEMS == hr) | ||
| 155 | { | ||
| 156 | hr = S_OK; | ||
| 157 | } | ||
| 158 | ExitOnFailure(hr, "Failure while processing VirtualDirs"); | ||
| 159 | |||
| 160 | LExit: | ||
| 161 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 162 | |||
| 163 | ReleaseStr(pwzData); | ||
| 164 | |||
| 165 | return hr; | ||
| 166 | } | ||
| 167 | |||
| 168 | |||
| 169 | HRESULT ScaVirtualDirsInstall7( | ||
| 170 | __in SCA_VDIR7* psvdList, | ||
| 171 | __in SCA_APPPOOL * psapList | ||
| 172 | ) | ||
| 173 | { | ||
| 174 | HRESULT hr = S_OK; | ||
| 175 | SCA_VDIR7* psvd = psvdList; | ||
| 176 | LPWSTR wzPath = NULL; | ||
| 177 | WCHAR wzAppPoolName[MAX_PATH]; | ||
| 178 | while (psvd) | ||
| 179 | { | ||
| 180 | if (WcaIsInstalling(psvd->isInstalled, psvd->isAction)) | ||
| 181 | { | ||
| 182 | // First write all applications, this is necessary since vdirs must be nested under the applications. | ||
| 183 | if (psvd->fHasApplication) | ||
| 184 | { | ||
| 185 | //create the application for this vdir application | ||
| 186 | hr = ScaWriteConfigID(IIS_APPLICATION); | ||
| 187 | ExitOnFailure(hr, "Failed to write app ID"); | ||
| 188 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 189 | ExitOnFailure(hr, "Failed to write app action"); | ||
| 190 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 191 | hr = ScaWriteConfigString(psvd->wzWebName); //site name key | ||
| 192 | ExitOnFailure(hr, "Failed to write app web key"); | ||
| 193 | hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot); | ||
| 194 | ExitOnFailure(hr, "Failed to create app path"); | ||
| 195 | hr = ScaWriteConfigString(wzPath); // App Path | ||
| 196 | ExitOnFailure(hr, "Failed to write app path root "); | ||
| 197 | |||
| 198 | if (!*psvd->swapp.wzAppPool) | ||
| 199 | { | ||
| 200 | //This Application goes in default appPool | ||
| 201 | hr = ScaWriteConfigString(L""); // App Pool | ||
| 202 | } | ||
| 203 | else | ||
| 204 | { | ||
| 205 | //get apppool from WebApplication | ||
| 206 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 207 | hr = ScaFindAppPool7(psvd->swapp.wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList); | ||
| 208 | ExitOnFailure(hr, "Failed to read app pool from application"); | ||
| 209 | hr = ScaWriteConfigString(wzAppPoolName); // App Pool | ||
| 210 | ExitOnFailure(hr, "Failed to write appPool for vdir"); | ||
| 211 | |||
| 212 | } | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | psvd = psvd->psvdNext; | ||
| 217 | } | ||
| 218 | |||
| 219 | // Reset our linked list and write all the VDirs | ||
| 220 | psvd = psvdList; | ||
| 221 | while (psvd) | ||
| 222 | { | ||
| 223 | if (WcaIsInstalling(psvd->isInstalled, psvd->isAction)) | ||
| 224 | { | ||
| 225 | //create the Vdir | ||
| 226 | hr = ScaWriteConfigID(IIS_VDIR); | ||
| 227 | ExitOnFailure(hr, "Failed write VirDir ID") | ||
| 228 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 229 | ExitOnFailure(hr, "Failed write VirDir action") | ||
| 230 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 231 | hr = ScaWriteConfigString(psvd->wzWebName); //site name key | ||
| 232 | ExitOnFailure(hr, "Failed write VirDir web name"); | ||
| 233 | hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot); | ||
| 234 | ExitOnFailure(hr, "Failed to create vdir path"); | ||
| 235 | hr = ScaWriteConfigString(wzPath); //vdir path | ||
| 236 | ExitOnFailure(hr, "Failed write VirDir path") | ||
| 237 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 238 | hr = ScaWriteConfigString(psvd->wzDirectory); //physical dir | ||
| 239 | ExitOnFailure(hr, "Failed write VirDir dir"); | ||
| 240 | |||
| 241 | if (psvd->fHasProperties) | ||
| 242 | { | ||
| 243 | ScaWriteWebDirProperties7(psvd->wzWebName, psvd->wzVDirRoot, &psvd->swp); | ||
| 244 | ExitOnFailure(hr, "Failed to write directory properties for VirtualDir"); | ||
| 245 | } | ||
| 246 | |||
| 247 | if (psvd->fHasApplication) | ||
| 248 | { | ||
| 249 | hr = ScaWriteWebApplication7(psvd->wzWebName, psvd->wzVDirRoot, &psvd->swapp, psapList); | ||
| 250 | ExitOnFailure(hr, "Failed to write application for VirtualDir"); | ||
| 251 | } | ||
| 252 | |||
| 253 | if (psvd->psmm) | ||
| 254 | { | ||
| 255 | hr = ScaWriteMimeMap7(psvd->wzWebName, psvd->wzVDirRoot, psvd->psmm); | ||
| 256 | ExitOnFailure(hr, "Failed to write mimemap for VirtualDir"); | ||
| 257 | } | ||
| 258 | |||
| 259 | if (psvd->pshh) | ||
| 260 | { | ||
| 261 | hr = ScaWriteHttpHeader7(psvd->wzWebName, psvd->wzVDirRoot, psvd->pshh); | ||
| 262 | ExitOnFailure(hr, "Failed to write custom HTTP headers for VirtualDir"); | ||
| 263 | } | ||
| 264 | |||
| 265 | if (psvd->pswe) | ||
| 266 | { | ||
| 267 | hr = ScaWriteWebError7(psvd->wzWebName, psvd->wzVDirRoot, psvd->pswe); | ||
| 268 | ExitOnFailure(hr, "Failed to write custom web errors for VirtualDir"); | ||
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | psvd = psvd->psvdNext; | ||
| 273 | } | ||
| 274 | |||
| 275 | LExit: | ||
| 276 | ReleaseStr(wzPath); | ||
| 277 | return hr; | ||
| 278 | } | ||
| 279 | |||
| 280 | |||
| 281 | HRESULT ScaVirtualDirsUninstall7( | ||
| 282 | __in SCA_VDIR7* psvdList | ||
| 283 | ) | ||
| 284 | { | ||
| 285 | |||
| 286 | HRESULT hr = S_OK; | ||
| 287 | SCA_VDIR7* psvd = psvdList; | ||
| 288 | LPWSTR wzPath = NULL; | ||
| 289 | |||
| 290 | while (psvd) | ||
| 291 | { | ||
| 292 | if (WcaIsUninstalling(psvd->isInstalled, psvd->isAction)) | ||
| 293 | { | ||
| 294 | //init path | ||
| 295 | hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot); | ||
| 296 | ExitOnFailure(hr, "Failed to create vdir path"); | ||
| 297 | |||
| 298 | if (psvd->fHasApplication) | ||
| 299 | { | ||
| 300 | //delete Application | ||
| 301 | hr = ScaWriteConfigID(IIS_APPLICATION); | ||
| 302 | ExitOnFailure(hr, "Failed to write app ID "); | ||
| 303 | hr = ScaWriteConfigID(IIS_DELETE); | ||
| 304 | ExitOnFailure(hr, "Failed to write delete app ID "); | ||
| 305 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 306 | hr = ScaWriteConfigString(psvd->wzWebName); //site name key | ||
| 307 | ExitOnFailure(hr, "Failed to write App site Name"); | ||
| 308 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 309 | hr = ScaWriteConfigString(wzPath); // App Path | ||
| 310 | ExitOnFailure(hr, "Failed to write app path root "); | ||
| 311 | hr = ScaWriteConfigString(L"NOP"); // App pool | ||
| 312 | ExitOnFailure(hr, "Failed to write app path app pool "); | ||
| 313 | } | ||
| 314 | else | ||
| 315 | { | ||
| 316 | //delete VDir | ||
| 317 | hr = ScaWriteConfigID(IIS_VDIR); | ||
| 318 | ExitOnFailure(hr, "Failed to write vDir ID "); | ||
| 319 | hr = ScaWriteConfigID(IIS_DELETE); | ||
| 320 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 321 | hr = ScaWriteConfigString(psvd->wzWebName); //site name key | ||
| 322 | ExitOnFailure(hr, "Failed to write App site Name"); | ||
| 323 | hr = ScaWriteConfigString(wzPath); // Vdir Path | ||
| 324 | ExitOnFailure(hr, "Failed to write app vdir "); | ||
| 325 | hr = ScaWriteConfigString(L"NOP"); // Phy Path | ||
| 326 | ExitOnFailure(hr, "Failed to write vdir path"); | ||
| 327 | } | ||
| 328 | |||
| 329 | ExitOnFailure(hr, "Failed to remove VirtualDir '%ls' from config", psvd->wzKey); | ||
| 330 | } | ||
| 331 | |||
| 332 | psvd = psvd->psvdNext; | ||
| 333 | } | ||
| 334 | |||
| 335 | LExit: | ||
| 336 | ReleaseStr(wzPath); | ||
| 337 | return hr; | ||
| 338 | } | ||
| 339 | |||
| 340 | |||
| 341 | void ScaVirtualDirsFreeList7( | ||
| 342 | __in SCA_VDIR7* psvdList | ||
| 343 | ) | ||
| 344 | { | ||
| 345 | SCA_VDIR7* psvdDelete = psvdList; | ||
| 346 | while (psvdList) | ||
| 347 | { | ||
| 348 | psvdDelete = psvdList; | ||
| 349 | psvdList = psvdList->psvdNext; | ||
| 350 | |||
| 351 | if (psvdDelete->psmm) | ||
| 352 | { | ||
| 353 | ScaMimeMapFreeList(psvdDelete->psmm); | ||
| 354 | } | ||
| 355 | |||
| 356 | if (psvdDelete->pswe) | ||
| 357 | { | ||
| 358 | ScaWebErrorFreeList(psvdDelete->pswe); | ||
| 359 | } | ||
| 360 | |||
| 361 | MemFree(psvdDelete); | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | |||
| 366 | static HRESULT AddVirtualDirToList7( | ||
| 367 | __in SCA_VDIR7** ppsvdList | ||
| 368 | ) | ||
| 369 | { | ||
| 370 | HRESULT hr = S_OK; | ||
| 371 | |||
| 372 | SCA_VDIR7* psvd = static_cast<SCA_VDIR7*>(MemAlloc(sizeof(SCA_VDIR7), TRUE)); | ||
| 373 | ExitOnNull(psvd, hr, E_OUTOFMEMORY, "failed to allocate memory for new vdir list element"); | ||
| 374 | |||
| 375 | psvd->psvdNext= *ppsvdList; | ||
| 376 | *ppsvdList = psvd; | ||
| 377 | |||
| 378 | LExit: | ||
| 379 | return hr; | ||
| 380 | } | ||
diff --git a/src/ext/Iis/ca/scavdir7.h b/src/ext/Iis/ca/scavdir7.h new file mode 100644 index 00000000..dba25431 --- /dev/null +++ b/src/ext/Iis/ca/scavdir7.h | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scawebprop.h" | ||
| 6 | #include "scawebapp.h" | ||
| 7 | #include "scamimemap.h" | ||
| 8 | #include "scaapppool.h" | ||
| 9 | |||
| 10 | struct SCA_VDIR7 | ||
| 11 | { | ||
| 12 | // darwin information | ||
| 13 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 14 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 15 | INSTALLSTATE isInstalled; | ||
| 16 | INSTALLSTATE isAction; | ||
| 17 | |||
| 18 | // metabase information | ||
| 19 | WCHAR wzWebKey[MAX_DARWIN_KEY + 1]; | ||
| 20 | WCHAR wzWebName[METADATA_MAX_NAME_LEN + 1]; | ||
| 21 | WCHAR wzVDirRoot[METADATA_MAX_NAME_LEN + 1]; | ||
| 22 | |||
| 23 | // iis configuation information | ||
| 24 | WCHAR wzDirectory[MAX_PATH]; | ||
| 25 | |||
| 26 | BOOL fHasProperties; | ||
| 27 | SCA_WEB_PROPERTIES swp; | ||
| 28 | |||
| 29 | BOOL fHasApplication; | ||
| 30 | SCA_WEB_APPLICATION swapp; | ||
| 31 | |||
| 32 | SCA_MIMEMAP* psmm; // mime mappings | ||
| 33 | SCA_HTTP_HEADER* pshh; // custom web errors | ||
| 34 | SCA_WEB_ERROR* pswe; // custom web errors | ||
| 35 | |||
| 36 | SCA_VDIR7* psvdNext; | ||
| 37 | }; | ||
| 38 | |||
| 39 | |||
| 40 | // prototypes | ||
| 41 | HRESULT __stdcall ScaVirtualDirsRead7( | ||
| 42 | __in SCA_WEB7* pswList, | ||
| 43 | __in SCA_VDIR7** ppsvdList, | ||
| 44 | __in SCA_MIMEMAP** ppsmmList, | ||
| 45 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 46 | __in SCA_WEB_ERROR** ppsweList, | ||
| 47 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 48 | __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, | ||
| 49 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 50 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 51 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 52 | __inout LPWSTR *ppwzCustomActionData | ||
| 53 | ); | ||
| 54 | |||
| 55 | HRESULT ScaVirtualDirsInstall7( | ||
| 56 | __in SCA_VDIR7* psvdList, | ||
| 57 | __in SCA_APPPOOL * psapList | ||
| 58 | ); | ||
| 59 | |||
| 60 | HRESULT ScaVirtualDirsUninstall7( | ||
| 61 | __in SCA_VDIR7* psvdList | ||
| 62 | ); | ||
| 63 | |||
| 64 | void ScaVirtualDirsFreeList7( | ||
| 65 | __in SCA_VDIR7* psvdList | ||
| 66 | ); | ||
diff --git a/src/ext/Iis/ca/scaweb.cpp b/src/ext/Iis/ca/scaweb.cpp new file mode 100644 index 00000000..0452fb0b --- /dev/null +++ b/src/ext/Iis/ca/scaweb.cpp | |||
| @@ -0,0 +1,1187 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | //Adding this because delivery doesn't have the updated specstrings.h that windows build does | ||
| 6 | #ifndef __in_xcount | ||
| 7 | #define __in_xcount(size) | ||
| 8 | #endif | ||
| 9 | |||
| 10 | // sql queries | ||
| 11 | |||
| 12 | enum eWebBaseQuery { wbqWeb = 1, wbqId, wbqIP, wbqPort, wbqHeader, wbqSecure, wbqDescription }; | ||
| 13 | |||
| 14 | |||
| 15 | // prototypes for private helper functions | ||
| 16 | static SCA_WEB* NewWeb(); | ||
| 17 | static void FreeWeb(SCA_WEB *pswDelete); | ||
| 18 | static SCA_WEB* AddWebToList( | ||
| 19 | __in SCA_WEB* pswList, | ||
| 20 | __in SCA_WEB* psw | ||
| 21 | ); | ||
| 22 | static HRESULT ScaWebFindBase( | ||
| 23 | __in IMSAdminBase* piMetabase, | ||
| 24 | __in SCA_WEB* pswList, | ||
| 25 | __in_z LPCWSTR wzWeb, | ||
| 26 | __in int iSiteId, | ||
| 27 | __in_z LPCWSTR wzIP, | ||
| 28 | __in int iPort, | ||
| 29 | __in_z LPCWSTR wzHeader, | ||
| 30 | __in BOOL fSecure, | ||
| 31 | __in_z LPCWSTR wzDescription, | ||
| 32 | __out_ecount(cchWebBase) LPWSTR wzWebBase, | ||
| 33 | __in DWORD cchWebBase | ||
| 34 | ); | ||
| 35 | static HRESULT ScaWebFindFreeBase( | ||
| 36 | __in IMSAdminBase* piMetabase, | ||
| 37 | __in_xcount(unknown) SCA_WEB* pswList, | ||
| 38 | __in int iSiteId, | ||
| 39 | __in_z LPCWSTR wzDescription, | ||
| 40 | __out_ecount(cchWebBase) LPWSTR wzWebBase, | ||
| 41 | __in DWORD cchWebBase | ||
| 42 | ); | ||
| 43 | static HRESULT ScaWebWrite( | ||
| 44 | __in IMSAdminBase* piMetabase, | ||
| 45 | __in SCA_WEB* psw, | ||
| 46 | __in SCA_APPPOOL * psapList | ||
| 47 | ); | ||
| 48 | static HRESULT ScaWebRemove( | ||
| 49 | __in IMSAdminBase* piMetabase, | ||
| 50 | __in const SCA_WEB* psw); | ||
| 51 | static DWORD SiteIdFromDescription( | ||
| 52 | __in_z LPCWSTR wzDescription | ||
| 53 | ); | ||
| 54 | static void Sort( | ||
| 55 | __in_ecount(cArray) DWORD dwArray[], | ||
| 56 | __in int cArray | ||
| 57 | ); | ||
| 58 | |||
| 59 | |||
| 60 | HRESULT ScaWebsRead( | ||
| 61 | __in IMSAdminBase* piMetabase, | ||
| 62 | __in SCA_MIMEMAP** ppsmmList, | ||
| 63 | __in SCA_WEB** ppswList, | ||
| 64 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 65 | __in SCA_WEB_ERROR** ppsweList, | ||
| 66 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 67 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 68 | __in WCA_WRAPQUERY_HANDLE hSslCertQuery, | ||
| 69 | __in WCA_WRAPQUERY_HANDLE hWebLogQuery, | ||
| 70 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 71 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 72 | __inout LPWSTR *ppwzCustomActionData | ||
| 73 | ) | ||
| 74 | { | ||
| 75 | Assert(piMetabase && ppswList); | ||
| 76 | |||
| 77 | HRESULT hr = S_OK; | ||
| 78 | |||
| 79 | MSIHANDLE hRec; | ||
| 80 | MSIHANDLE hRecAddresses; | ||
| 81 | |||
| 82 | SCA_WEB* psw = NULL; | ||
| 83 | LPWSTR pwzData = NULL; | ||
| 84 | int iSiteId; | ||
| 85 | |||
| 86 | DWORD dwLen = 0; | ||
| 87 | WCA_WRAPQUERY_HANDLE hQueryWebSite = NULL; | ||
| 88 | WCA_WRAPQUERY_HANDLE hQueryWebAddress = NULL; | ||
| 89 | |||
| 90 | hr = WcaBeginUnwrapQuery(&hQueryWebSite, ppwzCustomActionData); | ||
| 91 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead"); | ||
| 92 | |||
| 93 | hr = WcaBeginUnwrapQuery(&hQueryWebAddress, ppwzCustomActionData); | ||
| 94 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead"); | ||
| 95 | |||
| 96 | if (0 == WcaGetQueryRecords(hQueryWebSite)) | ||
| 97 | { | ||
| 98 | WcaLog(LOGMSG_VERBOSE, "Required tables not present"); | ||
| 99 | ExitFunction1(hr = S_FALSE); | ||
| 100 | } | ||
| 101 | |||
| 102 | // loop through all the webs | ||
| 103 | while (S_OK == (hr = WcaFetchWrappedRecord(hQueryWebSite, &hRec))) | ||
| 104 | { | ||
| 105 | psw = NewWeb(); | ||
| 106 | ExitOnNull(psw, hr, E_OUTOFMEMORY, "Failed to allocate memory for web object in memory"); | ||
| 107 | |||
| 108 | // get the darwin information | ||
| 109 | hr = WcaGetRecordString(hRec, wqWeb, &pwzData); | ||
| 110 | ExitOnFailure(hr, "Failed to get Web"); | ||
| 111 | hr = ::StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData); | ||
| 112 | ExitOnFailure(hr, "Failed to copy key string to web object"); | ||
| 113 | |||
| 114 | if (*pwzData && *ppsmmList) | ||
| 115 | { | ||
| 116 | hr = ScaGetMimeMap(mmptWeb, pwzData, ppsmmList, &psw->psmm); | ||
| 117 | ExitOnFailure(hr, "Failed to get mimemap for VirtualDir"); | ||
| 118 | } | ||
| 119 | |||
| 120 | // get component install state | ||
| 121 | hr = WcaGetRecordString(hRec, wqComponent, &pwzData); | ||
| 122 | ExitOnFailure(hr, "Failed to get Component for Web"); | ||
| 123 | hr = ::StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData); | ||
| 124 | ExitOnFailure(hr, "Failed to copy component string to web object"); | ||
| 125 | if (*(psw->wzComponent)) | ||
| 126 | { | ||
| 127 | psw->fHasComponent = TRUE; | ||
| 128 | |||
| 129 | hr = WcaGetRecordInteger(hRec, wqInstalled, (int *)&psw->isInstalled); | ||
| 130 | ExitOnFailure(hr, "Failed to get web Component's installed state"); | ||
| 131 | |||
| 132 | WcaGetRecordInteger(hRec, wqAction, (int *)&psw->isAction); | ||
| 133 | ExitOnFailure(hr, "Failed to get web Component's action state"); | ||
| 134 | |||
| 135 | if (!WcaIsInstalling(psw->isInstalled, psw->isAction) && !WcaIsUninstalling(psw->isInstalled, psw->isAction) | ||
| 136 | && !WcaIsReInstalling(psw->isInstalled, psw->isAction)) | ||
| 137 | { | ||
| 138 | FreeWeb(psw); | ||
| 139 | psw = NULL; | ||
| 140 | |||
| 141 | continue; // If we aren't acting on this component, skip it | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | hr = WcaGetRecordInteger(hRec, wqId, &iSiteId); | ||
| 146 | ExitOnFailure(hr, "Failed to get SiteId for Web"); | ||
| 147 | |||
| 148 | // Get the web's key address. | ||
| 149 | hr = WcaGetRecordString(hRec, wqAddress, &pwzData); | ||
| 150 | ExitOnFailure(hr, "Failed to get Address for Web"); | ||
| 151 | hr = ::StringCchCopyW(psw->swaKey.wzKey, countof(psw->swaKey.wzKey), pwzData); | ||
| 152 | ExitOnFailure(hr, "Failed to copy key string to web object"); | ||
| 153 | |||
| 154 | hr = WcaGetRecordString(hRec, wqIP, &pwzData); | ||
| 155 | ExitOnFailure(hr, "Failed to get IP for Web"); | ||
| 156 | hr = ::StringCchCopyW(psw->swaKey.wzIP, countof(psw->swaKey.wzIP), pwzData); | ||
| 157 | ExitOnFailure(hr, "Failed to copy IP string to web object"); | ||
| 158 | |||
| 159 | hr = WcaGetRecordString(hRec, wqPort, &pwzData); | ||
| 160 | ExitOnFailure(hr, "Failed to get Web Address port"); | ||
| 161 | psw->swaKey.iPort = wcstol(pwzData, NULL, 10); | ||
| 162 | |||
| 163 | hr = WcaGetRecordString(hRec, wqHeader, &pwzData); | ||
| 164 | ExitOnFailure(hr, "Failed to get Header for Web"); | ||
| 165 | hr = ::StringCchCopyW(psw->swaKey.wzHeader, countof(psw->swaKey.wzHeader), pwzData); | ||
| 166 | ExitOnFailure(hr, "Failed to copy header string to web object"); | ||
| 167 | |||
| 168 | hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaKey.fSecure); | ||
| 169 | ExitOnFailure(hr, "Failed to get if Web is secure"); | ||
| 170 | if (S_FALSE == hr) | ||
| 171 | { | ||
| 172 | psw->swaKey.fSecure = FALSE; | ||
| 173 | } | ||
| 174 | |||
| 175 | // Get the web's description. | ||
| 176 | hr = WcaGetRecordString(hRec, wqDescription, &pwzData); | ||
| 177 | ExitOnFailure(hr, "Failed to get Description for Web"); | ||
| 178 | hr = ::StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData); | ||
| 179 | ExitOnFailure(hr, "Failed to copy description string to web object"); | ||
| 180 | |||
| 181 | // Try to find the web root in case it already exists. | ||
| 182 | dwLen = METADATA_MAX_NAME_LEN; | ||
| 183 | hr = ScaWebFindBase(piMetabase, *ppswList, | ||
| 184 | psw->wzKey, | ||
| 185 | iSiteId, | ||
| 186 | psw->swaKey.wzIP, | ||
| 187 | psw->swaKey.iPort, | ||
| 188 | psw->swaKey.wzHeader, | ||
| 189 | psw->swaKey.fSecure, | ||
| 190 | psw->wzDescription, | ||
| 191 | psw->wzWebBase, dwLen); | ||
| 192 | if (S_OK == hr) | ||
| 193 | { | ||
| 194 | psw->fBaseExists = TRUE; | ||
| 195 | } | ||
| 196 | else if (S_FALSE == hr) // didn't find the web site. | ||
| 197 | { | ||
| 198 | psw->fBaseExists = FALSE; | ||
| 199 | |||
| 200 | // If we're actually configuring the web site. | ||
| 201 | if (psw->fHasComponent) | ||
| 202 | { | ||
| 203 | if (WcaIsInstalling(psw->isInstalled, psw->isAction)) | ||
| 204 | { | ||
| 205 | hr = ScaWebFindFreeBase(piMetabase, *ppswList, iSiteId, psw->wzDescription, psw->wzWebBase, countof(psw->wzWebBase)); | ||
| 206 | ExitOnFailure(hr, "Failed to find free web root."); | ||
| 207 | } | ||
| 208 | else if (WcaIsUninstalling(psw->isInstalled, psw->isAction)) | ||
| 209 | { | ||
| 210 | WcaLog(LOGMSG_VERBOSE, "Web site: '%ls' was already removed, skipping.", psw->wzKey); | ||
| 211 | |||
| 212 | hr = S_OK; | ||
| 213 | continue; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | } | ||
| 217 | ExitOnFailure(hr, "Failed to find web root"); | ||
| 218 | |||
| 219 | // get any extra web addresses | ||
| 220 | WcaFetchWrappedReset(hQueryWebAddress); | ||
| 221 | while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hQueryWebAddress, 2, psw->wzKey, &hRecAddresses))) | ||
| 222 | { | ||
| 223 | if (MAX_ADDRESSES_PER_WEB <= psw->cExtraAddresses) | ||
| 224 | { | ||
| 225 | hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); | ||
| 226 | ExitOnFailure(hr, "Failure to get more extra web addresses, max exceeded."); | ||
| 227 | } | ||
| 228 | |||
| 229 | hr = WcaGetRecordString(hRecAddresses, waqAddress, &pwzData); | ||
| 230 | ExitOnFailure(hr, "Failed to get extra web Address"); | ||
| 231 | |||
| 232 | // if this isn't the key address add it | ||
| 233 | if (0 != lstrcmpW(pwzData, psw->swaKey.wzKey)) | ||
| 234 | { | ||
| 235 | hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData); | ||
| 236 | ExitOnFailure(hr, "Failed to copy extra addresses key string to web object"); | ||
| 237 | |||
| 238 | hr = WcaGetRecordString(hRecAddresses, waqIP, &pwzData); | ||
| 239 | ExitOnFailure(hr, "Failed to get extra web IP"); | ||
| 240 | hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData); | ||
| 241 | ExitOnFailure(hr, "Failed to copy extra addresses IP string to web object"); | ||
| 242 | |||
| 243 | hr = WcaGetRecordString(hRecAddresses, waqPort, &pwzData); | ||
| 244 | ExitOnFailure(hr, "Failed to get port for extra web IP"); | ||
| 245 | psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10); | ||
| 246 | |||
| 247 | hr = WcaGetRecordString(hRecAddresses, waqHeader, &pwzData); | ||
| 248 | ExitOnFailure(hr, "Failed to get header for extra web IP"); | ||
| 249 | hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData); | ||
| 250 | ExitOnFailure(hr, "Failed to copy extra addresses header string to web object"); | ||
| 251 | |||
| 252 | hr = WcaGetRecordInteger(hRecAddresses, waqSecure, &psw->swaExtraAddresses[psw->cExtraAddresses].fSecure); | ||
| 253 | ExitOnFailure(hr, "Failed to get if secure extra web IP"); | ||
| 254 | if (S_FALSE == hr) | ||
| 255 | psw->swaExtraAddresses[psw->cExtraAddresses].fSecure = FALSE; | ||
| 256 | |||
| 257 | ++psw->cExtraAddresses; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | if (E_NOMOREITEMS == hr) | ||
| 262 | hr = S_OK; | ||
| 263 | ExitOnFailure(hr, "Failure occured while getting extra web addresses"); | ||
| 264 | |||
| 265 | hr = WcaGetRecordInteger(hRec, wqConnectionTimeout, &psw->iConnectionTimeout); | ||
| 266 | ExitOnFailure(hr, "Failed to get connection timeout for Web"); | ||
| 267 | |||
| 268 | if (psw->fHasComponent) // If we're installing it, it needs a dir | ||
| 269 | { | ||
| 270 | // get the web's directory | ||
| 271 | if (INSTALLSTATE_SOURCE == psw->isAction) | ||
| 272 | { | ||
| 273 | hr = WcaGetRecordString(hRec, wqSourcePath, &pwzData); | ||
| 274 | } | ||
| 275 | else | ||
| 276 | { | ||
| 277 | hr = WcaGetRecordString(hRec, wqTargetPath, &pwzData); | ||
| 278 | } | ||
| 279 | ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); | ||
| 280 | |||
| 281 | // remove trailing backslashes | ||
| 282 | while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\') | ||
| 283 | { | ||
| 284 | pwzData[lstrlenW(pwzData)-1] = 0; | ||
| 285 | } | ||
| 286 | hr = ::StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), pwzData); | ||
| 287 | ExitOnFailure(hr, "Failed to copy directory string to web object"); | ||
| 288 | } | ||
| 289 | |||
| 290 | hr = WcaGetRecordInteger(hRec, wqState, &psw->iState); | ||
| 291 | ExitOnFailure(hr, "Failed to get state for Web"); | ||
| 292 | |||
| 293 | hr = WcaGetRecordInteger(hRec, wqAttributes, &psw->iAttributes); | ||
| 294 | ExitOnFailure(hr, "Failed to get attributes for Web"); | ||
| 295 | |||
| 296 | // get the dir properties for this web | ||
| 297 | hr = WcaGetRecordString(hRec, wqProperties, &pwzData); | ||
| 298 | ExitOnFailure(hr, "Failed to get directory property record for Web"); | ||
| 299 | if (*pwzData) | ||
| 300 | { | ||
| 301 | hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &psw->swp); | ||
| 302 | ExitOnFailure(hr, "Failed to get directory properties for Web"); | ||
| 303 | |||
| 304 | psw->fHasProperties = TRUE; | ||
| 305 | } | ||
| 306 | |||
| 307 | // get the application information for this web | ||
| 308 | hr = WcaGetRecordString(hRec, wqApplication, &pwzData); | ||
| 309 | ExitOnFailure(hr, "Failed to get application identifier for Web"); | ||
| 310 | if (*pwzData) | ||
| 311 | { | ||
| 312 | hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &psw->swapp); | ||
| 313 | ExitOnFailure(hr, "Failed to get application for Web"); | ||
| 314 | |||
| 315 | psw->fHasApplication = TRUE; | ||
| 316 | } | ||
| 317 | |||
| 318 | // get the SSL certificates | ||
| 319 | hr = ScaSslCertificateRead(psw->wzKey, hSslCertQuery, &(psw->pswscList)); | ||
| 320 | ExitOnFailure(hr, "Failed to get SSL Certificates."); | ||
| 321 | |||
| 322 | // get the custom headers | ||
| 323 | if (*ppshhList) | ||
| 324 | { | ||
| 325 | hr = ScaGetHttpHeader(hhptWeb, psw->wzKey, ppshhList, &(psw->pshhList)); | ||
| 326 | ExitOnFailure(hr, "Failed to get Custom HTTP Headers"); | ||
| 327 | } | ||
| 328 | |||
| 329 | // get the errors | ||
| 330 | if (*ppsweList) | ||
| 331 | { | ||
| 332 | hr = ScaGetWebError(weptWeb, psw->wzKey, ppsweList, &(psw->psweList)); | ||
| 333 | ExitOnFailure(hr, "Failed to get Custom Errors"); | ||
| 334 | } | ||
| 335 | |||
| 336 | // get the log information for this web | ||
| 337 | hr = WcaGetRecordString(hRec, wqLog, &pwzData); | ||
| 338 | ExitOnFailure(hr, "Failed to get log identifier for Web"); | ||
| 339 | if (*pwzData) | ||
| 340 | { | ||
| 341 | hr = ScaGetWebLog(piMetabase, pwzData, hWebLogQuery, &psw->swl); | ||
| 342 | ExitOnFailure(hr, "Failed to get Log for Web."); | ||
| 343 | |||
| 344 | psw->fHasLog = TRUE; | ||
| 345 | } | ||
| 346 | |||
| 347 | *ppswList = AddWebToList(*ppswList, psw); | ||
| 348 | psw = NULL; // set the web NULL so it doesn't accidentally get freed below | ||
| 349 | } | ||
| 350 | |||
| 351 | if (E_NOMOREITEMS == hr) | ||
| 352 | { | ||
| 353 | hr = S_OK; | ||
| 354 | } | ||
| 355 | |||
| 356 | LExit: | ||
| 357 | // if anything was left over after an error clean it all up | ||
| 358 | WcaFinishUnwrapQuery(hQueryWebSite); | ||
| 359 | WcaFinishUnwrapQuery(hQueryWebAddress); | ||
| 360 | |||
| 361 | if (psw) | ||
| 362 | { | ||
| 363 | ScaWebsFreeList(psw); | ||
| 364 | } | ||
| 365 | |||
| 366 | ReleaseStr(pwzData); | ||
| 367 | |||
| 368 | return hr; | ||
| 369 | } | ||
| 370 | |||
| 371 | |||
| 372 | HRESULT ScaWebsGetBase( | ||
| 373 | __in IMSAdminBase* piMetabase, | ||
| 374 | __in SCA_WEB* pswList, | ||
| 375 | __in LPCWSTR wzWeb, | ||
| 376 | __out_ecount(cchWebBase) LPWSTR wzWebBase, | ||
| 377 | __in DWORD cchWebBase, | ||
| 378 | __in WCA_WRAPQUERY_HANDLE hWrapQuery | ||
| 379 | ) | ||
| 380 | { | ||
| 381 | HRESULT hr = S_OK; | ||
| 382 | MSIHANDLE hRec; | ||
| 383 | |||
| 384 | int iSiteId; | ||
| 385 | WCHAR wzIP[MAX_PATH]; | ||
| 386 | int iPort = -1; | ||
| 387 | WCHAR wzHeader[MAX_PATH]; | ||
| 388 | BOOL fSecure = FALSE; | ||
| 389 | |||
| 390 | LPWSTR pwzData = NULL; | ||
| 391 | |||
| 392 | // get the web information | ||
| 393 | WcaFetchWrappedReset(hWrapQuery); | ||
| 394 | |||
| 395 | hr = WcaFetchWrappedRecordWhereString(hWrapQuery, 1, wzWeb, &hRec); | ||
| 396 | if (S_OK == hr) | ||
| 397 | { | ||
| 398 | // get the data to search for | ||
| 399 | hr = WcaGetRecordInteger(hRec, wbqId, &iSiteId); | ||
| 400 | ExitOnFailure(hr, "Failed to get SiteId for Web for VirtualDir"); | ||
| 401 | |||
| 402 | hr = WcaGetRecordString(hRec, wbqIP, &pwzData); | ||
| 403 | ExitOnFailure(hr, "Failed to get IP for Web for VirtualDir"); | ||
| 404 | hr = ::StringCchCopyW(wzIP, countof(wzIP), pwzData); | ||
| 405 | ExitOnFailure(hr, "Failed to copy IP for Web for VirtualDir"); | ||
| 406 | |||
| 407 | hr = WcaGetRecordString(hRec, wbqPort, &pwzData); | ||
| 408 | ExitOnFailure(hr, "Failed to get port for extra web IP"); | ||
| 409 | iPort = wcstol(pwzData, NULL, 10); | ||
| 410 | |||
| 411 | hr = WcaGetRecordString(hRec, wbqHeader, &pwzData); | ||
| 412 | ExitOnFailure(hr, "Failed to get Header for Web for VirtualDir"); | ||
| 413 | hr = ::StringCchCopyW(wzHeader, countof(wzHeader), pwzData); | ||
| 414 | ExitOnFailure(hr, "Failed to copy Header for Web for VirtualDir"); | ||
| 415 | |||
| 416 | hr = WcaGetRecordInteger(hRec, wbqSecure, &fSecure); | ||
| 417 | if (S_FALSE == hr) | ||
| 418 | fSecure = FALSE; | ||
| 419 | |||
| 420 | hr = WcaGetRecordString(hRec, wbqDescription, &pwzData); | ||
| 421 | ExitOnFailure(hr, "Failed to get Description for Web"); | ||
| 422 | |||
| 423 | // find the web or find the next free web location | ||
| 424 | hr = ScaWebFindBase(piMetabase, pswList, wzWeb, iSiteId, wzIP, iPort, wzHeader, fSecure, pwzData, wzWebBase, cchWebBase); | ||
| 425 | if (S_FALSE == hr) | ||
| 426 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 427 | ExitOnFailure(hr, "Failed to find Web base"); | ||
| 428 | } | ||
| 429 | else if (S_FALSE == hr) | ||
| 430 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 431 | |||
| 432 | // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would | ||
| 433 | HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWrapQuery, 1, wzWeb, &hRec); | ||
| 434 | if (SUCCEEDED(hrTemp)) | ||
| 435 | { | ||
| 436 | AssertSz(E_NOMOREITEMS == hrTemp, "ScaWebsGetBase found more than one record"); | ||
| 437 | } | ||
| 438 | |||
| 439 | LExit: | ||
| 440 | ReleaseStr(pwzData); | ||
| 441 | |||
| 442 | return hr; | ||
| 443 | } | ||
| 444 | |||
| 445 | |||
| 446 | HRESULT ScaWebsInstall( | ||
| 447 | __in IMSAdminBase* piMetabase, | ||
| 448 | __in SCA_WEB* pswList, | ||
| 449 | __in SCA_APPPOOL * psapList | ||
| 450 | ) | ||
| 451 | { | ||
| 452 | HRESULT hr = S_OK; | ||
| 453 | SCA_WEB* psw = pswList; | ||
| 454 | |||
| 455 | while (psw) | ||
| 456 | { | ||
| 457 | // if we are installing the web site | ||
| 458 | if (psw->fHasComponent && WcaIsInstalling(psw->isInstalled, psw->isAction)) | ||
| 459 | { | ||
| 460 | hr = ScaWebWrite(piMetabase, psw, psapList); | ||
| 461 | ExitOnFailure(hr, "failed to write web '%ls' to metabase", psw->wzKey); | ||
| 462 | } | ||
| 463 | |||
| 464 | psw = psw->pswNext; | ||
| 465 | } | ||
| 466 | |||
| 467 | LExit: | ||
| 468 | return hr; | ||
| 469 | } | ||
| 470 | |||
| 471 | |||
| 472 | HRESULT ScaWebsUninstall( | ||
| 473 | __in IMSAdminBase* piMetabase, | ||
| 474 | __in SCA_WEB* pswList | ||
| 475 | ) | ||
| 476 | { | ||
| 477 | HRESULT hr = S_OK; | ||
| 478 | SCA_WEB* psw = pswList; | ||
| 479 | |||
| 480 | while (psw) | ||
| 481 | { | ||
| 482 | // if we are uninstalling the web site | ||
| 483 | if (psw->fHasComponent && WcaIsUninstalling(psw->isInstalled, psw->isAction)) | ||
| 484 | { | ||
| 485 | hr = ScaWebRemove(piMetabase, psw); | ||
| 486 | ExitOnFailure(hr, "Failed to remove web '%ls' from metabase", psw->wzKey); | ||
| 487 | } | ||
| 488 | |||
| 489 | psw = psw->pswNext; | ||
| 490 | } | ||
| 491 | |||
| 492 | LExit: | ||
| 493 | return hr; | ||
| 494 | } | ||
| 495 | |||
| 496 | |||
| 497 | void ScaWebsFreeList( | ||
| 498 | __in SCA_WEB* pswList | ||
| 499 | ) | ||
| 500 | { | ||
| 501 | SCA_WEB* pswDelete = pswList; | ||
| 502 | while (pswList) | ||
| 503 | { | ||
| 504 | pswDelete = pswList; | ||
| 505 | pswList = pswList->pswNext; | ||
| 506 | |||
| 507 | // Free the SSL, headers and errors list first | ||
| 508 | FreeWeb(pswDelete); | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | |||
| 513 | // private helper functions | ||
| 514 | |||
| 515 | static void FreeWeb(SCA_WEB *pswDelete) | ||
| 516 | { | ||
| 517 | ScaSslCertificateFreeList(pswDelete->pswscList); | ||
| 518 | ScaHttpHeaderFreeList(pswDelete->pshhList); | ||
| 519 | ScaWebErrorFreeList(pswDelete->psweList); | ||
| 520 | MemFree(pswDelete); | ||
| 521 | } | ||
| 522 | |||
| 523 | static SCA_WEB* NewWeb() | ||
| 524 | { | ||
| 525 | SCA_WEB* psw = static_cast<SCA_WEB*>(MemAlloc(sizeof(SCA_WEB), TRUE)); | ||
| 526 | Assert(psw); | ||
| 527 | return psw; | ||
| 528 | } | ||
| 529 | |||
| 530 | |||
| 531 | static SCA_WEB* AddWebToList( | ||
| 532 | __in SCA_WEB* pswList, | ||
| 533 | __in SCA_WEB* psw | ||
| 534 | ) | ||
| 535 | { | ||
| 536 | if (pswList) | ||
| 537 | { | ||
| 538 | SCA_WEB* pswTemp = pswList; | ||
| 539 | while (pswTemp->pswNext) | ||
| 540 | { | ||
| 541 | pswTemp = pswTemp->pswNext; | ||
| 542 | } | ||
| 543 | |||
| 544 | pswTemp->pswNext = psw; | ||
| 545 | } | ||
| 546 | else | ||
| 547 | { | ||
| 548 | pswList = psw; | ||
| 549 | } | ||
| 550 | |||
| 551 | return pswList; | ||
| 552 | } | ||
| 553 | |||
| 554 | |||
| 555 | static HRESULT ScaWebFindBase( | ||
| 556 | __in IMSAdminBase* piMetabase, | ||
| 557 | __in SCA_WEB* pswList, | ||
| 558 | __in_z LPCWSTR wzWeb, | ||
| 559 | __in int iSiteId, | ||
| 560 | __in_z LPCWSTR wzIP, | ||
| 561 | __in int iPort, | ||
| 562 | __in_z LPCWSTR wzHeader, | ||
| 563 | __in BOOL fSecure, | ||
| 564 | __in_z LPCWSTR wzDescription, | ||
| 565 | __out_ecount(cchWebBase) LPWSTR wzWebBase, | ||
| 566 | __in DWORD cchWebBase | ||
| 567 | ) | ||
| 568 | { | ||
| 569 | Assert(piMetabase); | ||
| 570 | |||
| 571 | HRESULT hr = S_OK; | ||
| 572 | |||
| 573 | WCHAR wzKey[METADATA_MAX_NAME_LEN]; | ||
| 574 | WCHAR wzSubkey[METADATA_MAX_NAME_LEN]; | ||
| 575 | LPWSTR wzFoundKey = NULL; | ||
| 576 | |||
| 577 | METADATA_RECORD mr; | ||
| 578 | ::ZeroMemory(&mr, sizeof(mr)); | ||
| 579 | |||
| 580 | METADATA_RECORD mrCompare; | ||
| 581 | ::ZeroMemory(&mrCompare, sizeof(mrCompare)); | ||
| 582 | |||
| 583 | // try to find the web in memory first | ||
| 584 | for (SCA_WEB* psw = pswList; psw; psw = psw->pswNext) | ||
| 585 | { | ||
| 586 | if (0 == lstrcmpW(wzWeb, psw->wzKey)) | ||
| 587 | { | ||
| 588 | if ((0 == lstrcmpW(wzIP, psw->swaKey.wzIP) || 0 == lstrcmpW(wzIP, L"*") || 0 == lstrcmpW(psw->swaKey.wzIP, L"*")) && | ||
| 589 | iPort == psw->swaKey.iPort && | ||
| 590 | 0 == lstrcmpW(wzHeader, psw->swaKey.wzHeader) && | ||
| 591 | fSecure == psw->swaKey.fSecure) | ||
| 592 | { | ||
| 593 | if (0 == lstrlenW(psw->wzWebBase)) | ||
| 594 | { | ||
| 595 | WcaLog(LOGMSG_STANDARD, "A matching web object in memory was found, but the web object in memory has no associated base"); | ||
| 596 | ExitFunction1(hr = S_FALSE); | ||
| 597 | } | ||
| 598 | |||
| 599 | hr = ::StringCchCopyW(wzKey, countof(wzKey), psw->wzWebBase); | ||
| 600 | ExitOnFailure(hr, "Failed to copy web base into key."); | ||
| 601 | |||
| 602 | wzFoundKey = wzKey; | ||
| 603 | break; | ||
| 604 | } | ||
| 605 | else | ||
| 606 | { | ||
| 607 | WcaLog(LOGMSG_STANDARD, "Found web `%ls` but data did not match.", wzWeb); | ||
| 608 | hr = E_UNEXPECTED; | ||
| 609 | break; | ||
| 610 | } | ||
| 611 | } | ||
| 612 | } | ||
| 613 | ExitOnFailure(hr, "Failure occured while searching for web in memory"); | ||
| 614 | |||
| 615 | // If we didn't find a web in memory matching look in the metabase. | ||
| 616 | if (!wzFoundKey) | ||
| 617 | { | ||
| 618 | mr.dwMDIdentifier = MD_KEY_TYPE; | ||
| 619 | mr.dwMDAttributes = METADATA_INHERIT; | ||
| 620 | mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 621 | mr.dwMDDataType = ALL_METADATA; | ||
| 622 | mr.dwMDDataLen = 0; | ||
| 623 | mr.pbMDData = NULL; | ||
| 624 | |||
| 625 | // If we're looking based on the old WebAddress detection (NULL) or the new | ||
| 626 | // Web description detection (-1) | ||
| 627 | if (MSI_NULL_INTEGER == iSiteId || -1 == iSiteId) | ||
| 628 | { | ||
| 629 | if (MSI_NULL_INTEGER == iSiteId) | ||
| 630 | { | ||
| 631 | mrCompare.dwMDIdentifier = (fSecure) ? MD_SECURE_BINDINGS : MD_SERVER_BINDINGS; | ||
| 632 | } | ||
| 633 | else | ||
| 634 | { | ||
| 635 | mrCompare.dwMDIdentifier = MD_SERVER_COMMENT; | ||
| 636 | } | ||
| 637 | mrCompare.dwMDAttributes = METADATA_INHERIT; | ||
| 638 | mrCompare.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 639 | mrCompare.dwMDDataType = ALL_METADATA; | ||
| 640 | mrCompare.dwMDDataLen = 0; | ||
| 641 | mrCompare.pbMDData = NULL; | ||
| 642 | |||
| 643 | // Loop through the "web keys" looking for the "IIsWebServer" key that matches our search criteria. | ||
| 644 | for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex) | ||
| 645 | { | ||
| 646 | hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC", wzSubkey, dwIndex); | ||
| 647 | if (SUCCEEDED(hr)) | ||
| 648 | { | ||
| 649 | hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/W3SVC/%s", wzSubkey); | ||
| 650 | ExitOnFailure(hr, "Failed to copy web subkey."); | ||
| 651 | |||
| 652 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mr); | ||
| 653 | if (MD_ERROR_DATA_NOT_FOUND == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) | ||
| 654 | { | ||
| 655 | hr = S_FALSE; // didn't find anything, try next one | ||
| 656 | continue; | ||
| 657 | } | ||
| 658 | ExitOnFailure(hr, "Failed to get key from metabase while searching for web servers"); | ||
| 659 | |||
| 660 | // If we have an IIsWebServer check to see if this is the site we are searching for. | ||
| 661 | if (0 == lstrcmpW(L"IIsWebServer", (LPCWSTR)mr.pbMDData)) | ||
| 662 | { | ||
| 663 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mrCompare); | ||
| 664 | if (MD_ERROR_DATA_NOT_FOUND == hr || NULL == mrCompare.pbMDData) | ||
| 665 | { | ||
| 666 | hr = S_FALSE; | ||
| 667 | continue; | ||
| 668 | } | ||
| 669 | ExitOnFailure(hr, "Failed to get address/description from metabase while searching for web servers"); | ||
| 670 | |||
| 671 | LPWSTR pwzExists = (LPWSTR)mrCompare.pbMDData; | ||
| 672 | if (MSI_NULL_INTEGER == iSiteId) | ||
| 673 | { | ||
| 674 | // Break down the address into its constituent parts (IP:Port:Header). | ||
| 675 | while (S_OK == hr && *pwzExists) | ||
| 676 | { | ||
| 677 | LPCWSTR pwzIPExists = pwzExists; | ||
| 678 | pwzExists = const_cast<LPWSTR>(wcsstr(pwzIPExists, L":")); | ||
| 679 | ExitOnNull(pwzExists, hr, E_INVALIDARG, "Invalid web address. IP was not separated by a colon."); | ||
| 680 | *pwzExists = L'\0'; | ||
| 681 | |||
| 682 | LPCWSTR pwzPortExists = pwzExists + 1; | ||
| 683 | pwzExists = const_cast<LPWSTR>(wcsstr(pwzPortExists, L":")); | ||
| 684 | ExitOnNull(pwzExists, hr, E_INVALIDARG, "Invalid web address. Port was not separated by a colon."); | ||
| 685 | *pwzExists = L'\0'; | ||
| 686 | int iPortExists = wcstol(pwzPortExists, NULL, 10); | ||
| 687 | |||
| 688 | LPCWSTR pwzHeaderExists = pwzExists + 1; | ||
| 689 | |||
| 690 | // compare the passed in address with the address listed for this web | ||
| 691 | if ((0 == lstrcmpW(wzIP, pwzIPExists) || 0 == lstrcmpW(wzIP, L"*")) && | ||
| 692 | iPort == iPortExists && | ||
| 693 | 0 == lstrcmpW(wzHeader, pwzHeaderExists)) | ||
| 694 | { | ||
| 695 | wzFoundKey = wzKey; | ||
| 696 | break; | ||
| 697 | } | ||
| 698 | |||
| 699 | // move to the next block of data, this may move beyond the available | ||
| 700 | // data and exit the while loop above. | ||
| 701 | pwzExists = const_cast<LPWSTR>(pwzHeaderExists + lstrlenW(pwzHeaderExists) + 1); | ||
| 702 | } | ||
| 703 | } | ||
| 704 | else | ||
| 705 | { | ||
| 706 | if (0 == lstrcmpW(wzDescription, pwzExists)) | ||
| 707 | { | ||
| 708 | wzFoundKey = wzKey; | ||
| 709 | } | ||
| 710 | } | ||
| 711 | |||
| 712 | // If we found the key we were looking for, no point in continuing to search. | ||
| 713 | if (wzFoundKey) | ||
| 714 | { | ||
| 715 | break; | ||
| 716 | } | ||
| 717 | } | ||
| 718 | } | ||
| 719 | } | ||
| 720 | |||
| 721 | if (E_NOMOREITEMS == hr) | ||
| 722 | { | ||
| 723 | Assert(!wzFoundKey); | ||
| 724 | hr = S_FALSE; | ||
| 725 | } | ||
| 726 | } | ||
| 727 | else // we're looking a specific SiteId | ||
| 728 | { | ||
| 729 | hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/W3SVC/%d", iSiteId); | ||
| 730 | ExitOnFailure(hr, "Failed to allocate metabase key string."); | ||
| 731 | |||
| 732 | // if we have an IIsWebServer store the key | ||
| 733 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mr); | ||
| 734 | |||
| 735 | if (SUCCEEDED(hr) && NULL != mr.pbMDData && 0 == lstrcmpW(L"IIsWebServer", (LPCWSTR)mr.pbMDData)) | ||
| 736 | { | ||
| 737 | wzFoundKey = wzKey; | ||
| 738 | } | ||
| 739 | else if (MD_ERROR_DATA_NOT_FOUND == hr || NULL == mrCompare.pbMDData || NULL == mr.pbMDData) | ||
| 740 | { | ||
| 741 | hr = S_FALSE; | ||
| 742 | } | ||
| 743 | } | ||
| 744 | } | ||
| 745 | |||
| 746 | if (wzFoundKey) | ||
| 747 | { | ||
| 748 | Assert(S_OK == hr); | ||
| 749 | |||
| 750 | hr = ::StringCchCopyW(wzWebBase, cchWebBase, wzFoundKey); | ||
| 751 | ExitOnFailure(hr, "Buffer not larger enough for found base key."); | ||
| 752 | } | ||
| 753 | |||
| 754 | LExit: | ||
| 755 | MetaFreeValue(&mr); | ||
| 756 | MetaFreeValue(&mrCompare); | ||
| 757 | |||
| 758 | if (!wzFoundKey && SUCCEEDED(hr)) | ||
| 759 | { | ||
| 760 | hr = S_FALSE; | ||
| 761 | } | ||
| 762 | |||
| 763 | return hr; | ||
| 764 | } | ||
| 765 | |||
| 766 | |||
| 767 | static HRESULT ScaWebFindFreeBase( | ||
| 768 | __in IMSAdminBase* piMetabase, | ||
| 769 | __in_xcount(unknown) SCA_WEB* pswList, | ||
| 770 | __in int iSiteId, | ||
| 771 | __in_z LPCWSTR wzDescription, | ||
| 772 | __out_ecount(cchWebBase) LPWSTR wzWebBase, | ||
| 773 | __in DWORD cchWebBase | ||
| 774 | ) | ||
| 775 | { | ||
| 776 | Assert(piMetabase); | ||
| 777 | |||
| 778 | HRESULT hr = S_OK; | ||
| 779 | |||
| 780 | WCHAR wzKey[METADATA_MAX_NAME_LEN]; | ||
| 781 | WCHAR wzSubkey[METADATA_MAX_NAME_LEN]; | ||
| 782 | DWORD* prgdwSubKeys = NULL; | ||
| 783 | DWORD cSubKeys = 128; | ||
| 784 | DWORD cSubKeysFilled = 0; | ||
| 785 | |||
| 786 | DWORD dwKey; | ||
| 787 | |||
| 788 | METADATA_RECORD mr; | ||
| 789 | ::ZeroMemory(&mr, sizeof(METADATA_RECORD)); | ||
| 790 | mr.dwMDIdentifier = MD_KEY_TYPE; | ||
| 791 | mr.dwMDAttributes = 0; | ||
| 792 | mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 793 | mr.dwMDDataType = STRING_METADATA; | ||
| 794 | mr.dwMDDataLen = 0; | ||
| 795 | mr.pbMDData = NULL; | ||
| 796 | |||
| 797 | if (MSI_NULL_INTEGER == iSiteId || -1 == iSiteId) | ||
| 798 | { | ||
| 799 | prgdwSubKeys = static_cast<DWORD*>(MemAlloc(cSubKeys * sizeof(DWORD), TRUE)); | ||
| 800 | ExitOnNull(prgdwSubKeys, hr, E_OUTOFMEMORY, "failed to allocate space for web site keys"); | ||
| 801 | |||
| 802 | // loop through the "web keys" looking for the "IIsWebServer" key that matches wzWeb | ||
| 803 | for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex) | ||
| 804 | { | ||
| 805 | hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC", wzSubkey, dwIndex); | ||
| 806 | if (SUCCEEDED(hr)) | ||
| 807 | { | ||
| 808 | hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/W3SVC/%s", wzSubkey); | ||
| 809 | ExitOnFailure(hr, "Failed remember key."); | ||
| 810 | |||
| 811 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mr); | ||
| 812 | if (MD_ERROR_DATA_NOT_FOUND == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) | ||
| 813 | { | ||
| 814 | hr = S_FALSE; // didn't find anything, try next one | ||
| 815 | continue; | ||
| 816 | } | ||
| 817 | ExitOnFailure(hr, "Failed to get key from metabase while searching for free web root"); | ||
| 818 | |||
| 819 | // if we have a IIsWebServer get the address information | ||
| 820 | if (0 == lstrcmpW(L"IIsWebServer", (LPCWSTR)mr.pbMDData)) | ||
| 821 | { | ||
| 822 | if (cSubKeysFilled >= cSubKeys) | ||
| 823 | { | ||
| 824 | cSubKeys = cSubKeys * 2; | ||
| 825 | prgdwSubKeys = static_cast<DWORD*>(MemReAlloc(prgdwSubKeys, cSubKeys * sizeof(DWORD), FALSE)); | ||
| 826 | ExitOnNull(prgdwSubKeys, hr, E_OUTOFMEMORY, "failed to allocate space for web site keys"); | ||
| 827 | } | ||
| 828 | |||
| 829 | prgdwSubKeys[cSubKeysFilled] = wcstol(wzSubkey, NULL, 10); | ||
| 830 | ++cSubKeysFilled; | ||
| 831 | Sort(prgdwSubKeys, cSubKeysFilled); | ||
| 832 | } | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | if (E_NOMOREITEMS == hr) | ||
| 837 | { | ||
| 838 | hr = S_OK; | ||
| 839 | } | ||
| 840 | ExitOnFailure(hr, "Failed to find free web root"); | ||
| 841 | |||
| 842 | // Add all the webs created in memory. | ||
| 843 | CONST WCHAR *pcchSlash; | ||
| 844 | for (SCA_WEB* psw = pswList; psw; psw = psw->pswNext) | ||
| 845 | { | ||
| 846 | // Don't process webs that don't have a base | ||
| 847 | if (!*psw->wzWebBase) | ||
| 848 | { | ||
| 849 | continue; | ||
| 850 | } | ||
| 851 | |||
| 852 | // find the last slash in the web root because the root # is after it | ||
| 853 | pcchSlash = NULL; | ||
| 854 | for (CONST WCHAR *pcch = psw->wzWebBase; pcch && *pcch; ++pcch) | ||
| 855 | { | ||
| 856 | if (L'/' == *pcch) | ||
| 857 | { | ||
| 858 | pcchSlash = pcch; | ||
| 859 | } | ||
| 860 | } | ||
| 861 | // In case we don't find a slash, error out | ||
| 862 | ExitOnNull(pcchSlash, hr, E_INVALIDARG, "Failed to find a slash in the web root: %ls", psw->wzWebBase); | ||
| 863 | |||
| 864 | prgdwSubKeys[cSubKeysFilled] = wcstol(pcchSlash + 1, NULL, 10); | ||
| 865 | ++cSubKeysFilled; | ||
| 866 | Sort(prgdwSubKeys, cSubKeysFilled); | ||
| 867 | |||
| 868 | if (cSubKeysFilled >= cSubKeys) | ||
| 869 | { | ||
| 870 | cSubKeys = cSubKeys * 2; | ||
| 871 | prgdwSubKeys = static_cast<DWORD*>(MemReAlloc(prgdwSubKeys, cSubKeys * sizeof(DWORD), FALSE)); | ||
| 872 | ExitOnNull(prgdwSubKeys, hr, E_OUTOFMEMORY, "failed to allocate space for web site keys"); | ||
| 873 | } | ||
| 874 | } | ||
| 875 | |||
| 876 | // Find the lowest free web root. | ||
| 877 | dwKey = (-1 == iSiteId) ? SiteIdFromDescription(wzDescription) : 1; | ||
| 878 | for (DWORD i = 0; i < cSubKeysFilled; ++i) | ||
| 879 | { | ||
| 880 | if (dwKey == prgdwSubKeys[i]) | ||
| 881 | { | ||
| 882 | ++dwKey; | ||
| 883 | } | ||
| 884 | else if (dwKey < prgdwSubKeys[i]) | ||
| 885 | { | ||
| 886 | break; | ||
| 887 | } | ||
| 888 | } | ||
| 889 | } | ||
| 890 | else | ||
| 891 | { | ||
| 892 | dwKey = iSiteId; | ||
| 893 | } | ||
| 894 | |||
| 895 | hr = ::StringCchPrintfW(wzWebBase, cchWebBase, L"/LM/W3SVC/%u", dwKey); | ||
| 896 | ExitOnFailure(hr, "failed to format web base with key: %u", dwKey); | ||
| 897 | |||
| 898 | LExit: | ||
| 899 | MetaFreeValue(&mr); | ||
| 900 | |||
| 901 | if (prgdwSubKeys) | ||
| 902 | { | ||
| 903 | MemFree(prgdwSubKeys); | ||
| 904 | } | ||
| 905 | |||
| 906 | return hr; | ||
| 907 | } | ||
| 908 | |||
| 909 | |||
| 910 | static HRESULT ScaWebWrite( | ||
| 911 | __in IMSAdminBase* piMetabase, | ||
| 912 | __in SCA_WEB* psw, | ||
| 913 | __in SCA_APPPOOL * psapList) | ||
| 914 | { | ||
| 915 | HRESULT hr = S_OK; | ||
| 916 | |||
| 917 | UINT ui = 0; | ||
| 918 | WCHAR wzIP[64]; | ||
| 919 | WCHAR wzBindings[1024]; | ||
| 920 | WCHAR wzSecureBindings[1024]; | ||
| 921 | WCHAR* pcchNext; // used to properly create the MULTI_SZ | ||
| 922 | DWORD cchPcchNext; | ||
| 923 | WCHAR* pcchSecureNext ; // used to properly create the MULTI_SZ | ||
| 924 | DWORD cchPcchSecureNext; | ||
| 925 | |||
| 926 | // if the web root doesn't exist create it | ||
| 927 | if (!psw->fBaseExists) | ||
| 928 | { | ||
| 929 | hr = ScaCreateWeb(piMetabase, psw->wzKey, psw->wzWebBase); | ||
| 930 | ExitOnFailure(hr, "Failed to create web"); | ||
| 931 | } | ||
| 932 | else if (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS) // if we're not supposed to configure existing webs, bail | ||
| 933 | { | ||
| 934 | Assert(psw->fBaseExists); | ||
| 935 | |||
| 936 | hr = S_FALSE; | ||
| 937 | WcaLog(LOGMSG_VERBOSE, "Skipping configuration of existing web: %ls", psw->wzKey); | ||
| 938 | ExitFunction(); | ||
| 939 | } | ||
| 940 | |||
| 941 | // put the secure and non-secure bindings together as MULTI_SZs | ||
| 942 | ::ZeroMemory(wzBindings, sizeof(wzBindings)); | ||
| 943 | pcchNext = wzBindings; | ||
| 944 | cchPcchNext = countof(wzBindings); | ||
| 945 | ::ZeroMemory(wzSecureBindings, sizeof(wzSecureBindings)); | ||
| 946 | pcchSecureNext = wzSecureBindings; | ||
| 947 | cchPcchSecureNext = countof(wzSecureBindings); | ||
| 948 | |||
| 949 | // set the IP address appropriately | ||
| 950 | if (0 == lstrcmpW(psw->swaKey.wzIP, L"*")) | ||
| 951 | { | ||
| 952 | ::ZeroMemory(wzIP, sizeof(wzIP)); | ||
| 953 | } | ||
| 954 | else | ||
| 955 | { | ||
| 956 | hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaKey.wzIP); | ||
| 957 | ExitOnFailure(hr, "Failed to copy IP string"); | ||
| 958 | } | ||
| 959 | |||
| 960 | WCHAR wzBinding[256]; | ||
| 961 | hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaKey.iPort, psw->swaKey.wzHeader); | ||
| 962 | ExitOnFailure(hr, "Failed to format IP:Port:Header binding string"); | ||
| 963 | if (psw->swaKey.fSecure) | ||
| 964 | { | ||
| 965 | hr = ::StringCchCopyW(pcchSecureNext, cchPcchSecureNext, wzBinding); | ||
| 966 | ExitOnFailure(hr, "Failed to copy binding string to securenext string"); | ||
| 967 | pcchSecureNext += lstrlenW(wzBinding) + 1; | ||
| 968 | cchPcchSecureNext -= lstrlenW(wzBinding) + 1; | ||
| 969 | } | ||
| 970 | else | ||
| 971 | { | ||
| 972 | hr = ::StringCchCopyW(pcchNext, cchPcchNext, wzBinding); | ||
| 973 | ExitOnFailure(hr, "Failed to copy binding string to next string"); | ||
| 974 | pcchNext += lstrlenW(wzBinding) + 1; | ||
| 975 | cchPcchNext -= lstrlenW(wzBinding) + 1; | ||
| 976 | } | ||
| 977 | |||
| 978 | for (ui = 0; ui < psw->cExtraAddresses; ++ui) | ||
| 979 | { | ||
| 980 | // set the IP address appropriately | ||
| 981 | if (0 == lstrcmpW(psw->swaExtraAddresses[ui].wzIP, L"*")) | ||
| 982 | { | ||
| 983 | ::ZeroMemory(wzIP, sizeof(wzIP)); | ||
| 984 | } | ||
| 985 | else | ||
| 986 | { | ||
| 987 | hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaExtraAddresses[ui].wzIP); | ||
| 988 | ExitOnFailure(hr, "Failed to copy extra addresses IP to IP string"); | ||
| 989 | } | ||
| 990 | |||
| 991 | hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaExtraAddresses[ui].iPort, psw->swaExtraAddresses[ui].wzHeader); | ||
| 992 | ExitOnFailure(hr, "Failed to format IP:Port:Header binding string for extra address"); | ||
| 993 | if (psw->swaExtraAddresses[ui].fSecure) | ||
| 994 | { | ||
| 995 | hr = ::StringCchCopyW(pcchSecureNext, cchPcchSecureNext, wzBinding); | ||
| 996 | ExitOnFailure(hr, "Failed to copy binding string to securenext string for extra address"); | ||
| 997 | pcchSecureNext += lstrlenW(wzBinding) + 1; | ||
| 998 | cchPcchSecureNext -= lstrlenW(wzBinding) + 1; | ||
| 999 | } | ||
| 1000 | else | ||
| 1001 | { | ||
| 1002 | hr = ::StringCchCopyW(pcchNext, cchPcchNext, wzBinding); | ||
| 1003 | ExitOnFailure(hr, "Failed to copy binding string to next string for extra address"); | ||
| 1004 | pcchNext += lstrlenW(wzBinding) + 1; | ||
| 1005 | cchPcchNext -= lstrlenW(wzBinding) + 1; | ||
| 1006 | } | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | // Delete the existing secure bindings metabase value, as having one while SSLCertHash and SSLStoreName aren't both set correctly can result in | ||
| 1010 | // 0x80070520 (ERROR_NO_SUCH_LOGON_SESSION) errors in some situations on IIS7. Clearing this value first and then setting it after the install has completed | ||
| 1011 | // allows the two aforementioned properties to exist in an intermediate state without errors | ||
| 1012 | hr = ScaDeleteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SECURE_BINDINGS, MULTISZ_METADATA); | ||
| 1013 | ExitOnFailure(hr, "Failed to temporarily delete secure bindings for Web"); | ||
| 1014 | |||
| 1015 | // now write the bindings to the metabase | ||
| 1016 | hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, wzBindings); | ||
| 1017 | ExitOnFailure(hr, "Failed to write server bindings for Web"); | ||
| 1018 | |||
| 1019 | // write the target path for the web's directory to the metabase | ||
| 1020 | hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"/Root", MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, psw->wzDirectory); | ||
| 1021 | ExitOnFailure(hr, "Failed to write virtual root path for Web"); | ||
| 1022 | |||
| 1023 | // write the description for the web to the metabase | ||
| 1024 | hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_COMMENT, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, psw->wzDescription); | ||
| 1025 | ExitOnFailure(hr, "Failed to write description for Web"); | ||
| 1026 | |||
| 1027 | ui = psw->iConnectionTimeout; | ||
| 1028 | if (MSI_NULL_INTEGER != ui) | ||
| 1029 | { | ||
| 1030 | hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_CONNECTION_TIMEOUT, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui)); | ||
| 1031 | ExitOnFailure(hr, "Failed to write connection timeout for Web"); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | ui = psw->iState; | ||
| 1035 | if (MSI_NULL_INTEGER != ui) | ||
| 1036 | { | ||
| 1037 | if (2 == ui) | ||
| 1038 | { | ||
| 1039 | ui = 1; | ||
| 1040 | hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_AUTOSTART, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui)); | ||
| 1041 | ExitOnFailure(hr, "Failed to write auto start flag for Web"); | ||
| 1042 | ui = 2; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | if (1 == ui || 2 == ui) | ||
| 1046 | { | ||
| 1047 | ui = 1; // start command | ||
| 1048 | hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_COMMAND, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui)); | ||
| 1049 | ExitOnFailure(hr, "Failed to start Web"); | ||
| 1050 | } | ||
| 1051 | else if (0 == ui) | ||
| 1052 | { | ||
| 1053 | ui = 2; // stop command | ||
| 1054 | hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_COMMAND, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui)); | ||
| 1055 | ExitOnFailure(hr, "Failed to stop Web"); | ||
| 1056 | } | ||
| 1057 | else | ||
| 1058 | { | ||
| 1059 | hr = E_UNEXPECTED; | ||
| 1060 | ExitOnFailure(hr, "Unexpected value for Web State"); | ||
| 1061 | } | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | WCHAR wzRootOfWeb[METADATA_MAX_NAME_LEN]; | ||
| 1065 | hr = ::StringCchPrintfW(wzRootOfWeb, countof(wzRootOfWeb), L"%s/Root", psw->wzWebBase); | ||
| 1066 | ExitOnFailure(hr, "Failed to allocate WebBase/Root string for root of web"); | ||
| 1067 | |||
| 1068 | // write the web dirproperties information | ||
| 1069 | if (psw->fHasProperties) | ||
| 1070 | { | ||
| 1071 | hr = ScaWriteWebDirProperties(piMetabase, wzRootOfWeb, &psw->swp); | ||
| 1072 | ExitOnFailure(hr, "Failed to write web security information to metabase"); | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | // write the application information | ||
| 1076 | if (psw->fHasApplication) | ||
| 1077 | { | ||
| 1078 | // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created | ||
| 1079 | if (WcaIsReInstalling(psw->isInstalled, psw->isAction)) | ||
| 1080 | { | ||
| 1081 | hr = ScaDeleteApp(piMetabase, wzRootOfWeb); | ||
| 1082 | ExitOnFailure(hr, "Failed to remove application for WebDir as part of a reinstall"); | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | hr = ScaWriteWebApplication(piMetabase, wzRootOfWeb, &psw->swapp, psapList); | ||
| 1086 | ExitOnFailure(hr, "Failed to write web application information to metabase"); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | // write the SSL certificate information | ||
| 1090 | if (psw->pswscList) | ||
| 1091 | { | ||
| 1092 | hr = ScaSslCertificateWriteMetabase(piMetabase, psw->wzWebBase, psw->pswscList); | ||
| 1093 | ExitOnFailure(hr, "Failed to write SSL certificates for Web site: %ls", psw->wzKey); | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SECURE_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, wzSecureBindings); | ||
| 1097 | ExitOnFailure(hr, "Failed to write secure bindings for Web"); | ||
| 1098 | |||
| 1099 | // write the headers | ||
| 1100 | if (psw->pshhList) | ||
| 1101 | { | ||
| 1102 | hr = ScaWriteHttpHeader(piMetabase, wzRootOfWeb, psw->pshhList); | ||
| 1103 | ExitOnFailure(hr, "Failed to write custom HTTP headers for Web site: %ls", psw->wzKey); | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | // write the errors | ||
| 1107 | if (psw->psweList) | ||
| 1108 | { | ||
| 1109 | hr = ScaWriteWebError(piMetabase, weptWeb, psw->wzWebBase, psw->psweList); | ||
| 1110 | ExitOnFailure(hr, "Failed to write custom web errors for Web site: %ls", psw->wzKey); | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | // write the mimetypes | ||
| 1114 | if (psw->psmm) | ||
| 1115 | { | ||
| 1116 | hr = ScaWriteMimeMap(piMetabase, wzRootOfWeb, psw->psmm); | ||
| 1117 | ExitOnFailure(hr, "Failed to write mimemap for Web site: %ls", psw->wzKey); | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | // write the log information to the metabase | ||
| 1121 | if (psw->fHasLog) | ||
| 1122 | { | ||
| 1123 | hr = ScaWriteWebLog(piMetabase, psw->wzWebBase, &psw->swl); | ||
| 1124 | ExitOnFailure(hr, "Failed to write web log information to metabase"); | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | LExit: | ||
| 1128 | return hr; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | |||
| 1132 | static HRESULT ScaWebRemove( | ||
| 1133 | __in IMSAdminBase* piMetabase, | ||
| 1134 | __in const SCA_WEB* psw | ||
| 1135 | ) | ||
| 1136 | { | ||
| 1137 | HRESULT hr = S_OK; | ||
| 1138 | |||
| 1139 | // simply remove the root key and everything else is pulled at the same time | ||
| 1140 | hr = ScaDeleteMetabaseKey(piMetabase, psw->wzWebBase, L""); | ||
| 1141 | ExitOnFailure(hr, "Failed to remove web '%ls' from metabase", psw->wzKey); | ||
| 1142 | |||
| 1143 | LExit: | ||
| 1144 | return hr; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | |||
| 1148 | static DWORD SiteIdFromDescription( | ||
| 1149 | __in_z LPCWSTR wzDescription | ||
| 1150 | ) | ||
| 1151 | { | ||
| 1152 | LPCWSTR pwz = wzDescription; | ||
| 1153 | DWORD dwSiteId = 0; | ||
| 1154 | while (pwz && *pwz) | ||
| 1155 | { | ||
| 1156 | WCHAR ch = *pwz & 0xdf; | ||
| 1157 | dwSiteId = (dwSiteId * 101) + ch; | ||
| 1158 | ++pwz; | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | return (dwSiteId % INT_MAX) + 1; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | |||
| 1165 | // insertion sort | ||
| 1166 | static void Sort( | ||
| 1167 | __in_ecount(cArray) DWORD dwArray[], | ||
| 1168 | __in int cArray | ||
| 1169 | ) | ||
| 1170 | { | ||
| 1171 | int i, j; | ||
| 1172 | DWORD dwData; | ||
| 1173 | |||
| 1174 | for (i = 1; i < cArray; ++i) | ||
| 1175 | { | ||
| 1176 | dwData = dwArray[i]; | ||
| 1177 | |||
| 1178 | j = i - 1; | ||
| 1179 | while (0 <= j && dwArray[j] > dwData) | ||
| 1180 | { | ||
| 1181 | dwArray[j + 1] = dwArray[j]; | ||
| 1182 | j--; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | dwArray[j + 1] = dwData; | ||
| 1186 | } | ||
| 1187 | } | ||
diff --git a/src/ext/Iis/ca/scaweb.h b/src/ext/Iis/ca/scaweb.h new file mode 100644 index 00000000..294030b4 --- /dev/null +++ b/src/ext/Iis/ca/scaweb.h | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scawebapp.h" | ||
| 6 | #include "scawebprop.h" | ||
| 7 | #include "scahttpheader.h" | ||
| 8 | #include "scaweberr.h" | ||
| 9 | #include "scassl.h" | ||
| 10 | #include "scaapppool.h" | ||
| 11 | #include "scaweblog.h" | ||
| 12 | #include "scamimemap.h" | ||
| 13 | |||
| 14 | // globals | ||
| 15 | #define MAX_ADDRESSES_PER_WEB 10 | ||
| 16 | |||
| 17 | enum eWebQuery { wqWeb = 1, wqComponent, wqId, wqDescription, wqConnectionTimeout, wqDirectory, | ||
| 18 | wqState, wqAttributes, wqProperties, wqApplication, wqAddress, wqIP, wqPort, wqHeader, wqSecure, wqLog, wqInstalled, wqAction, wqSourcePath, wqTargetPath}; | ||
| 19 | |||
| 20 | enum eWebAddressQuery { waqAddress = 1, waqWeb, waqIP, waqPort, waqHeader, waqSecure }; | ||
| 21 | |||
| 22 | enum SCA_WEB_ATTRIBUTES | ||
| 23 | { | ||
| 24 | SWATTRIB_NOCONFIGUREIFEXISTS = 2 | ||
| 25 | }; | ||
| 26 | |||
| 27 | // structs | ||
| 28 | struct SCA_WEB_ADDRESS | ||
| 29 | { | ||
| 30 | WCHAR wzKey [MAX_DARWIN_KEY + 1]; | ||
| 31 | |||
| 32 | WCHAR wzIP[MAX_DARWIN_COLUMN + 1]; | ||
| 33 | int iPort; | ||
| 34 | WCHAR wzHeader[MAX_DARWIN_COLUMN + 1]; | ||
| 35 | BOOL fSecure; | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct SCA_WEB | ||
| 39 | { | ||
| 40 | // darwin information | ||
| 41 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 42 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 43 | BOOL fHasComponent; | ||
| 44 | INSTALLSTATE isInstalled; | ||
| 45 | INSTALLSTATE isAction; | ||
| 46 | |||
| 47 | // metabase information | ||
| 48 | WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1]; | ||
| 49 | BOOL fBaseExists; | ||
| 50 | |||
| 51 | // iis configuation information | ||
| 52 | SCA_WEB_ADDRESS swaKey; | ||
| 53 | |||
| 54 | SCA_WEB_ADDRESS swaExtraAddresses[MAX_ADDRESSES_PER_WEB + 1]; | ||
| 55 | DWORD cExtraAddresses; | ||
| 56 | |||
| 57 | WCHAR wzDirectory[MAX_PATH]; | ||
| 58 | WCHAR wzDescription[MAX_DARWIN_COLUMN + 1]; | ||
| 59 | |||
| 60 | int iState; | ||
| 61 | int iAttributes; | ||
| 62 | |||
| 63 | BOOL fHasProperties; | ||
| 64 | SCA_WEB_PROPERTIES swp; | ||
| 65 | |||
| 66 | BOOL fHasApplication; | ||
| 67 | SCA_WEB_APPLICATION swapp; | ||
| 68 | |||
| 69 | BOOL fHasSecurity; | ||
| 70 | int dwAccessPermissions; | ||
| 71 | int iConnectionTimeout; | ||
| 72 | |||
| 73 | SCA_MIMEMAP* psmm; // mime mappings | ||
| 74 | SCA_WEB_SSL_CERTIFICATE* pswscList; | ||
| 75 | SCA_HTTP_HEADER* pshhList; | ||
| 76 | SCA_WEB_ERROR* psweList; | ||
| 77 | |||
| 78 | BOOL fHasLog; | ||
| 79 | SCA_WEB_LOG swl; | ||
| 80 | |||
| 81 | SCA_WEB* pswNext; | ||
| 82 | }; | ||
| 83 | |||
| 84 | |||
| 85 | // prototypes | ||
| 86 | HRESULT ScaWebsRead( | ||
| 87 | __in IMSAdminBase* piMetabase, | ||
| 88 | __in SCA_MIMEMAP** ppsmmList, | ||
| 89 | __in SCA_WEB** ppswList, | ||
| 90 | __in SCA_HTTP_HEADER** pshhList, | ||
| 91 | __in SCA_WEB_ERROR** psweList, | ||
| 92 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 93 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 94 | __in WCA_WRAPQUERY_HANDLE hSslCertQuery, | ||
| 95 | __in WCA_WRAPQUERY_HANDLE hWebLogQuery, | ||
| 96 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 97 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 98 | __inout LPWSTR *ppwzCustomActionData | ||
| 99 | ); | ||
| 100 | |||
| 101 | HRESULT ScaWebsGetBase( | ||
| 102 | __in IMSAdminBase* piMetabase, | ||
| 103 | __in SCA_WEB* pswList, | ||
| 104 | __in LPCWSTR wzWeb, | ||
| 105 | __out_ecount(cchWebBase) LPWSTR wzWebBase, | ||
| 106 | __in DWORD cchWebBase, | ||
| 107 | __in WCA_WRAPQUERY_HANDLE hWrapQuery | ||
| 108 | ); | ||
| 109 | |||
| 110 | HRESULT ScaWebsInstall( | ||
| 111 | __in IMSAdminBase* piMetabase, | ||
| 112 | __in SCA_WEB* pswList, | ||
| 113 | __in SCA_APPPOOL * psapList | ||
| 114 | ); | ||
| 115 | |||
| 116 | HRESULT ScaWebsUninstall( | ||
| 117 | __in IMSAdminBase* piMetabase, | ||
| 118 | __in SCA_WEB* pswList | ||
| 119 | ); | ||
| 120 | |||
| 121 | void ScaWebsFreeList( | ||
| 122 | __in SCA_WEB* pswHead | ||
| 123 | ); | ||
diff --git a/src/ext/Iis/ca/scaweb7.cpp b/src/ext/Iis/ca/scaweb7.cpp new file mode 100644 index 00000000..3ee781f2 --- /dev/null +++ b/src/ext/Iis/ca/scaweb7.cpp | |||
| @@ -0,0 +1,953 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | //Adding this because delivery doesn't have the updated specstrings.h that windows build does | ||
| 6 | #ifndef __in_xcount | ||
| 7 | #define __in_xcount(size) | ||
| 8 | #endif | ||
| 9 | |||
| 10 | // prototypes for private helper functions | ||
| 11 | static SCA_WEB7* NewWeb7(); | ||
| 12 | static SCA_WEB7* AddWebToList7( | ||
| 13 | __in SCA_WEB7* pswList, | ||
| 14 | __in SCA_WEB7* psw | ||
| 15 | ); | ||
| 16 | |||
| 17 | static HRESULT ScaWebFindBase7( | ||
| 18 | __in SCA_WEB7* pswList, | ||
| 19 | LPCWSTR wzDescription | ||
| 20 | ); | ||
| 21 | |||
| 22 | static HRESULT ScaWebWrite7( | ||
| 23 | __in SCA_WEB7* psw, | ||
| 24 | __in SCA_APPPOOL * psapList | ||
| 25 | ); | ||
| 26 | |||
| 27 | static HRESULT ScaWebRemove7(__in const SCA_WEB7* psw); | ||
| 28 | |||
| 29 | |||
| 30 | HRESULT ScaWebsRead7( | ||
| 31 | __in SCA_WEB7** ppswList, | ||
| 32 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 33 | __in SCA_WEB_ERROR** ppsweList, | ||
| 34 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 35 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 36 | __in WCA_WRAPQUERY_HANDLE hSslCertQuery, | ||
| 37 | __in WCA_WRAPQUERY_HANDLE hWebLogQuery, | ||
| 38 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 39 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 40 | __inout LPWSTR *ppwzCustomActionData | ||
| 41 | ) | ||
| 42 | { | ||
| 43 | Assert(ppswList); | ||
| 44 | WcaLog(LOGMSG_VERBOSE, "Entering ScaWebsRead7()"); | ||
| 45 | |||
| 46 | HRESULT hr = S_OK; | ||
| 47 | |||
| 48 | MSIHANDLE hRec; | ||
| 49 | MSIHANDLE hRecAddresses; | ||
| 50 | |||
| 51 | WCA_WRAPQUERY_HANDLE hQueryWebSite = NULL; | ||
| 52 | WCA_WRAPQUERY_HANDLE hQueryWebAddress = NULL; | ||
| 53 | |||
| 54 | SCA_WEB7* psw = NULL; | ||
| 55 | LPWSTR pwzData = NULL; | ||
| 56 | |||
| 57 | DWORD dwLen = 0; | ||
| 58 | errno_t error = EINVAL; | ||
| 59 | |||
| 60 | // check to see what tables are available | ||
| 61 | hr = WcaBeginUnwrapQuery(&hQueryWebSite, ppwzCustomActionData); | ||
| 62 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead"); | ||
| 63 | |||
| 64 | hr = WcaBeginUnwrapQuery(&hQueryWebAddress, ppwzCustomActionData); | ||
| 65 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead"); | ||
| 66 | |||
| 67 | |||
| 68 | if (0 == WcaGetQueryRecords(hQueryWebSite) || 0 == WcaGetQueryRecords(hQueryWebAddress)) | ||
| 69 | { | ||
| 70 | WcaLog(LOGMSG_VERBOSE, "Required tables not present"); | ||
| 71 | ExitFunction1(hr = S_FALSE); | ||
| 72 | } | ||
| 73 | |||
| 74 | // loop through all the webs | ||
| 75 | while (S_OK == (hr = WcaFetchWrappedRecord(hQueryWebSite, &hRec))) | ||
| 76 | { | ||
| 77 | psw = NewWeb7(); | ||
| 78 | if (!psw) | ||
| 79 | { | ||
| 80 | hr = E_OUTOFMEMORY; | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | |||
| 84 | // get the darwin information | ||
| 85 | hr = WcaGetRecordString(hRec, wqWeb, &pwzData); | ||
| 86 | ExitOnFailure(hr, "Failed to get Web"); | ||
| 87 | hr = ::StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData); | ||
| 88 | ExitOnFailure(hr, "Failed to copy key string to web object"); | ||
| 89 | |||
| 90 | // get component install state | ||
| 91 | hr = WcaGetRecordString(hRec, wqComponent, &pwzData); | ||
| 92 | ExitOnFailure(hr, "Failed to get Component for Web"); | ||
| 93 | hr = ::StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData); | ||
| 94 | ExitOnFailure(hr, "Failed to copy component string to web object"); | ||
| 95 | if (*(psw->wzComponent)) | ||
| 96 | { | ||
| 97 | psw->fHasComponent = TRUE; | ||
| 98 | |||
| 99 | hr = WcaGetRecordInteger(hRec, wqInstalled, (int *)&psw->isInstalled); | ||
| 100 | ExitOnFailure(hr, "Failed to get web Component's installed state"); | ||
| 101 | |||
| 102 | WcaGetRecordInteger(hRec, wqAction, (int *)&psw->isAction); | ||
| 103 | ExitOnFailure(hr, "Failed to get web Component's action state"); | ||
| 104 | } | ||
| 105 | |||
| 106 | // Get the web's description. | ||
| 107 | hr = WcaGetRecordString(hRec, wqDescription, &pwzData); | ||
| 108 | ExitOnFailure(hr, "Failed to get Description for Web"); | ||
| 109 | hr = ::StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData); | ||
| 110 | ExitOnFailure(hr, "Failed to copy description string to web object"); | ||
| 111 | |||
| 112 | //get web's site Id | ||
| 113 | hr = WcaGetRecordInteger(hRec, wqId, &psw->iSiteId); | ||
| 114 | ExitOnFailure(hr, "Failed to get SiteId for Web"); | ||
| 115 | |||
| 116 | // get the web's key address (Bindings) | ||
| 117 | hr = WcaGetRecordString(hRec, wqAddress, &pwzData); | ||
| 118 | ExitOnFailure(hr, "Failed to get Address for Web"); | ||
| 119 | hr = ::StringCchCopyW(psw->swaBinding.wzKey, countof(psw->swaBinding.wzKey), pwzData); | ||
| 120 | ExitOnFailure(hr, "Failed to copy web binding key"); | ||
| 121 | |||
| 122 | hr = WcaGetRecordString(hRec, wqIP, &pwzData); | ||
| 123 | ExitOnFailure(hr, "Failed to get IP for Web"); | ||
| 124 | hr = ::StringCchCopyW(psw->swaBinding.wzIP, countof(psw->swaBinding.wzIP), pwzData); | ||
| 125 | ExitOnFailure(hr, "Failed to copy web IP"); | ||
| 126 | |||
| 127 | hr = WcaGetRecordString(hRec, wqPort, &pwzData); | ||
| 128 | ExitOnFailure(hr, "Failed to get Web Address port"); | ||
| 129 | psw->swaBinding.iPort = wcstol(pwzData, NULL, 10); | ||
| 130 | |||
| 131 | hr = WcaGetRecordString(hRec, wqHeader, &pwzData); | ||
| 132 | ExitOnFailure(hr, "Failed to get Header for Web"); | ||
| 133 | hr = ::StringCchCopyW(psw->swaBinding.wzHeader, countof(psw->swaBinding.wzHeader), pwzData); | ||
| 134 | ExitOnFailure(hr, "Failed to copy web header"); | ||
| 135 | |||
| 136 | hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaBinding.fSecure); | ||
| 137 | ExitOnFailure(hr, "Failed to get if Web is secure"); | ||
| 138 | if (S_FALSE == hr) | ||
| 139 | { | ||
| 140 | psw->swaBinding.fSecure = FALSE; | ||
| 141 | } | ||
| 142 | |||
| 143 | // look to see if site exists | ||
| 144 | dwLen = METADATA_MAX_NAME_LEN; | ||
| 145 | hr = ScaWebFindBase7(*ppswList, psw->wzDescription); | ||
| 146 | |||
| 147 | // If we didn't find a web in memory, ignore it - during execute CA | ||
| 148 | // if the site truly does not exist then there will be an error. | ||
| 149 | if (S_OK == hr) | ||
| 150 | { | ||
| 151 | // site exists in config | ||
| 152 | psw->fBaseExists = TRUE; | ||
| 153 | } | ||
| 154 | else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
| 155 | { | ||
| 156 | hr = S_OK; | ||
| 157 | |||
| 158 | // site does not exists in config | ||
| 159 | psw->fBaseExists = FALSE; | ||
| 160 | } | ||
| 161 | ExitOnFailure(hr, "Failed to find web site"); | ||
| 162 | |||
| 163 | // get any extra web addresses | ||
| 164 | WcaFetchWrappedReset(hQueryWebAddress); | ||
| 165 | |||
| 166 | while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hQueryWebAddress, 2, psw->wzKey, &hRecAddresses))) | ||
| 167 | { | ||
| 168 | if (MAX_ADDRESSES_PER_WEB <= psw->cExtraAddresses) | ||
| 169 | { | ||
| 170 | hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); | ||
| 171 | ExitOnFailure(hr, "Failure to get more extra web addresses, max exceeded."); | ||
| 172 | } | ||
| 173 | |||
| 174 | hr = WcaGetRecordString(hRecAddresses, waqAddress, &pwzData); | ||
| 175 | ExitOnFailure(hr, "Failed to get extra web Address"); | ||
| 176 | |||
| 177 | // if this isn't the key address add it | ||
| 178 | if (0 != lstrcmpW(pwzData, psw->swaBinding.wzKey)) | ||
| 179 | { | ||
| 180 | hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey, | ||
| 181 | countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData); | ||
| 182 | ExitOnFailure(hr, "Failed to copy web binding key"); | ||
| 183 | |||
| 184 | hr = WcaGetRecordString(hRecAddresses, waqIP, &pwzData); | ||
| 185 | ExitOnFailure(hr, "Failed to get extra web IP"); | ||
| 186 | hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData); | ||
| 187 | ExitOnFailure(hr, "Failed to copy web binding IP"); | ||
| 188 | |||
| 189 | hr = WcaGetRecordString(hRecAddresses, waqPort, &pwzData); | ||
| 190 | ExitOnFailure(hr, "Failed to get port for extra web IP"); | ||
| 191 | psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10); | ||
| 192 | |||
| 193 | // errno is set to ERANGE if overflow or underflow occurs | ||
| 194 | _get_errno(&error); | ||
| 195 | |||
| 196 | if (ERANGE == error) | ||
| 197 | { | ||
| 198 | hr = E_INVALIDARG; | ||
| 199 | ExitOnFailure(hr, "Failed to convert web Port address"); | ||
| 200 | } | ||
| 201 | |||
| 202 | hr = WcaGetRecordString(hRecAddresses, waqHeader, &pwzData); | ||
| 203 | ExitOnFailure(hr, "Failed to get header for extra web IP"); | ||
| 204 | hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData); | ||
| 205 | ExitOnFailure(hr, "Failed to copy web binding header"); | ||
| 206 | |||
| 207 | hr = WcaGetRecordInteger(hRecAddresses, waqSecure, &psw->swaExtraAddresses[psw->cExtraAddresses].fSecure); | ||
| 208 | ExitOnFailure(hr, "Failed to get if secure extra web IP"); | ||
| 209 | if (S_FALSE == hr) | ||
| 210 | { | ||
| 211 | psw->swaExtraAddresses[psw->cExtraAddresses].fSecure = FALSE; | ||
| 212 | } | ||
| 213 | |||
| 214 | ++psw->cExtraAddresses; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | if (E_NOMOREITEMS == hr) | ||
| 219 | { | ||
| 220 | hr = S_OK; | ||
| 221 | } | ||
| 222 | ExitOnFailure(hr, "Failure occured while getting extra web addresses"); | ||
| 223 | |||
| 224 | // | ||
| 225 | // Connection time out | ||
| 226 | // | ||
| 227 | hr = WcaGetRecordInteger(hRec, wqConnectionTimeout, &psw->iConnectionTimeout); | ||
| 228 | ExitOnFailure(hr, "Failed to get connection timeout for Web"); | ||
| 229 | |||
| 230 | if (psw->fHasComponent) // If we're installing it, it needs a dir | ||
| 231 | { | ||
| 232 | // get the web's directory | ||
| 233 | if (INSTALLSTATE_SOURCE == psw->isAction) | ||
| 234 | { | ||
| 235 | hr = WcaGetRecordString(hRec, wqSourcePath, &pwzData); | ||
| 236 | } | ||
| 237 | else | ||
| 238 | { | ||
| 239 | hr = WcaGetRecordString(hRec, wqTargetPath, &pwzData); | ||
| 240 | } | ||
| 241 | ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); | ||
| 242 | |||
| 243 | dwLen = lstrlenW(pwzData); | ||
| 244 | // remove trailing backslash | ||
| 245 | if (dwLen > 0 && pwzData[dwLen-1] == L'\\') | ||
| 246 | { | ||
| 247 | pwzData[dwLen-1] = 0; | ||
| 248 | } | ||
| 249 | hr = ::StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), pwzData); | ||
| 250 | ExitOnFailure(hr, "Failed to copy web dir: '%ls'", pwzData); | ||
| 251 | |||
| 252 | } | ||
| 253 | |||
| 254 | hr = WcaGetRecordInteger(hRec, wqState, &psw->iState); | ||
| 255 | ExitOnFailure(hr, "Failed to get state for Web"); | ||
| 256 | |||
| 257 | hr = WcaGetRecordInteger(hRec, wqAttributes, &psw->iAttributes); | ||
| 258 | ExitOnFailure(hr, "Failed to get attributes for Web"); | ||
| 259 | |||
| 260 | // get the dir properties for this web | ||
| 261 | hr = WcaGetRecordString(hRec, wqProperties, &pwzData); | ||
| 262 | ExitOnFailure(hr, "Failed to get directory properties for Web"); | ||
| 263 | if (*pwzData) | ||
| 264 | { | ||
| 265 | hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &psw->swp); | ||
| 266 | ExitOnFailure(hr, "Failed to get directory properties for Web"); | ||
| 267 | |||
| 268 | psw->fHasProperties = TRUE; | ||
| 269 | } | ||
| 270 | |||
| 271 | // get the application information for this web | ||
| 272 | hr = WcaGetRecordString(hRec, wqApplication, &pwzData); | ||
| 273 | ExitOnFailure(hr, "Failed to get application identifier for Web"); | ||
| 274 | if (*pwzData) | ||
| 275 | { | ||
| 276 | hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &psw->swapp); | ||
| 277 | ExitOnFailure(hr, "Failed to get application for Web"); | ||
| 278 | |||
| 279 | psw->fHasApplication = TRUE; | ||
| 280 | } | ||
| 281 | |||
| 282 | // get the SSL certificates | ||
| 283 | hr = ScaSslCertificateRead(psw->wzKey, hSslCertQuery, &(psw->pswscList)); | ||
| 284 | ExitOnFailure(hr, "Failed to get SSL Certificates."); | ||
| 285 | |||
| 286 | // get the custom headers | ||
| 287 | if (*ppshhList) | ||
| 288 | { | ||
| 289 | hr = ScaGetHttpHeader(hhptWeb, psw->wzKey, ppshhList, &(psw->pshhList)); | ||
| 290 | ExitOnFailure(hr, "Failed to get Custom HTTP Headers"); | ||
| 291 | } | ||
| 292 | |||
| 293 | // get the errors | ||
| 294 | if (*ppsweList) | ||
| 295 | { | ||
| 296 | hr = ScaGetWebError(weptWeb, psw->wzKey, ppsweList, &(psw->psweList)); | ||
| 297 | ExitOnFailure(hr, "Failed to get Custom Errors"); | ||
| 298 | } | ||
| 299 | |||
| 300 | // get the log information for this web | ||
| 301 | hr = WcaGetRecordString(hRec, wqLog, &pwzData); | ||
| 302 | ExitOnFailure(hr, "Failed to get log identifier for Web"); | ||
| 303 | if (*pwzData) | ||
| 304 | { | ||
| 305 | hr = ScaGetWebLog7(pwzData, hWebLogQuery, &psw->swl); | ||
| 306 | ExitOnFailure(hr, "Failed to get Log for Web."); | ||
| 307 | psw->fHasLog = TRUE; | ||
| 308 | } | ||
| 309 | |||
| 310 | *ppswList = AddWebToList7(*ppswList, psw); | ||
| 311 | psw = NULL; // set the web NULL so it doesn't accidentally get freed below | ||
| 312 | } | ||
| 313 | |||
| 314 | if (E_NOMOREITEMS == hr) | ||
| 315 | { | ||
| 316 | hr = S_OK; | ||
| 317 | } | ||
| 318 | |||
| 319 | LExit: | ||
| 320 | // if anything was left over after an error clean it all up | ||
| 321 | WcaFinishUnwrapQuery(hQueryWebSite); | ||
| 322 | WcaFinishUnwrapQuery(hQueryWebAddress); | ||
| 323 | |||
| 324 | ScaWebsFreeList7(psw); | ||
| 325 | |||
| 326 | ReleaseStr(pwzData); | ||
| 327 | WcaLog(LOGMSG_VERBOSE, "Exiting ScaWebsRead7()"); | ||
| 328 | |||
| 329 | return hr; | ||
| 330 | } | ||
| 331 | |||
| 332 | BOOL CompareBinding( | ||
| 333 | __in IAppHostElement* pBinding, | ||
| 334 | __in LPVOID pContext | ||
| 335 | ) | ||
| 336 | { | ||
| 337 | BOOL fFound = FALSE; | ||
| 338 | HRESULT hr = S_OK; | ||
| 339 | LPWSTR pwzBindingInfo = NULL; | ||
| 340 | SCA_WEB7* psw = (SCA_WEB7*)pContext; | ||
| 341 | |||
| 342 | hr = Iis7GetPropertyString(pBinding, IIS_CONFIG_BINDINGINFO, &pwzBindingInfo); | ||
| 343 | ExitOnFailure(hr, "Failed to get bindinginfo for binding element"); | ||
| 344 | |||
| 345 | LPWSTR pwzExists = pwzBindingInfo; | ||
| 346 | // Break down the address into its constituent parts (IP:Port:Header). | ||
| 347 | // Taken from IIS6 CA code for compatibility | ||
| 348 | while (S_OK == hr && *pwzExists) | ||
| 349 | { | ||
| 350 | LPCWSTR pwzIPExists = pwzExists; | ||
| 351 | pwzExists = const_cast<LPWSTR>(wcsstr(pwzIPExists, L":")); | ||
| 352 | if (NULL == pwzExists) | ||
| 353 | { | ||
| 354 | ExitFunction(); | ||
| 355 | } | ||
| 356 | *pwzExists = L'\0'; | ||
| 357 | |||
| 358 | LPCWSTR pwzPortExists = pwzExists + 1; | ||
| 359 | pwzExists = const_cast<LPWSTR>(wcsstr(pwzPortExists, L":")); | ||
| 360 | if (NULL == pwzExists) | ||
| 361 | { | ||
| 362 | ExitFunction(); | ||
| 363 | } | ||
| 364 | *pwzExists = L'\0'; | ||
| 365 | int iPortExists = wcstol(pwzPortExists, NULL, 10); | ||
| 366 | |||
| 367 | LPCWSTR pwzHeaderExists = pwzExists + 1; | ||
| 368 | |||
| 369 | BOOL fIpMatches = (0 == lstrcmpW(psw->swaBinding.wzIP, pwzIPExists)); // Explicit IP match | ||
| 370 | fIpMatches |= (0 == lstrcmpW(psw->swaBinding.wzIP, L"*")); // Authored * matches any IP | ||
| 371 | fIpMatches |= ('\0' != psw->swaBinding.wzIP) && // Unauthored IP | ||
| 372 | (0 == lstrcmpW(pwzIPExists, L"*")); // matches the All Unassigned IP : '*' | ||
| 373 | |||
| 374 | // compare the passed in address with the address listed for this web | ||
| 375 | if (fIpMatches && psw->swaBinding.iPort == iPortExists && | ||
| 376 | 0 == lstrcmpW(psw->swaBinding.wzHeader, pwzHeaderExists)) | ||
| 377 | { | ||
| 378 | fFound = TRUE; | ||
| 379 | break; | ||
| 380 | } | ||
| 381 | |||
| 382 | // move to the next block of data, this may move beyond the available | ||
| 383 | // data and exit the while loop above. | ||
| 384 | pwzExists = const_cast<LPWSTR>(pwzHeaderExists + lstrlenW(pwzHeaderExists)); | ||
| 385 | } | ||
| 386 | |||
| 387 | LExit: | ||
| 388 | WcaLog(LOGMSG_VERBOSE, "Site with binding %ls %s a match", pwzBindingInfo, fFound ? "is" : "is not"); | ||
| 389 | ReleaseNullStr(pwzBindingInfo); | ||
| 390 | return fFound; | ||
| 391 | } | ||
| 392 | |||
| 393 | BOOL EnumSiteCompareBinding( | ||
| 394 | __in IAppHostElement* pSite, | ||
| 395 | __in LPVOID pContext | ||
| 396 | ) | ||
| 397 | { | ||
| 398 | BOOL fFound = FALSE; | ||
| 399 | HRESULT hr = S_OK; | ||
| 400 | SCA_WEB7* psw = (SCA_WEB7*)pContext; | ||
| 401 | IAppHostChildElementCollection *pSiteChildren = NULL; | ||
| 402 | IAppHostElement *pBindings = NULL; | ||
| 403 | IAppHostElementCollection *pBindingsCollection = NULL; | ||
| 404 | IAppHostElement *pBinding = NULL; | ||
| 405 | VARIANT vtProp; | ||
| 406 | VariantInit(&vtProp); | ||
| 407 | |||
| 408 | hr = pSite->get_ChildElements(&pSiteChildren); | ||
| 409 | ExitOnFailure(hr, "Failed get site child elements collection"); | ||
| 410 | |||
| 411 | vtProp.vt = VT_BSTR; | ||
| 412 | vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS); | ||
| 413 | hr = pSiteChildren->get_Item(vtProp, &pBindings); | ||
| 414 | ExitOnFailure(hr, "Failed get bindings element"); | ||
| 415 | |||
| 416 | hr = pBindings->get_Collection(&pBindingsCollection); | ||
| 417 | ExitOnFailure(hr, "Failed get bindings collection"); | ||
| 418 | |||
| 419 | WcaLog(LOGMSG_VERBOSE, "Searching for site with binding %ls:%d:%ls", psw->swaBinding.wzIP, psw->swaBinding.iPort, psw->swaBinding.wzHeader); | ||
| 420 | |||
| 421 | hr = Iis7EnumAppHostElements(pBindingsCollection, CompareBinding, psw, &pBinding, NULL); | ||
| 422 | ExitOnFailure(hr, "Failed search bindings collection"); | ||
| 423 | |||
| 424 | fFound = NULL != pBinding; | ||
| 425 | LExit: | ||
| 426 | VariantClear(&vtProp); | ||
| 427 | ReleaseNullObject(pSiteChildren); | ||
| 428 | ReleaseNullObject(pBindings); | ||
| 429 | ReleaseNullObject(pBindingsCollection); | ||
| 430 | ReleaseNullObject(pBinding); | ||
| 431 | return fFound; | ||
| 432 | } | ||
| 433 | |||
| 434 | HRESULT ScaWebSearch7( | ||
| 435 | __in SCA_WEB7* psw, | ||
| 436 | __deref_out_z_opt LPWSTR* pswWeb, | ||
| 437 | __out_opt BOOL* pfFound | ||
| 438 | ) | ||
| 439 | { | ||
| 440 | HRESULT hr = S_OK; | ||
| 441 | BOOL fInitializedCom = FALSE; | ||
| 442 | BSTR bstrSites = NULL; | ||
| 443 | BSTR bstrAppHostRoot = NULL; | ||
| 444 | IAppHostAdminManager *pAdminMgr = NULL; | ||
| 445 | IAppHostElement *pSites = NULL; | ||
| 446 | IAppHostElementCollection *pCollection = NULL; | ||
| 447 | IAppHostElement *pSite = NULL; | ||
| 448 | |||
| 449 | if (NULL != pswWeb) | ||
| 450 | { | ||
| 451 | ReleaseNullStr(*pswWeb); | ||
| 452 | } | ||
| 453 | |||
| 454 | if (NULL != pfFound) | ||
| 455 | { | ||
| 456 | *pfFound = FALSE; | ||
| 457 | } | ||
| 458 | |||
| 459 | hr = ::CoInitialize(NULL); | ||
| 460 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
| 461 | fInitializedCom = TRUE; | ||
| 462 | |||
| 463 | hr = CoCreateInstance(__uuidof(AppHostAdminManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(IAppHostAdminManager), reinterpret_cast<void**> (&pAdminMgr)); | ||
| 464 | if (REGDB_E_CLASSNOTREG == hr) | ||
| 465 | { | ||
| 466 | WcaLog(LOGMSG_VERBOSE, "AppHostAdminManager was not registered, cannot find site."); | ||
| 467 | hr = S_OK; | ||
| 468 | ExitFunction(); | ||
| 469 | } | ||
| 470 | ExitOnFailure(hr, "Failed to CoCreate IAppHostAdminManager"); | ||
| 471 | |||
| 472 | bstrSites = ::SysAllocString(IIS_CONFIG_SITES_SECTION); | ||
| 473 | ExitOnNull(bstrSites, hr, E_OUTOFMEMORY, "Failed to allocate sites string."); | ||
| 474 | |||
| 475 | bstrAppHostRoot = ::SysAllocString(IIS_CONFIG_APPHOST_ROOT); | ||
| 476 | ExitOnNull(bstrAppHostRoot, hr, E_OUTOFMEMORY, "Failed to allocate host root string."); | ||
| 477 | |||
| 478 | hr = pAdminMgr->GetAdminSection(bstrSites, bstrAppHostRoot, &pSites); | ||
| 479 | ExitOnFailure(hr, "Failed get sites section"); | ||
| 480 | ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object"); | ||
| 481 | |||
| 482 | hr = pSites->get_Collection(&pCollection); | ||
| 483 | ExitOnFailure(hr, "Failed get sites collection"); | ||
| 484 | |||
| 485 | // not explicitly doing a Description search | ||
| 486 | if (-1 != psw->iSiteId) | ||
| 487 | { | ||
| 488 | if (MSI_NULL_INTEGER == psw->iSiteId) | ||
| 489 | { | ||
| 490 | // Enumerate sites & determine if the binding matches | ||
| 491 | hr = Iis7EnumAppHostElements(pCollection, EnumSiteCompareBinding, psw, &pSite, NULL); | ||
| 492 | ExitOnFailure(hr, "Failed locate site by ID"); | ||
| 493 | } | ||
| 494 | else | ||
| 495 | { | ||
| 496 | // Find a site with ID matches | ||
| 497 | hr = Iis7FindAppHostElementInteger(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_ID, psw->iSiteId, &pSite, NULL); | ||
| 498 | ExitOnFailure(hr, "Failed locate site by ID"); | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | if (NULL == pSite) | ||
| 503 | { | ||
| 504 | // Find a site with Name that matches | ||
| 505 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, psw->wzDescription, &pSite, NULL); | ||
| 506 | ExitOnFailure(hr, "Failed locate site by ID"); | ||
| 507 | } | ||
| 508 | |||
| 509 | if (NULL != pSite) | ||
| 510 | { | ||
| 511 | if (NULL != pfFound) | ||
| 512 | { | ||
| 513 | *pfFound = TRUE; | ||
| 514 | } | ||
| 515 | |||
| 516 | if (NULL != pswWeb) | ||
| 517 | { | ||
| 518 | // We found a site, return its description | ||
| 519 | hr = Iis7GetPropertyString(pSite, IIS_CONFIG_NAME, pswWeb); | ||
| 520 | ExitOnFailure(hr, "Failed get site name"); | ||
| 521 | } | ||
| 522 | } | ||
| 523 | LExit: | ||
| 524 | ReleaseNullObject(pAdminMgr); | ||
| 525 | ReleaseNullObject(pSites); | ||
| 526 | ReleaseNullObject(pCollection); | ||
| 527 | ReleaseNullObject(pSite); | ||
| 528 | ReleaseBSTR(bstrAppHostRoot); | ||
| 529 | ReleaseBSTR(bstrSites); | ||
| 530 | |||
| 531 | if (fInitializedCom) | ||
| 532 | { | ||
| 533 | ::CoUninitialize(); | ||
| 534 | } | ||
| 535 | return hr; | ||
| 536 | } | ||
| 537 | |||
| 538 | |||
| 539 | HRESULT ScaWebsGetBase7( | ||
| 540 | __in SCA_WEB7* pswList, | ||
| 541 | __in LPCWSTR pswWebKey, | ||
| 542 | __out_ecount(cchDest) LPWSTR pswWeb, | ||
| 543 | __in DWORD_PTR cchDest | ||
| 544 | ) | ||
| 545 | { | ||
| 546 | HRESULT hr = S_OK; | ||
| 547 | BOOL fFound = FALSE; | ||
| 548 | SCA_WEB7* psw = pswList; | ||
| 549 | LPWSTR wzSiteName = NULL; | ||
| 550 | |||
| 551 | *pswWeb = '/0'; | ||
| 552 | |||
| 553 | //looking for psw->wzKey == pswWebKey | ||
| 554 | while(psw) | ||
| 555 | { | ||
| 556 | if (0 == wcscmp(pswWebKey, psw->wzKey)) | ||
| 557 | { | ||
| 558 | fFound = TRUE; | ||
| 559 | break; | ||
| 560 | } | ||
| 561 | psw = psw->pswNext; | ||
| 562 | } | ||
| 563 | |||
| 564 | if (!fFound) | ||
| 565 | { | ||
| 566 | ExitFunction1(hr = S_FALSE); | ||
| 567 | } | ||
| 568 | |||
| 569 | // Search if we're not installing the site | ||
| 570 | if (!psw->fHasComponent || (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS)) | ||
| 571 | { | ||
| 572 | // We are not installing this website. Search for it in IIS config | ||
| 573 | hr = ScaWebSearch7(psw, &wzSiteName, NULL); | ||
| 574 | ExitOnFailure(hr, "Failed to search for Website"); | ||
| 575 | |||
| 576 | if (NULL != wzSiteName) | ||
| 577 | { | ||
| 578 | hr = ::StringCchCopyW(pswWeb, cchDest, wzSiteName); | ||
| 579 | ExitOnFailure(hr, "Failed to set Website description for located Website"); | ||
| 580 | } | ||
| 581 | } | ||
| 582 | |||
| 583 | if ('/0' == *pswWeb) | ||
| 584 | { | ||
| 585 | WcaLog(LOGMSG_VERBOSE, "Could not find Web: %ls, defaulting to %ls", psw->wzKey, psw->wzDescription); | ||
| 586 | // Default to the provided description, the Exec CA will locate by description | ||
| 587 | hr = ::StringCchCopyW(pswWeb, cchDest, psw->wzDescription); | ||
| 588 | ExitOnFailure(hr, "Failed to set Website description to default"); | ||
| 589 | } | ||
| 590 | LExit: | ||
| 591 | ReleaseNullStr(wzSiteName); | ||
| 592 | return hr; | ||
| 593 | } | ||
| 594 | |||
| 595 | HRESULT ScaWebsInstall7( | ||
| 596 | __in SCA_WEB7* pswList, | ||
| 597 | __in SCA_APPPOOL * psapList | ||
| 598 | ) | ||
| 599 | { | ||
| 600 | HRESULT hr = S_OK; | ||
| 601 | SCA_WEB7* psw = pswList; | ||
| 602 | |||
| 603 | while (psw) | ||
| 604 | { | ||
| 605 | // if we are installing the web site | ||
| 606 | if (psw->fHasComponent && WcaIsInstalling(psw->isInstalled, psw->isAction)) | ||
| 607 | { | ||
| 608 | hr = ScaWebWrite7(psw, psapList); | ||
| 609 | ExitOnFailure(hr, "failed to write web '%ls' to metabase", psw->wzKey); | ||
| 610 | } | ||
| 611 | |||
| 612 | psw = psw->pswNext; | ||
| 613 | } | ||
| 614 | |||
| 615 | LExit: | ||
| 616 | return hr; | ||
| 617 | } | ||
| 618 | |||
| 619 | |||
| 620 | HRESULT ScaWebsUninstall7( | ||
| 621 | __in SCA_WEB7* pswList | ||
| 622 | ) | ||
| 623 | { | ||
| 624 | HRESULT hr = S_OK; | ||
| 625 | SCA_WEB7* psw = pswList; | ||
| 626 | |||
| 627 | while (psw) | ||
| 628 | { | ||
| 629 | if (psw->fHasComponent && WcaIsUninstalling(psw->isInstalled, psw->isAction)) | ||
| 630 | { | ||
| 631 | // If someone | ||
| 632 | hr = ScaWebRemove7(psw); | ||
| 633 | ExitOnFailure(hr, "Failed to remove web '%ls' ", psw->wzKey); | ||
| 634 | } | ||
| 635 | |||
| 636 | psw = psw->pswNext; | ||
| 637 | } | ||
| 638 | |||
| 639 | LExit: | ||
| 640 | return hr; | ||
| 641 | } | ||
| 642 | |||
| 643 | |||
| 644 | void ScaWebsFreeList7(__in SCA_WEB7* pswList) | ||
| 645 | { | ||
| 646 | SCA_WEB7* pswDelete = pswList; | ||
| 647 | while (pswList) | ||
| 648 | { | ||
| 649 | pswDelete = pswList; | ||
| 650 | pswList = pswList->pswNext; | ||
| 651 | |||
| 652 | // Free the SSL, headers and errors list first | ||
| 653 | ScaSslCertificateFreeList(pswDelete->pswscList); | ||
| 654 | ScaHttpHeaderFreeList(pswDelete->pshhList); | ||
| 655 | ScaWebErrorFreeList(pswDelete->psweList); | ||
| 656 | |||
| 657 | MemFree(pswDelete); | ||
| 658 | } | ||
| 659 | } | ||
| 660 | |||
| 661 | |||
| 662 | // private helper functions | ||
| 663 | |||
| 664 | static SCA_WEB7* NewWeb7() | ||
| 665 | { | ||
| 666 | SCA_WEB7* psw = (SCA_WEB7*)MemAlloc(sizeof(SCA_WEB7), TRUE); | ||
| 667 | Assert(psw); | ||
| 668 | return psw; | ||
| 669 | } | ||
| 670 | |||
| 671 | |||
| 672 | static SCA_WEB7* AddWebToList7( | ||
| 673 | __in SCA_WEB7* pswList, | ||
| 674 | __in SCA_WEB7* psw | ||
| 675 | ) | ||
| 676 | { | ||
| 677 | if (pswList) | ||
| 678 | { | ||
| 679 | SCA_WEB7* pswTemp = pswList; | ||
| 680 | while (pswTemp->pswNext) | ||
| 681 | { | ||
| 682 | pswTemp = pswTemp->pswNext; | ||
| 683 | } | ||
| 684 | |||
| 685 | pswTemp->pswNext = psw; | ||
| 686 | } | ||
| 687 | else | ||
| 688 | { | ||
| 689 | pswList = psw; | ||
| 690 | } | ||
| 691 | |||
| 692 | return pswList; | ||
| 693 | } | ||
| 694 | |||
| 695 | |||
| 696 | static HRESULT ScaWebFindBase7( | ||
| 697 | __in SCA_WEB7* pswList, | ||
| 698 | __in_z LPCWSTR wzDescription | ||
| 699 | ) | ||
| 700 | { | ||
| 701 | HRESULT hr = S_OK; | ||
| 702 | BOOL fFound = FALSE; | ||
| 703 | |||
| 704 | // try to find the web in memory first | ||
| 705 | for (SCA_WEB7* psw = pswList; psw; psw = psw->pswNext) | ||
| 706 | { | ||
| 707 | if (0 == wcscmp(wzDescription, psw->wzDescription)) | ||
| 708 | { | ||
| 709 | fFound = TRUE; | ||
| 710 | break; | ||
| 711 | } | ||
| 712 | } | ||
| 713 | |||
| 714 | if (!fFound) | ||
| 715 | { | ||
| 716 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
| 717 | } | ||
| 718 | |||
| 719 | return hr; | ||
| 720 | } | ||
| 721 | |||
| 722 | |||
| 723 | static HRESULT ScaWebWrite7( | ||
| 724 | __in SCA_WEB7* psw, | ||
| 725 | __in SCA_APPPOOL * psapList | ||
| 726 | ) | ||
| 727 | { | ||
| 728 | HRESULT hr = S_OK; | ||
| 729 | |||
| 730 | BOOL fExists = FALSE; | ||
| 731 | UINT ui = 0; | ||
| 732 | WCHAR wzIP[64]; | ||
| 733 | WCHAR wzBinding[1024]; | ||
| 734 | WCHAR wzAppPoolName[MAX_PATH]; | ||
| 735 | |||
| 736 | // | ||
| 737 | // determine if site must be new | ||
| 738 | // | ||
| 739 | if (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS) | ||
| 740 | { | ||
| 741 | // Check if site already exists. | ||
| 742 | hr = ScaWebSearch7(psw, NULL, &fExists); | ||
| 743 | ExitOnFailure(hr, "Failed to search for web: %ls", psw->wzKey); | ||
| 744 | |||
| 745 | if (fExists) | ||
| 746 | { | ||
| 747 | hr = S_FALSE; | ||
| 748 | WcaLog(LOGMSG_VERBOSE, "Skipping configuration of existing web: %ls", psw->wzKey); | ||
| 749 | ExitFunction(); | ||
| 750 | } | ||
| 751 | } | ||
| 752 | |||
| 753 | //create a site | ||
| 754 | hr = ScaWriteConfigID(IIS_SITE); | ||
| 755 | ExitOnFailure(hr, "Failed write site ID"); | ||
| 756 | |||
| 757 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 758 | ExitOnFailure(hr, "Failed write site ID create action"); | ||
| 759 | |||
| 760 | //Site Name | ||
| 761 | hr = ScaWriteConfigString(psw->wzDescription); //Site Name | ||
| 762 | ExitOnFailure(hr, "Failed write site desc"); | ||
| 763 | |||
| 764 | //Site Id -- value is MSI_NULL_INTEGER if not set in WIX | ||
| 765 | hr = ScaWriteConfigInteger(psw->iSiteId); //SiteID | ||
| 766 | ExitOnFailure(hr, "Failed write site id value"); | ||
| 767 | |||
| 768 | //Site Auto Start -- value is MSI_NULL_INTEGER if not set in WIX | ||
| 769 | hr = ScaWriteConfigInteger(psw->iState); // serverAutoStart | ||
| 770 | ExitOnFailure(hr, "Failed write site autostart"); | ||
| 771 | |||
| 772 | hr = ScaWriteConfigInteger(psw->iConnectionTimeout); //limits/connectionTimeout | ||
| 773 | ExitOnFailure(hr, "Failed write site timeout"); | ||
| 774 | |||
| 775 | //create default application | ||
| 776 | hr = ScaWriteConfigID(IIS_APPLICATION); | ||
| 777 | ExitOnFailure(hr, "Failed write app ID"); | ||
| 778 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 779 | ExitOnFailure(hr, "Failed write app action ID"); | ||
| 780 | hr = ScaWriteConfigString(psw->wzDescription); //site name key | ||
| 781 | ExitOnFailure(hr, "Failed write app desc"); | ||
| 782 | hr = ScaWriteConfigString(L"/"); // App Path (default) | ||
| 783 | ExitOnFailure(hr, "Failed write app def path /"); | ||
| 784 | |||
| 785 | if (psw->fHasApplication && *psw->swapp.wzAppPool) | ||
| 786 | { | ||
| 787 | hr = ScaFindAppPool7(psw->swapp.wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList); | ||
| 788 | ExitOnFailure(hr, "Failed to read app pool from application"); | ||
| 789 | |||
| 790 | hr = ScaWriteConfigString(wzAppPoolName); | ||
| 791 | ExitOnFailure(hr, "Failed write app appPool"); | ||
| 792 | } | ||
| 793 | else | ||
| 794 | { | ||
| 795 | hr = ScaWriteConfigString(L""); | ||
| 796 | ExitOnFailure(hr, "Failed write app appPool"); | ||
| 797 | } | ||
| 798 | |||
| 799 | //create vdir for default application | ||
| 800 | hr = ScaWriteConfigID(IIS_VDIR); | ||
| 801 | ExitOnFailure(hr, "Failed write vdir ID"); | ||
| 802 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 803 | ExitOnFailure(hr, "Failed write vdir action"); | ||
| 804 | hr = ScaWriteConfigString(psw->wzDescription); //site name key | ||
| 805 | ExitOnFailure(hr, "Failed write vdir desc"); | ||
| 806 | hr = ScaWriteConfigString(L"/"); //vdir path (default) | ||
| 807 | ExitOnFailure(hr, "Failed write vdir app"); | ||
| 808 | hr = ScaWriteConfigString(psw->wzDirectory); //physical dir | ||
| 809 | ExitOnFailure(hr, "Failed write vdir dir"); | ||
| 810 | |||
| 811 | //create bindings for site | ||
| 812 | hr = ScaWriteConfigID(IIS_BINDING); | ||
| 813 | ExitOnFailure(hr, "Failed write binding ID"); | ||
| 814 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 815 | ExitOnFailure(hr, "Failed write binding action ID"); | ||
| 816 | hr = ScaWriteConfigString(psw->wzDescription); //site name key | ||
| 817 | ExitOnFailure(hr, "Failed write binding site key"); | ||
| 818 | |||
| 819 | if (psw->swaBinding.fSecure) | ||
| 820 | { | ||
| 821 | hr = ScaWriteConfigString(L"https"); // binding protocol | ||
| 822 | ExitOnFailure(hr, "Failed write binding https"); | ||
| 823 | } | ||
| 824 | else | ||
| 825 | { | ||
| 826 | hr = ScaWriteConfigString(L"http"); // binding protocol | ||
| 827 | ExitOnFailure(hr, "Failed write binding http"); | ||
| 828 | } | ||
| 829 | |||
| 830 | // set the IP address appropriately | ||
| 831 | if (0 == wcscmp(psw->swaBinding.wzIP, L"")) | ||
| 832 | { | ||
| 833 | hr = ::StringCchCopyW(wzIP, countof(wzIP), L"*"); // if no IP specified = add * | ||
| 834 | } | ||
| 835 | else | ||
| 836 | { | ||
| 837 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 838 | hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaBinding.wzIP); // else leave untouched | ||
| 839 | } | ||
| 840 | ExitOnFailure(hr, "Failed to copy IP string"); | ||
| 841 | |||
| 842 | hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaBinding.iPort, psw->swaBinding.wzHeader); | ||
| 843 | ExitOnFailure(hr, "Failed to format IP:Port:Header binding string"); | ||
| 844 | |||
| 845 | // write bindings CAData | ||
| 846 | hr = ScaWriteConfigString(wzBinding) ; //binding info | ||
| 847 | ExitOnFailure(hr, "Failed to create web bindings"); | ||
| 848 | |||
| 849 | for (ui = 0; (ui < MAX_ADDRESSES_PER_WEB) && (ui < psw->cExtraAddresses); ++ui) | ||
| 850 | { | ||
| 851 | // set the IP address appropriately | ||
| 852 | if (0 == wcscmp(psw->swaExtraAddresses[ui].wzIP, L"")) | ||
| 853 | { | ||
| 854 | hr = ::StringCchCopyW(wzIP, countof(wzIP), L"*"); // if no IP specified = add * | ||
| 855 | } | ||
| 856 | else | ||
| 857 | { | ||
| 858 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 859 | hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaExtraAddresses[ui].wzIP); //else leave untouched | ||
| 860 | } | ||
| 861 | ExitOnFailure(hr, "Failed to copy web IP string"); | ||
| 862 | |||
| 863 | hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaExtraAddresses[ui].iPort, psw->swaExtraAddresses[ui].wzHeader); | ||
| 864 | ExitOnFailure(hr, "Failed to copy web IP"); | ||
| 865 | |||
| 866 | //create bindings for site | ||
| 867 | hr = ScaWriteConfigID(IIS_BINDING); | ||
| 868 | ExitOnFailure(hr, "Failed write binding ID"); | ||
| 869 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 870 | ExitOnFailure(hr, "Failed write binding action"); | ||
| 871 | hr = ScaWriteConfigString(psw->wzDescription); //site name key | ||
| 872 | ExitOnFailure(hr, "Failed write binding web name"); | ||
| 873 | |||
| 874 | if (psw->swaExtraAddresses[ui].fSecure) | ||
| 875 | { | ||
| 876 | hr = ScaWriteConfigString(L"https"); // binding protocol | ||
| 877 | } | ||
| 878 | else | ||
| 879 | { | ||
| 880 | hr = ScaWriteConfigString(L"http"); // binding protocol | ||
| 881 | } | ||
| 882 | ExitOnFailure(hr, "Failed write binding http(s)"); | ||
| 883 | |||
| 884 | // write bindings CAData | ||
| 885 | hr = ScaWriteConfigString(wzBinding) ; //binding info | ||
| 886 | ExitOnFailure(hr, "Failed write binding info"); | ||
| 887 | } | ||
| 888 | |||
| 889 | // write the web dirproperties information | ||
| 890 | if (psw->fHasProperties) | ||
| 891 | { | ||
| 892 | // dir properties are for the default application of the web | ||
| 893 | // with location '/' | ||
| 894 | hr = ScaWriteWebDirProperties7(psw->wzDescription, L"/", &psw->swp); | ||
| 895 | ExitOnFailure(hr, "Failed to write web security information to metabase"); | ||
| 896 | } | ||
| 897 | |||
| 898 | //// write the application information | ||
| 899 | if (psw->fHasApplication) | ||
| 900 | { | ||
| 901 | hr = ScaWriteWebApplication7(psw->wzDescription, L"/", &psw->swapp, psapList); | ||
| 902 | ExitOnFailure(hr, "Failed to write web application information to metabase"); | ||
| 903 | } | ||
| 904 | |||
| 905 | // write the SSL certificate information | ||
| 906 | if (psw->pswscList) | ||
| 907 | { | ||
| 908 | hr = ScaSslCertificateWrite7(psw->wzDescription, psw->pswscList); | ||
| 909 | ExitOnFailure(hr, "Failed to write SSL certificates for Web site: %ls", psw->wzKey); | ||
| 910 | } | ||
| 911 | |||
| 912 | // write the headers | ||
| 913 | if (psw->pshhList) | ||
| 914 | { | ||
| 915 | hr = ScaWriteHttpHeader7(psw->wzDescription, L"/", psw->pshhList); | ||
| 916 | ExitOnFailure(hr, "Failed to write custom HTTP headers for Web site: %ls", psw->wzKey); | ||
| 917 | } | ||
| 918 | |||
| 919 | // write the errors | ||
| 920 | if (psw->psweList) | ||
| 921 | { | ||
| 922 | hr = ScaWriteWebError7(psw->wzDescription, L"/", psw->psweList); | ||
| 923 | ExitOnFailure(hr, "Failed to write custom web errors for Web site: %ls", psw->wzKey); | ||
| 924 | } | ||
| 925 | |||
| 926 | // write the log information to the metabase | ||
| 927 | if (psw->fHasLog) | ||
| 928 | { | ||
| 929 | hr = ScaWriteWebLog7(psw->wzDescription, &psw->swl); | ||
| 930 | ExitOnFailure(hr, "Failed to write web log information to metabase"); | ||
| 931 | } | ||
| 932 | |||
| 933 | LExit: | ||
| 934 | return hr; | ||
| 935 | } | ||
| 936 | |||
| 937 | |||
| 938 | static HRESULT ScaWebRemove7( | ||
| 939 | __in const SCA_WEB7* psw | ||
| 940 | ) | ||
| 941 | { | ||
| 942 | HRESULT hr = S_OK; | ||
| 943 | |||
| 944 | hr = ScaWriteConfigID(IIS_SITE); | ||
| 945 | ExitOnFailure(hr, "Failed write site ID"); | ||
| 946 | hr = ScaWriteConfigID(IIS_DELETE); | ||
| 947 | ExitOnFailure(hr, "Failed write site action"); | ||
| 948 | hr = ScaWriteConfigString(psw->wzDescription); //Site Name | ||
| 949 | ExitOnFailure(hr, "Failed write site name"); | ||
| 950 | |||
| 951 | LExit: | ||
| 952 | return hr; | ||
| 953 | } | ||
diff --git a/src/ext/Iis/ca/scaweb7.h b/src/ext/Iis/ca/scaweb7.h new file mode 100644 index 00000000..78946756 --- /dev/null +++ b/src/ext/Iis/ca/scaweb7.h | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scawebapp.h" | ||
| 6 | #include "scawebprop.h" | ||
| 7 | #include "scahttpheader.h" | ||
| 8 | #include "scaweberr.h" | ||
| 9 | #include "scassl.h" | ||
| 10 | #include "scaapppool.h" | ||
| 11 | #include "scaweblog.h" | ||
| 12 | |||
| 13 | // globals | ||
| 14 | #define MAX_ADDRESSES_PER_WEB 10 | ||
| 15 | |||
| 16 | // structs | ||
| 17 | struct SCA_WEB7 | ||
| 18 | { | ||
| 19 | // darwin information | ||
| 20 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 21 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 22 | BOOL fHasComponent; | ||
| 23 | INSTALLSTATE isInstalled; | ||
| 24 | INSTALLSTATE isAction; | ||
| 25 | |||
| 26 | int iSiteId; | ||
| 27 | |||
| 28 | // metabase information | ||
| 29 | WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1]; | ||
| 30 | BOOL fBaseExists; | ||
| 31 | |||
| 32 | // iis configuation information | ||
| 33 | SCA_WEB_ADDRESS swaBinding; | ||
| 34 | |||
| 35 | SCA_WEB_ADDRESS swaExtraAddresses[MAX_ADDRESSES_PER_WEB + 1]; | ||
| 36 | DWORD cExtraAddresses; | ||
| 37 | |||
| 38 | WCHAR wzDirectory[MAX_PATH]; | ||
| 39 | WCHAR wzDescription[MAX_DARWIN_COLUMN + 1]; | ||
| 40 | |||
| 41 | int iState; | ||
| 42 | int iAttributes; | ||
| 43 | |||
| 44 | BOOL fHasProperties; | ||
| 45 | SCA_WEB_PROPERTIES swp; | ||
| 46 | |||
| 47 | BOOL fHasApplication; | ||
| 48 | SCA_WEB_APPLICATION swapp; | ||
| 49 | |||
| 50 | BOOL fHasSecurity; | ||
| 51 | int dwAccessPermissions; | ||
| 52 | int iConnectionTimeout; | ||
| 53 | |||
| 54 | SCA_WEB_SSL_CERTIFICATE* pswscList; | ||
| 55 | SCA_HTTP_HEADER* pshhList; | ||
| 56 | SCA_WEB_ERROR* psweList; | ||
| 57 | |||
| 58 | BOOL fHasLog; | ||
| 59 | SCA_WEB_LOG swl; | ||
| 60 | |||
| 61 | SCA_WEB7* pswNext; | ||
| 62 | }; | ||
| 63 | |||
| 64 | |||
| 65 | // prototypes | ||
| 66 | HRESULT ScaWebsRead7( | ||
| 67 | __in SCA_WEB7** ppswList, | ||
| 68 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 69 | __in SCA_WEB_ERROR** ppsweList, | ||
| 70 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 71 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 72 | __in WCA_WRAPQUERY_HANDLE hSslCertQuery, | ||
| 73 | __in WCA_WRAPQUERY_HANDLE hWebLogQuery, | ||
| 74 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 75 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 76 | __inout LPWSTR *ppwzCustomActionData | ||
| 77 | ); | ||
| 78 | |||
| 79 | HRESULT ScaWebsGetBase7( | ||
| 80 | __in SCA_WEB7* pswList, | ||
| 81 | __in LPCWSTR pswWebKey, | ||
| 82 | __out_ecount(cchDest) LPWSTR pswWeb, | ||
| 83 | __in DWORD_PTR cchDest | ||
| 84 | ); | ||
| 85 | |||
| 86 | HRESULT ScaWebsInstall7( | ||
| 87 | __in SCA_WEB7* pswList, | ||
| 88 | __in SCA_APPPOOL * psapList | ||
| 89 | ); | ||
| 90 | |||
| 91 | HRESULT ScaWebsUninstall7( | ||
| 92 | __in SCA_WEB7* pswList | ||
| 93 | ); | ||
| 94 | |||
| 95 | void ScaWebsFreeList7( | ||
| 96 | __in SCA_WEB7* pswHead | ||
| 97 | ); | ||
diff --git a/src/ext/Iis/ca/scawebapp.cpp b/src/ext/Iis/ca/scawebapp.cpp new file mode 100644 index 00000000..a7e9cf82 --- /dev/null +++ b/src/ext/Iis/ca/scawebapp.cpp | |||
| @@ -0,0 +1,194 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // sql queries | ||
| 6 | enum eWebApplicationQuery { wappqName = 1, wappqIsolation, wappqAllowSession, | ||
| 7 | wappqSessionTimeout, wappqBuffer, wappqParentPaths, | ||
| 8 | wappqDefaultScript, wappqScriptTimeout, | ||
| 9 | wappqServerDebugging, wappqClientDebugging, wappqAppPool, wappqApplication}; | ||
| 10 | |||
| 11 | |||
| 12 | HRESULT ScaGetWebApplication(MSIHANDLE /*hViewApplications*/, | ||
| 13 | LPCWSTR pwzApplication, | ||
| 14 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 15 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 16 | SCA_WEB_APPLICATION* pswapp) | ||
| 17 | { | ||
| 18 | HRESULT hr = S_OK; | ||
| 19 | |||
| 20 | MSIHANDLE hRec; | ||
| 21 | LPWSTR pwzData = NULL; | ||
| 22 | |||
| 23 | // Reset back to the first record | ||
| 24 | WcaFetchWrappedReset(hWebAppQuery); | ||
| 25 | |||
| 26 | // get the application information | ||
| 27 | hr = WcaFetchWrappedRecordWhereString(hWebAppQuery, wappqApplication, pwzApplication, &hRec); | ||
| 28 | if (S_OK == hr) | ||
| 29 | { | ||
| 30 | // application name | ||
| 31 | hr = WcaGetRecordString(hRec, wappqName, &pwzData); | ||
| 32 | ExitOnFailure(hr, "Failed to get Name of App"); | ||
| 33 | hr = ::StringCchCopyW(pswapp->wzName, countof(pswapp->wzName), pwzData); | ||
| 34 | if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr) | ||
| 35 | { | ||
| 36 | // The application name is sometimes truncated to IIS's supported length, so ignore insufficient buffer errors here | ||
| 37 | WcaLog(LOGMSG_VERBOSE, "Application name \"%ls\" truncated to fit IIS's supported %d-character length", pwzData, MAX_APP_NAME); | ||
| 38 | hr = S_OK; | ||
| 39 | } | ||
| 40 | ExitOnFailure(hr, "Failed to copy name string to webapp object"); | ||
| 41 | |||
| 42 | hr = WcaGetRecordInteger(hRec, wappqIsolation, &pswapp->iIsolation); | ||
| 43 | ExitOnFailure(hr, "Failed to get App isolation: '%ls'", pswapp->wzName); | ||
| 44 | |||
| 45 | hr = WcaGetRecordInteger(hRec, wappqAllowSession, &pswapp->fAllowSessionState); | ||
| 46 | |||
| 47 | hr = WcaGetRecordInteger(hRec, wappqSessionTimeout, &pswapp->iSessionTimeout); | ||
| 48 | |||
| 49 | hr = WcaGetRecordInteger(hRec, wappqBuffer, &pswapp->fBuffer); | ||
| 50 | |||
| 51 | hr = WcaGetRecordInteger(hRec, wappqParentPaths, &pswapp->fParentPaths); | ||
| 52 | |||
| 53 | hr = WcaGetRecordString(hRec, wappqDefaultScript, &pwzData); | ||
| 54 | ExitOnFailure(hr, "Failed to get default scripting language for App: '%ls'", pswapp->wzName); | ||
| 55 | hr = ::StringCchCopyW(pswapp->wzDefaultScript, countof(pswapp->wzDefaultScript), pwzData); | ||
| 56 | ExitOnFailure(hr, "Failed to copy default script string to webapp object"); | ||
| 57 | |||
| 58 | // asp script timeout | ||
| 59 | hr = WcaGetRecordInteger(hRec, wappqScriptTimeout, &pswapp->iScriptTimeout); | ||
| 60 | ExitOnFailure(hr, "Failed to get scripting timeout for App: '%ls'", pswapp->wzName); | ||
| 61 | |||
| 62 | // asp server-side script debugging | ||
| 63 | hr = WcaGetRecordInteger(hRec, wappqServerDebugging, &pswapp->fServerDebugging); | ||
| 64 | |||
| 65 | // asp client-side script debugging | ||
| 66 | hr = WcaGetRecordInteger(hRec, wappqClientDebugging, &pswapp->fClientDebugging); | ||
| 67 | |||
| 68 | hr = WcaGetRecordString(hRec, wappqAppPool, &pwzData); | ||
| 69 | ExitOnFailure(hr, "Failed to get AppPool for App: '%ls'", pswapp->wzName); | ||
| 70 | hr = ::StringCchCopyW(pswapp->wzAppPool, countof(pswapp->wzAppPool), pwzData); | ||
| 71 | ExitOnFailure(hr, "failed to copy AppPool: '%ls' for App: '%ls'", pwzData, pswapp->wzName); | ||
| 72 | |||
| 73 | // app extensions | ||
| 74 | hr = ScaWebAppExtensionsRead(pwzApplication, hWebAppExtQuery, &pswapp->pswappextList); | ||
| 75 | ExitOnFailure(hr, "Failed to read AppExtensions for App: '%ls'", pswapp->wzName); | ||
| 76 | |||
| 77 | hr = S_OK; | ||
| 78 | } | ||
| 79 | else if (E_NOMOREITEMS == hr) | ||
| 80 | { | ||
| 81 | WcaLog(LOGMSG_STANDARD, "Error: Cannot locate IIsWebApplication.Application='%ls'", pwzApplication); | ||
| 82 | hr = E_FAIL; | ||
| 83 | } | ||
| 84 | else | ||
| 85 | ExitOnFailure(hr, "Error matching Application rows"); | ||
| 86 | |||
| 87 | // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would | ||
| 88 | HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebAppQuery, wappqApplication, pwzApplication, &hRec); | ||
| 89 | if (SUCCEEDED(hrTemp)) | ||
| 90 | { | ||
| 91 | AssertSz(E_NOMOREITEMS == hrTemp, "ScaGetWebApplication found more than one record"); | ||
| 92 | } | ||
| 93 | |||
| 94 | LExit: | ||
| 95 | ReleaseStr(pwzData); | ||
| 96 | |||
| 97 | return hr; | ||
| 98 | } | ||
| 99 | |||
| 100 | |||
| 101 | HRESULT ScaWriteWebApplication(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, | ||
| 102 | SCA_WEB_APPLICATION* pswapp, SCA_APPPOOL * psapList) | ||
| 103 | { | ||
| 104 | HRESULT hr = S_OK; | ||
| 105 | WCHAR wzAppPoolName[MAX_PATH]; | ||
| 106 | |||
| 107 | hr = ScaCreateApp(piMetabase, wzRootOfWeb, pswapp->iIsolation); | ||
| 108 | ExitOnFailure(hr, "Failed to create ASP App"); | ||
| 109 | |||
| 110 | // Medium Isolation seems to have to be set through the metabase | ||
| 111 | if (2 == pswapp->iIsolation) | ||
| 112 | { | ||
| 113 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_APP_ISOLATED, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->iIsolation)); | ||
| 114 | ExitOnFailure(hr, "Failed to write isolation value for App: '%ls'", pswapp->wzName); | ||
| 115 | } | ||
| 116 | |||
| 117 | // application name | ||
| 118 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_APP_FRIENDLY_NAME, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, pswapp->wzName); | ||
| 119 | ExitOnFailure(hr, "Failed to write Name of App: '%ls'", pswapp->wzName); | ||
| 120 | |||
| 121 | // allow session state | ||
| 122 | if (MSI_NULL_INTEGER != pswapp->fAllowSessionState) | ||
| 123 | { | ||
| 124 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ALLOWSESSIONSTATE, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fAllowSessionState)); | ||
| 125 | ExitOnFailure(hr, "Failed to write allow session information for App: '%ls'", pswapp->wzName); | ||
| 126 | } | ||
| 127 | |||
| 128 | // session timeout | ||
| 129 | if (MSI_NULL_INTEGER != pswapp->iSessionTimeout) | ||
| 130 | { | ||
| 131 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SESSIONTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->iSessionTimeout)); | ||
| 132 | ExitOnFailure(hr, "Failed to write session timeout for App: '%ls'", pswapp->wzName); | ||
| 133 | } | ||
| 134 | |||
| 135 | // asp buffering | ||
| 136 | if (MSI_NULL_INTEGER != pswapp->fBuffer) | ||
| 137 | { | ||
| 138 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_BUFFERINGON, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fBuffer)); | ||
| 139 | ExitOnFailure(hr, "Failed to write buffering flag for App: '%ls'", pswapp->wzName); | ||
| 140 | } | ||
| 141 | |||
| 142 | // asp parent paths | ||
| 143 | if (MSI_NULL_INTEGER != pswapp->fParentPaths) | ||
| 144 | { | ||
| 145 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ENABLEPARENTPATHS, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fParentPaths)); | ||
| 146 | ExitOnFailure(hr, "Failed to write parent paths flag for App: '%ls'", pswapp->wzName); | ||
| 147 | } | ||
| 148 | |||
| 149 | // default scripting language | ||
| 150 | if (*pswapp->wzDefaultScript) | ||
| 151 | { | ||
| 152 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTLANGUAGE, METADATA_INHERIT, ASP_MD_UT_APP, STRING_METADATA, pswapp->wzDefaultScript); | ||
| 153 | ExitOnFailure(hr, "Failed to write default scripting language for App: '%ls'", pswapp->wzName); | ||
| 154 | } | ||
| 155 | |||
| 156 | // asp script timeout | ||
| 157 | if (MSI_NULL_INTEGER != pswapp->iScriptTimeout) | ||
| 158 | { | ||
| 159 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->iScriptTimeout)); | ||
| 160 | ExitOnFailure(hr, "Failed to write script timeout for App: '%ls'", pswapp->wzName); | ||
| 161 | } | ||
| 162 | |||
| 163 | // asp server-side script debugging | ||
| 164 | if (MSI_NULL_INTEGER != pswapp->fServerDebugging) | ||
| 165 | { | ||
| 166 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ENABLESERVERDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fServerDebugging)); | ||
| 167 | ExitOnFailure(hr, "Failed to write ASP server-side script debugging flag for App: '%ls'", pswapp->wzName); | ||
| 168 | } | ||
| 169 | |||
| 170 | // asp server-side script debugging | ||
| 171 | if (MSI_NULL_INTEGER != pswapp->fClientDebugging) | ||
| 172 | { | ||
| 173 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ENABLECLIENTDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fClientDebugging)); | ||
| 174 | ExitOnFailure(hr, "Failed to write ASP client-side script debugging flag for App: '%ls'", pswapp->wzName); | ||
| 175 | } | ||
| 176 | |||
| 177 | // AppPool | ||
| 178 | if (*pswapp->wzAppPool && NULL != psapList) | ||
| 179 | { | ||
| 180 | hr = ScaFindAppPool(piMetabase, pswapp->wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList); | ||
| 181 | ExitOnFailure(hr, "failed to find app pool: %ls", pswapp->wzAppPool); | ||
| 182 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_APP_APPPOOL_ID, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, wzAppPoolName); | ||
| 183 | ExitOnFailure(hr, "Failed to write default AppPool for App: '%ls'", pswapp->wzName); | ||
| 184 | } | ||
| 185 | |||
| 186 | if (pswapp->pswappextList) | ||
| 187 | { | ||
| 188 | hr = ScaWebAppExtensionsWrite(piMetabase, wzRootOfWeb, pswapp->pswappextList); | ||
| 189 | ExitOnFailure(hr, "Failed to write AppExtensions for App: '%ls'", pswapp->wzName); | ||
| 190 | } | ||
| 191 | |||
| 192 | LExit: | ||
| 193 | return hr; | ||
| 194 | } | ||
diff --git a/src/ext/Iis/ca/scawebapp.h b/src/ext/Iis/ca/scawebapp.h new file mode 100644 index 00000000..a4152116 --- /dev/null +++ b/src/ext/Iis/ca/scawebapp.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scaapppool.h" | ||
| 6 | #include "scawebappext.h" | ||
| 7 | |||
| 8 | // global sql queries provided for optimization | ||
| 9 | extern LPCWSTR vcsWebApplicationQuery; | ||
| 10 | const int MAX_APP_NAME = 255; | ||
| 11 | |||
| 12 | // structs | ||
| 13 | struct SCA_WEB_APPLICATION | ||
| 14 | { | ||
| 15 | WCHAR wzName[MAX_APP_NAME + 1]; | ||
| 16 | |||
| 17 | int iIsolation; | ||
| 18 | BOOL fAllowSessionState; | ||
| 19 | int iSessionTimeout; | ||
| 20 | BOOL fBuffer; | ||
| 21 | BOOL fParentPaths; | ||
| 22 | |||
| 23 | WCHAR wzDefaultScript[MAX_DARWIN_COLUMN + 1]; | ||
| 24 | int iScriptTimeout; | ||
| 25 | BOOL fServerDebugging; | ||
| 26 | BOOL fClientDebugging; | ||
| 27 | WCHAR wzAppPool[MAX_DARWIN_COLUMN + 1]; | ||
| 28 | |||
| 29 | SCA_WEB_APPLICATION_EXTENSION* pswappextList; | ||
| 30 | }; | ||
| 31 | |||
| 32 | |||
| 33 | // prototypes | ||
| 34 | HRESULT ScaGetWebApplication(MSIHANDLE hViewApplications, | ||
| 35 | LPCWSTR pwzApplication, | ||
| 36 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 37 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 38 | SCA_WEB_APPLICATION* pswapp); | ||
| 39 | |||
| 40 | HRESULT ScaWriteWebApplication(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, | ||
| 41 | SCA_WEB_APPLICATION* pswapp, SCA_APPPOOL * psapList); | ||
| 42 | |||
diff --git a/src/ext/Iis/ca/scawebapp7.cpp b/src/ext/Iis/ca/scawebapp7.cpp new file mode 100644 index 00000000..94e6bb18 --- /dev/null +++ b/src/ext/Iis/ca/scawebapp7.cpp | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | HRESULT ScaWriteWebApplication7( | ||
| 5 | __in_z LPCWSTR wzWebName, | ||
| 6 | __in_z LPCWSTR wzRootOfWeb, | ||
| 7 | SCA_WEB_APPLICATION* pswapp, | ||
| 8 | SCA_APPPOOL * /*psapList*/ | ||
| 9 | ) | ||
| 10 | { | ||
| 11 | HRESULT hr = S_OK; | ||
| 12 | |||
| 13 | //all go to same web/root location tag | ||
| 14 | hr = ScaWriteConfigID(IIS_ASP_BEGIN); | ||
| 15 | ExitOnFailure(hr, "Failed to write WebApp ASP begin id"); | ||
| 16 | hr = ScaWriteConfigString(wzWebName); //site name key | ||
| 17 | ExitOnFailure(hr, "Failed to write app web key"); | ||
| 18 | hr = ScaWriteConfigString(wzRootOfWeb); //app path key | ||
| 19 | ExitOnFailure(hr, "Failed to write app web root"); | ||
| 20 | |||
| 21 | // IIS7 Not Supported: Isolation | ||
| 22 | if (MSI_NULL_INTEGER != pswapp->iIsolation) | ||
| 23 | { | ||
| 24 | WcaLog(LOGMSG_TRACEONLY, "Not supported by IIS7: Isolation Mode, ignoring"); | ||
| 25 | } | ||
| 26 | |||
| 27 | // allow session state | ||
| 28 | if (MSI_NULL_INTEGER != pswapp->fAllowSessionState) | ||
| 29 | { | ||
| 30 | //system.webServer/asp /session | allowSessionState | ||
| 31 | hr = ScaWriteConfigID(IIS_ASP_SESSIONSTATE); | ||
| 32 | ExitOnFailure(hr, "Failed to write WebApp ASP sessionstate id"); | ||
| 33 | hr = ScaWriteConfigInteger(pswapp->fAllowSessionState); | ||
| 34 | ExitOnFailure(hr, "Failed to write allow session information for App: '%ls'", pswapp->wzName); | ||
| 35 | } | ||
| 36 | |||
| 37 | // session timeout | ||
| 38 | if (MSI_NULL_INTEGER != pswapp->iSessionTimeout) | ||
| 39 | { | ||
| 40 | //system.webServer/asp /session | timeout | ||
| 41 | hr = ScaWriteConfigID(IIS_ASP_SESSIONTIMEOUT); | ||
| 42 | ExitOnFailure(hr, "Failed to write WebApp ASP sessiontimepot id"); | ||
| 43 | hr = ScaWriteConfigInteger(pswapp->iSessionTimeout); | ||
| 44 | ExitOnFailure(hr, "Failed to write session timeout for App: '%ls'", pswapp->wzName); | ||
| 45 | } | ||
| 46 | |||
| 47 | // asp buffering | ||
| 48 | if (MSI_NULL_INTEGER != pswapp->fBuffer) | ||
| 49 | { | ||
| 50 | //system.webServer/asp | bufferingOn | ||
| 51 | hr = ScaWriteConfigID(IIS_ASP_BUFFER); | ||
| 52 | ExitOnFailure(hr, "Failed to write WebApp ASP buffer id"); | ||
| 53 | hr = ScaWriteConfigInteger(pswapp->fBuffer); | ||
| 54 | ExitOnFailure(hr, "Failed to write buffering flag for App: '%ls'", pswapp->wzName); | ||
| 55 | } | ||
| 56 | |||
| 57 | // asp parent paths | ||
| 58 | if (MSI_NULL_INTEGER != pswapp->fParentPaths) | ||
| 59 | { | ||
| 60 | //system.webServer/asp | enableParentPaths | ||
| 61 | hr = ScaWriteConfigID(IIS_ASP_PARENTPATHS); | ||
| 62 | ExitOnFailure(hr, "Failed to write WebApp ASP parentpaths id"); | ||
| 63 | hr = ScaWriteConfigInteger(pswapp->fParentPaths); | ||
| 64 | ExitOnFailure(hr, "Failed to write parent paths flag for App: '%ls'", pswapp->wzName); | ||
| 65 | } | ||
| 66 | |||
| 67 | // default scripting language | ||
| 68 | if (*pswapp->wzDefaultScript) | ||
| 69 | { | ||
| 70 | //system.webServer/asp | scriptLanguage | ||
| 71 | hr = ScaWriteConfigID(IIS_ASP_SCRIPTLANG); | ||
| 72 | ExitOnFailure(hr, "Failed to write WebApp ASP script lang id"); | ||
| 73 | hr = ScaWriteConfigString(pswapp->wzDefaultScript); | ||
| 74 | ExitOnFailure(hr, "Failed to write default scripting language for App: '%ls'", pswapp->wzName); | ||
| 75 | } | ||
| 76 | |||
| 77 | // asp script timeout | ||
| 78 | if (MSI_NULL_INTEGER != pswapp->iScriptTimeout) | ||
| 79 | { | ||
| 80 | //system.webServer/asp /limits | scriptTimeout | ||
| 81 | hr = ScaWriteConfigID(IIS_ASP_SCRIPTTIMEOUT); | ||
| 82 | ExitOnFailure(hr, "Failed to write WebApp ASP script timeout id"); | ||
| 83 | hr = ScaWriteConfigInteger(pswapp->iScriptTimeout); | ||
| 84 | ExitOnFailure(hr, "Failed to write script timeout for App: '%ls'", pswapp->wzName); | ||
| 85 | } | ||
| 86 | |||
| 87 | // asp server-side script debugging | ||
| 88 | if (MSI_NULL_INTEGER != pswapp->fServerDebugging) | ||
| 89 | { | ||
| 90 | //system.webServer/asp | appAllowDebugging | ||
| 91 | hr = ScaWriteConfigID(IIS_ASP_SCRIPTSERVERDEBUG); | ||
| 92 | ExitOnFailure(hr, "Failed to write WebApp ASP script debug id"); | ||
| 93 | hr = ScaWriteConfigInteger(pswapp->fServerDebugging); | ||
| 94 | ExitOnFailure(hr, "Failed to write ASP server-side script debugging flag for App: '%ls'", pswapp->wzName); | ||
| 95 | } | ||
| 96 | |||
| 97 | // asp client-side script debugging | ||
| 98 | if (MSI_NULL_INTEGER != pswapp->fClientDebugging) | ||
| 99 | { | ||
| 100 | //system.webServer/asp | appAllowClientDebug | ||
| 101 | hr = ScaWriteConfigID(IIS_ASP_SCRIPTCLIENTDEBUG); | ||
| 102 | ExitOnFailure(hr, "Failed to write WebApp ASP script debug id"); | ||
| 103 | hr = ScaWriteConfigInteger(pswapp->fClientDebugging); | ||
| 104 | ExitOnFailure(hr, "Failed to write ASP client-side script debugging flag for App: '%ls'", pswapp->wzName); | ||
| 105 | } | ||
| 106 | |||
| 107 | //done with ASP application properties | ||
| 108 | hr = ScaWriteConfigID(IIS_ASP_END); | ||
| 109 | ExitOnFailure(hr, "Failed to write WebApp ASP begin id"); | ||
| 110 | |||
| 111 | //write out app estensions | ||
| 112 | if (pswapp->pswappextList) | ||
| 113 | { | ||
| 114 | hr = ScaWebAppExtensionsWrite7(wzWebName, wzRootOfWeb, pswapp->pswappextList); | ||
| 115 | ExitOnFailure(hr, "Failed to write AppExtensions for App: '%ls'", pswapp->wzName); | ||
| 116 | } | ||
| 117 | |||
| 118 | LExit: | ||
| 119 | return hr; | ||
| 120 | } | ||
diff --git a/src/ext/Iis/ca/scawebapp7.h b/src/ext/Iis/ca/scawebapp7.h new file mode 100644 index 00000000..e1d87f53 --- /dev/null +++ b/src/ext/Iis/ca/scawebapp7.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaWriteWebApplication7( | ||
| 6 | __in_z LPCWSTR wzWebName, | ||
| 7 | __in_z LPCWSTR wzRootOfWeb, | ||
| 8 | SCA_WEB_APPLICATION* pswapp, | ||
| 9 | SCA_APPPOOL * psapList | ||
| 10 | ); | ||
diff --git a/src/ext/Iis/ca/scawebappext.cpp b/src/ext/Iis/ca/scawebappext.cpp new file mode 100644 index 00000000..cf3b9dd3 --- /dev/null +++ b/src/ext/Iis/ca/scawebappext.cpp | |||
| @@ -0,0 +1,207 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | enum eWebAppExtensionQuery { wappextqExtension = 1, wappextqVerbs, wappextqExecutable, wappextqAttributes, wappextqApplication }; | ||
| 6 | |||
| 7 | // prototypes for private helper functions | ||
| 8 | static HRESULT NewAppExt( | ||
| 9 | __out SCA_WEB_APPLICATION_EXTENSION** ppswappext | ||
| 10 | ); | ||
| 11 | static SCA_WEB_APPLICATION_EXTENSION* AddAppExtToList( | ||
| 12 | __in SCA_WEB_APPLICATION_EXTENSION* pswappextList, | ||
| 13 | __in SCA_WEB_APPLICATION_EXTENSION* pswappext | ||
| 14 | ); | ||
| 15 | |||
| 16 | |||
| 17 | |||
| 18 | HRESULT ScaWebAppExtensionsRead( | ||
| 19 | __in LPCWSTR wzApplication, | ||
| 20 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 21 | __inout SCA_WEB_APPLICATION_EXTENSION** ppswappextList | ||
| 22 | ) | ||
| 23 | { | ||
| 24 | HRESULT hr = S_OK; | ||
| 25 | MSIHANDLE hRec; | ||
| 26 | |||
| 27 | SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL; | ||
| 28 | LPWSTR pwzData = NULL; | ||
| 29 | |||
| 30 | // Reset back to the first record | ||
| 31 | WcaFetchWrappedReset(hWebAppExtQuery); | ||
| 32 | |||
| 33 | // get the application extension information | ||
| 34 | while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hWebAppExtQuery, wappextqApplication, wzApplication, &hRec))) | ||
| 35 | { | ||
| 36 | hr = NewAppExt(&pswappext); | ||
| 37 | ExitOnFailure(hr, "failed to create new web app extension"); | ||
| 38 | |||
| 39 | // get the extension | ||
| 40 | hr = WcaGetRecordString(hRec, wappextqExtension, &pwzData); | ||
| 41 | ExitOnFailure(hr, "Failed to get Web Application Extension"); | ||
| 42 | hr = ::StringCchCopyW(pswappext->wzExtension, countof(pswappext->wzExtension), pwzData); | ||
| 43 | ExitOnFailure(hr, "Failed to copy extension string to webappext object"); | ||
| 44 | |||
| 45 | // application extension verbs | ||
| 46 | hr = WcaGetRecordString(hRec, wappextqVerbs, &pwzData); | ||
| 47 | ExitOnFailure(hr, "Failed to get Verbs for Application: '%ls'", wzApplication); | ||
| 48 | hr = ::StringCchCopyW(pswappext->wzVerbs, countof(pswappext->wzVerbs), pwzData); | ||
| 49 | ExitOnFailure(hr, "Failed to copy verbs string to webappext object"); | ||
| 50 | |||
| 51 | // extension executeable | ||
| 52 | hr = WcaGetRecordString(hRec, wappextqExecutable, &pwzData); | ||
| 53 | ExitOnFailure(hr, "Failed to get Executable for Application: '%ls'", wzApplication); | ||
| 54 | hr = ::StringCchCopyW(pswappext->wzExecutable, countof(pswappext->wzExecutable), pwzData); | ||
| 55 | ExitOnFailure(hr, "Failed to copy executable string to webappext object"); | ||
| 56 | |||
| 57 | hr = WcaGetRecordInteger(hRec, wappextqAttributes, &pswappext->iAttributes); | ||
| 58 | if (S_FALSE == hr) | ||
| 59 | { | ||
| 60 | pswappext->iAttributes = 0; | ||
| 61 | hr = S_OK; | ||
| 62 | } | ||
| 63 | ExitOnFailure(hr, "Failed to get App isolation"); | ||
| 64 | |||
| 65 | *ppswappextList = AddAppExtToList(*ppswappextList, pswappext); | ||
| 66 | pswappext = NULL; // set the appext NULL so it doesn't accidentally get freed below | ||
| 67 | } | ||
| 68 | |||
| 69 | if (E_NOMOREITEMS == hr) | ||
| 70 | { | ||
| 71 | hr = S_OK; | ||
| 72 | } | ||
| 73 | |||
| 74 | LExit: | ||
| 75 | // if anything was left over after an error clean it all up | ||
| 76 | if (pswappext) | ||
| 77 | { | ||
| 78 | ScaWebAppExtensionsFreeList(pswappext); | ||
| 79 | } | ||
| 80 | |||
| 81 | ReleaseStr(pwzData); | ||
| 82 | |||
| 83 | return hr; | ||
| 84 | } | ||
| 85 | |||
| 86 | |||
| 87 | |||
| 88 | HRESULT ScaWebAppExtensionsWrite( | ||
| 89 | __in IMSAdminBase* piMetabase, | ||
| 90 | __in LPCWSTR wzRootOfWeb, | ||
| 91 | __in SCA_WEB_APPLICATION_EXTENSION* pswappextList | ||
| 92 | ) | ||
| 93 | { | ||
| 94 | HRESULT hr = S_OK; | ||
| 95 | |||
| 96 | LPWSTR wzAppExt = NULL; | ||
| 97 | DWORD cchAppExt; | ||
| 98 | WCHAR wzAppExtension[1024]; | ||
| 99 | WCHAR wzAppExtensions[65536]; | ||
| 100 | SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL; | ||
| 101 | |||
| 102 | if (!pswappextList) | ||
| 103 | { | ||
| 104 | ExitFunction(); | ||
| 105 | } | ||
| 106 | |||
| 107 | ::ZeroMemory(wzAppExtensions, sizeof(wzAppExtensions)); | ||
| 108 | wzAppExt = wzAppExtensions; | ||
| 109 | cchAppExt = countof(wzAppExtensions); | ||
| 110 | pswappext = pswappextList; | ||
| 111 | |||
| 112 | while (pswappext) | ||
| 113 | { | ||
| 114 | // if all (represented by "*" or blank) | ||
| 115 | if (0 == lstrcmpW(pswappext->wzExtension, L"*") || 0 == lstrlenW(pswappext->wzExtension)) | ||
| 116 | { | ||
| 117 | hr = ::StringCchPrintfW(wzAppExtension, countof(wzAppExtension), L"*,%s,%d", pswappext->wzExecutable, pswappext->iAttributes); | ||
| 118 | ExitOnFailure(hr, "Failed to format *,executable,attributes string"); | ||
| 119 | } | ||
| 120 | else | ||
| 121 | { | ||
| 122 | hr = ::StringCchPrintfW(wzAppExtension, countof(wzAppExtension), L".%s,%s,%d", pswappext->wzExtension, pswappext->wzExecutable, pswappext->iAttributes); | ||
| 123 | ExitOnFailure(hr, "Failed to format extension,executable,attributes string"); | ||
| 124 | } | ||
| 125 | |||
| 126 | // if verbs were specified and not the keyword "all" | ||
| 127 | if (pswappext->wzVerbs[0] && CSTR_EQUAL != CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pswappext->wzVerbs, -1, L"all", -1)) | ||
| 128 | { | ||
| 129 | hr = ::StringCchCatW(wzAppExtension, countof(wzAppExtension), L","); | ||
| 130 | ExitOnFailure(hr, "Failed to concatenate comma to app extension string"); | ||
| 131 | hr = ::StringCchCatW(wzAppExtension, countof(wzAppExtension), pswappext->wzVerbs); | ||
| 132 | ExitOnFailure(hr, "Failed to concatenate verb to app extension string"); | ||
| 133 | } | ||
| 134 | |||
| 135 | hr = ::StringCchCopyW(wzAppExt, cchAppExt, wzAppExtension); | ||
| 136 | ExitOnFailure(hr, "Failed to copy app extension string"); | ||
| 137 | wzAppExt += lstrlenW(wzAppExtension) + 1; | ||
| 138 | cchAppExt -= lstrlenW(wzAppExtension) + 1; | ||
| 139 | pswappext = pswappext->pswappextNext; | ||
| 140 | } | ||
| 141 | |||
| 142 | if (*wzAppExtensions) | ||
| 143 | { | ||
| 144 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_SCRIPT_MAPS, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzAppExtensions); | ||
| 145 | ExitOnFailure(hr, "Failed to write AppExtension: '%ls'", wzAppExtension); | ||
| 146 | } | ||
| 147 | |||
| 148 | LExit: | ||
| 149 | return hr; | ||
| 150 | } | ||
| 151 | |||
| 152 | |||
| 153 | void ScaWebAppExtensionsFreeList( | ||
| 154 | __in SCA_WEB_APPLICATION_EXTENSION* pswappextList | ||
| 155 | ) | ||
| 156 | { | ||
| 157 | SCA_WEB_APPLICATION_EXTENSION* pswappextDelete = pswappextList; | ||
| 158 | while (pswappextList) | ||
| 159 | { | ||
| 160 | pswappextDelete = pswappextList; | ||
| 161 | pswappextList = pswappextList->pswappextNext; | ||
| 162 | |||
| 163 | MemFree(pswappextDelete); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | |||
| 168 | |||
| 169 | // private helper functions | ||
| 170 | |||
| 171 | static HRESULT NewAppExt( | ||
| 172 | __out SCA_WEB_APPLICATION_EXTENSION** ppswappext | ||
| 173 | ) | ||
| 174 | { | ||
| 175 | HRESULT hr = S_OK; | ||
| 176 | SCA_WEB_APPLICATION_EXTENSION* pswappext = static_cast<SCA_WEB_APPLICATION_EXTENSION*>(MemAlloc(sizeof(SCA_WEB_APPLICATION_EXTENSION), TRUE)); | ||
| 177 | ExitOnNull(pswappext, hr, E_OUTOFMEMORY, "failed to allocate memory for new web app ext element"); | ||
| 178 | |||
| 179 | *ppswappext = pswappext; | ||
| 180 | |||
| 181 | LExit: | ||
| 182 | return hr; | ||
| 183 | } | ||
| 184 | |||
| 185 | |||
| 186 | static SCA_WEB_APPLICATION_EXTENSION* AddAppExtToList( | ||
| 187 | __in SCA_WEB_APPLICATION_EXTENSION* pswappextList, | ||
| 188 | __in SCA_WEB_APPLICATION_EXTENSION* pswappext | ||
| 189 | ) | ||
| 190 | { | ||
| 191 | if (pswappextList) | ||
| 192 | { | ||
| 193 | SCA_WEB_APPLICATION_EXTENSION* pswappextT = pswappextList; | ||
| 194 | while (pswappextT->pswappextNext) | ||
| 195 | { | ||
| 196 | pswappextT = pswappextT->pswappextNext; | ||
| 197 | } | ||
| 198 | |||
| 199 | pswappextT->pswappextNext = pswappext; | ||
| 200 | } | ||
| 201 | else | ||
| 202 | { | ||
| 203 | pswappextList = pswappext; | ||
| 204 | } | ||
| 205 | |||
| 206 | return pswappextList; | ||
| 207 | } | ||
diff --git a/src/ext/Iis/ca/scawebappext.h b/src/ext/Iis/ca/scawebappext.h new file mode 100644 index 00000000..71adfd00 --- /dev/null +++ b/src/ext/Iis/ca/scawebappext.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | struct SCA_WEB_APPLICATION_EXTENSION | ||
| 6 | { | ||
| 7 | WCHAR wzExtension[MAX_DARWIN_COLUMN + 1]; | ||
| 8 | |||
| 9 | WCHAR wzVerbs[MAX_DARWIN_COLUMN + 1]; | ||
| 10 | WCHAR wzExecutable[MAX_DARWIN_COLUMN + 1]; | ||
| 11 | int iAttributes; | ||
| 12 | |||
| 13 | SCA_WEB_APPLICATION_EXTENSION* pswappextNext; | ||
| 14 | }; | ||
| 15 | |||
| 16 | |||
| 17 | // prototypes | ||
| 18 | HRESULT ScaWebAppExtensionsRead( | ||
| 19 | __in LPCWSTR wzApplication, | ||
| 20 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 21 | __inout SCA_WEB_APPLICATION_EXTENSION** ppswappextList | ||
| 22 | ); | ||
| 23 | |||
| 24 | HRESULT ScaWebAppExtensionsWrite( | ||
| 25 | __in IMSAdminBase* piMetabase, | ||
| 26 | __in LPCWSTR wzRootOfWeb, | ||
| 27 | __in SCA_WEB_APPLICATION_EXTENSION* pswappextList | ||
| 28 | ); | ||
| 29 | |||
| 30 | void ScaWebAppExtensionsFreeList( | ||
| 31 | __in SCA_WEB_APPLICATION_EXTENSION* pswappextList | ||
| 32 | ); | ||
diff --git a/src/ext/Iis/ca/scawebappext7.cpp b/src/ext/Iis/ca/scawebappext7.cpp new file mode 100644 index 00000000..50d3172f --- /dev/null +++ b/src/ext/Iis/ca/scawebappext7.cpp | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | HRESULT ScaWebAppExtensionsWrite7( | ||
| 6 | __in_z LPCWSTR wzWebName, | ||
| 7 | __in_z LPCWSTR wzRootOfWeb, | ||
| 8 | __in SCA_WEB_APPLICATION_EXTENSION* pswappextList | ||
| 9 | ) | ||
| 10 | { | ||
| 11 | HRESULT hr = S_OK; | ||
| 12 | SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL; | ||
| 13 | |||
| 14 | if (!pswappextList) | ||
| 15 | { | ||
| 16 | ExitFunction1(hr = S_OK); | ||
| 17 | } | ||
| 18 | |||
| 19 | //create the Extension for this vdir application | ||
| 20 | //all go to same web/root location tag | ||
| 21 | hr = ScaWriteConfigID(IIS_APPEXT_BEGIN); | ||
| 22 | ExitOnFailure(hr, "Failed to write webappext begin id"); | ||
| 23 | hr = ScaWriteConfigString(wzWebName); //site name key | ||
| 24 | ExitOnFailure(hr, "Failed to write app web key"); | ||
| 25 | hr = ScaWriteConfigString(wzRootOfWeb); //app path key | ||
| 26 | ExitOnFailure(hr, "Failed to write app web key"); | ||
| 27 | |||
| 28 | pswappext = pswappextList; | ||
| 29 | |||
| 30 | while (pswappext) | ||
| 31 | { | ||
| 32 | //create the Extension for this vdir application | ||
| 33 | hr = ScaWriteConfigID(IIS_APPEXT); | ||
| 34 | ExitOnFailure(hr, "Failed to write webappext begin id"); | ||
| 35 | |||
| 36 | if (*pswappext->wzExtension) | ||
| 37 | { | ||
| 38 | hr = ScaWriteConfigString(pswappext->wzExtension); | ||
| 39 | } | ||
| 40 | else // blank means "*" (all) | ||
| 41 | { | ||
| 42 | hr = ScaWriteConfigString(L"*"); | ||
| 43 | } | ||
| 44 | ExitOnFailure(hr, "Failed to write extension"); | ||
| 45 | |||
| 46 | hr = ScaWriteConfigString(pswappext->wzExecutable); | ||
| 47 | ExitOnFailure(hr, "Failed to write extension executable"); | ||
| 48 | |||
| 49 | hr = ScaWriteConfigString(pswappext->wzVerbs); | ||
| 50 | ExitOnFailure(hr, "Failed to write extension verbs"); | ||
| 51 | |||
| 52 | pswappext = pswappext->pswappextNext; | ||
| 53 | } | ||
| 54 | |||
| 55 | hr = ScaWriteConfigID(IIS_APPEXT_END); | ||
| 56 | ExitOnFailure(hr, "Failed to write webappext begin id"); | ||
| 57 | |||
| 58 | LExit: | ||
| 59 | return hr; | ||
| 60 | } | ||
| 61 | |||
diff --git a/src/ext/Iis/ca/scawebappext7.h b/src/ext/Iis/ca/scawebappext7.h new file mode 100644 index 00000000..55c8b5fc --- /dev/null +++ b/src/ext/Iis/ca/scawebappext7.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaWebAppExtensionsWrite7( | ||
| 6 | __in_z LPCWSTR wzWebName, | ||
| 7 | __in_z LPCWSTR wzRootOfWeb, | ||
| 8 | __in SCA_WEB_APPLICATION_EXTENSION* pswappextList | ||
| 9 | ); | ||
diff --git a/src/ext/Iis/ca/scawebdir.cpp b/src/ext/Iis/ca/scawebdir.cpp new file mode 100644 index 00000000..26a7b32b --- /dev/null +++ b/src/ext/Iis/ca/scawebdir.cpp | |||
| @@ -0,0 +1,241 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // sql queries | ||
| 6 | enum eWebDirQuery { wdqWeb = 1, wdqWebDir, wdqComponent , wdqPath, wdqProperties, wdqApplication, wdqInstalled, wdqAction }; | ||
| 7 | |||
| 8 | // prototypes | ||
| 9 | static void AddWebDirToList(SCA_WEBDIR** ppswdList, SCA_WEBDIR *pswd); | ||
| 10 | |||
| 11 | static SCA_WEBDIR* NewWebDir(); | ||
| 12 | static void FreeWebDir(SCA_WEBDIR *pswd); | ||
| 13 | |||
| 14 | |||
| 15 | UINT __stdcall ScaWebDirsRead( | ||
| 16 | __in IMSAdminBase* piMetabase, | ||
| 17 | __in SCA_WEB* pswList, | ||
| 18 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 19 | __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, | ||
| 20 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 21 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 22 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 23 | __inout LPWSTR *ppwzCustomActionData, | ||
| 24 | __out SCA_WEBDIR** ppswdList | ||
| 25 | ) | ||
| 26 | { | ||
| 27 | Assert(piMetabase && ppswdList); | ||
| 28 | |||
| 29 | HRESULT hr = S_OK; | ||
| 30 | MSIHANDLE hRec; | ||
| 31 | |||
| 32 | LPWSTR pwzData = NULL; | ||
| 33 | SCA_WEBDIR* pswd; | ||
| 34 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 35 | |||
| 36 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 37 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebDirsRead"); | ||
| 38 | |||
| 39 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 40 | { | ||
| 41 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallWebDirs() because IIsWebDir table not present"); | ||
| 42 | ExitFunction1(hr = S_FALSE); | ||
| 43 | } | ||
| 44 | |||
| 45 | // loop through all the web directories | ||
| 46 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 47 | { | ||
| 48 | pswd = NewWebDir(); | ||
| 49 | ExitOnNull(pswd, hr, E_OUTOFMEMORY, "Failed to allocate memory for web dir object in memory"); | ||
| 50 | |||
| 51 | // get component install state | ||
| 52 | hr = WcaGetRecordString(hRec, wdqComponent, &pwzData); | ||
| 53 | ExitOnFailure(hr, "Failed to get Component for WebDirs"); | ||
| 54 | hr = ::StringCchCopyW(pswd->wzComponent, countof(pswd->wzComponent), pwzData); | ||
| 55 | ExitOnFailure(hr, "Failed to copy component string to webdir object"); | ||
| 56 | |||
| 57 | hr = WcaGetRecordInteger(hRec, wdqInstalled, (int *)&pswd->isInstalled); | ||
| 58 | ExitOnFailure(hr, "Failed to get Component installed state for webdir"); | ||
| 59 | |||
| 60 | hr = WcaGetRecordInteger(hRec, wdqAction, (int *)&pswd->isAction); | ||
| 61 | ExitOnFailure(hr, "Failed to get Component action state for webdir"); | ||
| 62 | |||
| 63 | // If this record has a component and no action is being taken for it, skip processing it entirely | ||
| 64 | if (0 < lstrlenW(pswd->wzComponent) && !WcaIsInstalling(pswd->isInstalled, pswd->isAction) | ||
| 65 | && !WcaIsUninstalling(pswd->isInstalled, pswd->isAction) && !WcaIsReInstalling(pswd->isInstalled, pswd->isAction)) | ||
| 66 | { | ||
| 67 | FreeWebDir(pswd); | ||
| 68 | pswd = NULL; | ||
| 69 | continue; | ||
| 70 | } | ||
| 71 | |||
| 72 | hr = WcaGetRecordString(hRec, wdqWeb, &pwzData); | ||
| 73 | ExitOnFailure(hr, "Failed to get Web for WebDir"); | ||
| 74 | |||
| 75 | hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pswd->wzWebBase, countof(pswd->wzWebBase), hWebBaseQuery); | ||
| 76 | if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction)) | ||
| 77 | { | ||
| 78 | // If we're uninstalling, ignore any failure to find the existing web | ||
| 79 | hr = S_OK; | ||
| 80 | } | ||
| 81 | |||
| 82 | ExitOnFailure(hr, "Failed to get base of web for WebDir"); | ||
| 83 | |||
| 84 | hr = WcaGetRecordString(hRec, wdqPath, &pwzData); | ||
| 85 | ExitOnFailure(hr, "Failed to get Path for WebDir"); | ||
| 86 | |||
| 87 | hr = ::StringCchPrintfW(pswd->wzWebDirRoot, countof(pswd->wzWebDirRoot), L"%s/Root/%s", pswd->wzWebBase, pwzData); | ||
| 88 | ExitOnFailure(hr, "Failed to format webdir root string"); | ||
| 89 | |||
| 90 | // get the directory properties for this web | ||
| 91 | hr = WcaGetRecordString(hRec, wdqProperties, &pwzData); | ||
| 92 | ExitOnFailure(hr, "Failed to get security identifier for WebDir"); | ||
| 93 | if (*pwzData) | ||
| 94 | { | ||
| 95 | hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pswd->swp); | ||
| 96 | ExitOnFailure(hr, "Failed to get properties for WebDir"); | ||
| 97 | |||
| 98 | pswd->fHasProperties = TRUE; | ||
| 99 | } | ||
| 100 | |||
| 101 | // get the application information for this web directory | ||
| 102 | hr = WcaGetRecordString(hRec, wdqApplication, &pwzData); | ||
| 103 | ExitOnFailure(hr, "Failed to get application identifier for WebDir"); | ||
| 104 | if (*pwzData) | ||
| 105 | { | ||
| 106 | hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pswd->swapp); | ||
| 107 | ExitOnFailure(hr, "Failed to get application for WebDir"); | ||
| 108 | |||
| 109 | pswd->fHasApplication = TRUE; | ||
| 110 | } | ||
| 111 | |||
| 112 | AddWebDirToList(ppswdList, pswd); | ||
| 113 | } | ||
| 114 | |||
| 115 | if (E_NOMOREITEMS == hr) | ||
| 116 | { | ||
| 117 | hr = S_OK; | ||
| 118 | } | ||
| 119 | ExitOnFailure(hr, "Failure while processing WebDirs"); | ||
| 120 | |||
| 121 | LExit: | ||
| 122 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 123 | |||
| 124 | ReleaseStr(pwzData); | ||
| 125 | |||
| 126 | return hr; | ||
| 127 | } | ||
| 128 | |||
| 129 | |||
| 130 | HRESULT ScaWebDirsInstall(IMSAdminBase* piMetabase, SCA_WEBDIR* pswdList, SCA_APPPOOL * psapList) | ||
| 131 | { | ||
| 132 | HRESULT hr = S_OK; | ||
| 133 | SCA_WEBDIR* pswd = pswdList; | ||
| 134 | int i; | ||
| 135 | |||
| 136 | while (pswd) | ||
| 137 | { | ||
| 138 | // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created | ||
| 139 | if (WcaIsReInstalling(pswd->isInstalled, pswd->isAction)) | ||
| 140 | { | ||
| 141 | if (pswd->fHasApplication) | ||
| 142 | { | ||
| 143 | hr = ScaDeleteApp(piMetabase, pswd->wzWebDirRoot); | ||
| 144 | ExitOnFailure(hr, "Failed to remove application for WebDir as part of a reinstall"); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | // if we are installing the web site | ||
| 149 | if (WcaIsInstalling(pswd->isInstalled, pswd->isAction)) | ||
| 150 | { | ||
| 151 | hr = ScaCreateMetabaseKey(piMetabase, pswd->wzWebDirRoot, L""); | ||
| 152 | ExitOnFailure(hr, "Failed to create key for WebDir"); | ||
| 153 | hr = ScaWriteMetabaseValue(piMetabase, pswd->wzWebDirRoot, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebDirectory"); | ||
| 154 | ExitOnFailure(hr, "Failed to write key type for for WebDir"); | ||
| 155 | i = 0x4000003e; // 1073741886: default directory browsing rights | ||
| 156 | hr = ScaWriteMetabaseValue(piMetabase, pswd->wzWebDirRoot, L"", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)i)); | ||
| 157 | ExitOnFailure(hr, "Failed to set directory browsing for WebDir"); | ||
| 158 | |||
| 159 | // get the security information for this web | ||
| 160 | if (pswd->fHasProperties) | ||
| 161 | { | ||
| 162 | ScaWriteWebDirProperties(piMetabase, pswd->wzWebDirRoot, &pswd->swp); | ||
| 163 | ExitOnFailure(hr, "Failed to write properties for WebDir"); | ||
| 164 | } | ||
| 165 | |||
| 166 | // get the application information for this web directory | ||
| 167 | if (pswd->fHasApplication) | ||
| 168 | { | ||
| 169 | hr = ScaWriteWebApplication(piMetabase, pswd->wzWebDirRoot, &pswd->swapp, psapList); | ||
| 170 | ExitOnFailure(hr, "Failed to write application for WebDir"); | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | pswd = pswd->pswdNext; | ||
| 175 | } | ||
| 176 | |||
| 177 | LExit: | ||
| 178 | return hr; | ||
| 179 | } | ||
| 180 | |||
| 181 | |||
| 182 | HRESULT ScaWebDirsUninstall(IMSAdminBase* piMetabase, SCA_WEBDIR* pswdList) | ||
| 183 | { | ||
| 184 | Assert(piMetabase); | ||
| 185 | |||
| 186 | HRESULT hr = S_OK; | ||
| 187 | SCA_WEBDIR* pswd = pswdList; | ||
| 188 | |||
| 189 | while (pswd) | ||
| 190 | { | ||
| 191 | if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction)) | ||
| 192 | { | ||
| 193 | // remove the application from this web directory | ||
| 194 | if (pswd->fHasApplication) | ||
| 195 | { | ||
| 196 | hr = ScaDeleteApp(piMetabase, pswd->wzWebDirRoot); | ||
| 197 | ExitOnFailure(hr, "Failed to remove application for WebDir"); | ||
| 198 | } | ||
| 199 | |||
| 200 | hr = ScaDeleteMetabaseKey(piMetabase, pswd->wzWebDirRoot, L""); | ||
| 201 | ExitOnFailure(hr, "Failed to remove WebDir '%ls' from metabase", pswd->wzKey); | ||
| 202 | } | ||
| 203 | |||
| 204 | pswd = pswd->pswdNext; | ||
| 205 | } | ||
| 206 | |||
| 207 | LExit: | ||
| 208 | return hr; | ||
| 209 | } | ||
| 210 | |||
| 211 | |||
| 212 | static SCA_WEBDIR* NewWebDir() | ||
| 213 | { | ||
| 214 | SCA_WEBDIR* pswd = static_cast<SCA_WEBDIR*>(MemAlloc(sizeof(SCA_WEBDIR), TRUE)); | ||
| 215 | Assert(pswd); | ||
| 216 | return pswd; | ||
| 217 | } | ||
| 218 | |||
| 219 | static void FreeWebDir(SCA_WEBDIR *pswd) | ||
| 220 | { | ||
| 221 | MemFree(pswd); | ||
| 222 | } | ||
| 223 | |||
| 224 | void ScaWebDirsFreeList(SCA_WEBDIR* pswdList) | ||
| 225 | { | ||
| 226 | SCA_WEBDIR* pswdDelete = pswdList; | ||
| 227 | while (pswdList) | ||
| 228 | { | ||
| 229 | pswdDelete = pswdList; | ||
| 230 | pswdList = pswdList->pswdNext; | ||
| 231 | |||
| 232 | FreeWebDir(pswdDelete); | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | |||
| 237 | static void AddWebDirToList(SCA_WEBDIR** ppswdList, SCA_WEBDIR *pswd) | ||
| 238 | { | ||
| 239 | pswd->pswdNext = *ppswdList; | ||
| 240 | *ppswdList = pswd; | ||
| 241 | } | ||
diff --git a/src/ext/Iis/ca/scawebdir.h b/src/ext/Iis/ca/scawebdir.h new file mode 100644 index 00000000..0b594532 --- /dev/null +++ b/src/ext/Iis/ca/scawebdir.h | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | struct SCA_WEBDIR | ||
| 6 | { | ||
| 7 | // darwin information | ||
| 8 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 9 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 10 | INSTALLSTATE isInstalled; | ||
| 11 | INSTALLSTATE isAction; | ||
| 12 | |||
| 13 | // metabase information | ||
| 14 | WCHAR wzWebKey[MAX_DARWIN_KEY + 1]; | ||
| 15 | WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1]; | ||
| 16 | WCHAR wzWebDirRoot[METADATA_MAX_NAME_LEN + 1]; | ||
| 17 | |||
| 18 | // iis configuation information | ||
| 19 | WCHAR wzDirectory[MAX_PATH]; | ||
| 20 | |||
| 21 | BOOL fHasProperties; | ||
| 22 | SCA_WEB_PROPERTIES swp; | ||
| 23 | |||
| 24 | BOOL fHasApplication; | ||
| 25 | SCA_WEB_APPLICATION swapp; | ||
| 26 | |||
| 27 | SCA_WEBDIR* pswdNext; | ||
| 28 | }; | ||
| 29 | |||
| 30 | |||
| 31 | // prototypes | ||
| 32 | UINT __stdcall ScaWebDirsRead( | ||
| 33 | __in IMSAdminBase* piMetabase, | ||
| 34 | __in SCA_WEB* pswList, | ||
| 35 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 36 | __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, | ||
| 37 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 38 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 39 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 40 | __inout LPWSTR *ppwzCustomActionData, | ||
| 41 | __out SCA_WEBDIR** ppswdList | ||
| 42 | ); | ||
| 43 | |||
| 44 | HRESULT ScaWebDirsInstall( | ||
| 45 | __in IMSAdminBase* piMetabase, | ||
| 46 | __in SCA_WEBDIR* pswdList, | ||
| 47 | __in SCA_APPPOOL* psapList | ||
| 48 | ); | ||
| 49 | |||
| 50 | HRESULT ScaWebDirsUninstall( | ||
| 51 | __in IMSAdminBase* piMetabase, | ||
| 52 | __in SCA_WEBDIR* pswdList | ||
| 53 | ); | ||
| 54 | |||
| 55 | void ScaWebDirsFreeList( | ||
| 56 | __in SCA_WEBDIR* pswdList | ||
| 57 | ); | ||
diff --git a/src/ext/Iis/ca/scawebdir7.cpp b/src/ext/Iis/ca/scawebdir7.cpp new file mode 100644 index 00000000..5ead0470 --- /dev/null +++ b/src/ext/Iis/ca/scawebdir7.cpp | |||
| @@ -0,0 +1,219 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // sql queries | ||
| 6 | static LPCWSTR vcsWebDirQuery7 = L"SELECT `Web_`, `WebDir`, `Component_`, `Path`, `DirProperties_`, `Application_`" | ||
| 7 | L"FROM `IIsWebDir`"; | ||
| 8 | |||
| 9 | enum eWebDirQuery { wdqWeb = 1, wdqWebDir, wdqComponent , wdqPath, wdqProperties, wdqApplication, wdqInstalled, wdqAction }; | ||
| 10 | |||
| 11 | // prototypes | ||
| 12 | static HRESULT AddWebDirToList(SCA_WEBDIR7** ppswdList); | ||
| 13 | |||
| 14 | |||
| 15 | UINT __stdcall ScaWebDirsRead7( | ||
| 16 | __in SCA_WEB7* pswList, | ||
| 17 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 18 | __in WCA_WRAPQUERY_HANDLE /*hWebBaseQuery*/, | ||
| 19 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 20 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 21 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 22 | __inout LPWSTR *ppwzCustomActionData, | ||
| 23 | __out SCA_WEBDIR7** ppswdList | ||
| 24 | ) | ||
| 25 | { | ||
| 26 | HRESULT hr = S_OK; | ||
| 27 | MSIHANDLE hRec; | ||
| 28 | |||
| 29 | LPWSTR pwzData = NULL; | ||
| 30 | SCA_WEBDIR7* pswd; | ||
| 31 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 32 | |||
| 33 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 34 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebDirsRead7"); | ||
| 35 | |||
| 36 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 37 | { | ||
| 38 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallWebDirs7() because IIsWebDir table not present"); | ||
| 39 | ExitFunction1(hr = S_FALSE); | ||
| 40 | } | ||
| 41 | |||
| 42 | // loop through all the web directories | ||
| 43 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 44 | { | ||
| 45 | hr = AddWebDirToList(ppswdList); | ||
| 46 | ExitOnFailure(hr, "failed to add web dir to list"); | ||
| 47 | |||
| 48 | pswd = *ppswdList; | ||
| 49 | ExitOnNull(pswd, hr, E_INVALIDARG, "No web dir provided"); | ||
| 50 | |||
| 51 | // get component install state | ||
| 52 | hr = WcaGetRecordString(hRec, wdqComponent, &pwzData); | ||
| 53 | ExitOnFailure(hr, "Failed to get Component for WebDirs"); | ||
| 54 | hr = ::StringCchCopyW(pswd->wzComponent, countof(pswd->wzComponent), pwzData); | ||
| 55 | ExitOnFailure(hr, "Failed to copy component string to webdir object"); | ||
| 56 | |||
| 57 | hr = WcaGetRecordInteger(hRec, wdqInstalled, (int *)&pswd->isInstalled); | ||
| 58 | ExitOnFailure(hr, "Failed to get Component installed state for webdir"); | ||
| 59 | |||
| 60 | hr = WcaGetRecordInteger(hRec, wdqAction, (int *)&pswd->isAction); | ||
| 61 | ExitOnFailure(hr, "Failed to get Component action state for webdir"); | ||
| 62 | |||
| 63 | hr = WcaGetRecordString(hRec, wdqWeb, &pwzData); | ||
| 64 | ExitOnFailure(hr, "Failed to get Web for WebDir"); | ||
| 65 | |||
| 66 | // get the web key | ||
| 67 | hr = ScaWebsGetBase7(pswList, pwzData, pswd->wzWebSite, countof(pswd->wzWebSite)); | ||
| 68 | if (S_FALSE == hr) | ||
| 69 | { | ||
| 70 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 71 | ExitOnFailure(hr, "Failed to get base of web for WebDir"); | ||
| 72 | } | ||
| 73 | ExitOnFailure(hr, "Failed to format webdir root string"); | ||
| 74 | |||
| 75 | hr = WcaGetRecordString(hRec, wdqPath, &pwzData); | ||
| 76 | ExitOnFailure(hr, "Failed to get Path for WebDir"); | ||
| 77 | |||
| 78 | hr = ::StringCchCopyW(pswd->wzPath, countof(pswd->wzPath), pwzData); | ||
| 79 | ExitOnFailure(hr, "Failed to copy path for WebDir"); | ||
| 80 | |||
| 81 | // get the directory properties for this web | ||
| 82 | hr = WcaGetRecordString(hRec, wdqProperties, &pwzData); | ||
| 83 | ExitOnFailure(hr, "Failed to get security identifier for WebDir"); | ||
| 84 | if (*pwzData) | ||
| 85 | { | ||
| 86 | hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pswd->swp); | ||
| 87 | ExitOnFailure(hr, "Failed to get properties for WebDir"); | ||
| 88 | |||
| 89 | pswd->fHasProperties = TRUE; | ||
| 90 | } | ||
| 91 | |||
| 92 | // get the application information for this web directory | ||
| 93 | hr = WcaGetRecordString(hRec, wdqApplication, &pwzData); | ||
| 94 | ExitOnFailure(hr, "Failed to get application identifier for WebDir"); | ||
| 95 | if (*pwzData) | ||
| 96 | { | ||
| 97 | hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pswd->swapp); | ||
| 98 | ExitOnFailure(hr, "Failed to get application for WebDir"); | ||
| 99 | |||
| 100 | pswd->fHasApplication = TRUE; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | if (E_NOMOREITEMS == hr) | ||
| 105 | { | ||
| 106 | hr = S_OK; | ||
| 107 | } | ||
| 108 | ExitOnFailure(hr, "Failure while processing WebDirs"); | ||
| 109 | |||
| 110 | LExit: | ||
| 111 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 112 | |||
| 113 | ReleaseStr(pwzData); | ||
| 114 | |||
| 115 | return hr; | ||
| 116 | } | ||
| 117 | |||
| 118 | |||
| 119 | HRESULT ScaWebDirsInstall7(SCA_WEBDIR7* pswdList, SCA_APPPOOL * psapList) | ||
| 120 | { | ||
| 121 | HRESULT hr = S_OK; | ||
| 122 | SCA_WEBDIR7* pswd = pswdList; | ||
| 123 | |||
| 124 | while (pswd) | ||
| 125 | { | ||
| 126 | // if we are installing the web site | ||
| 127 | if (WcaIsInstalling(pswd->isInstalled, pswd->isAction)) | ||
| 128 | { | ||
| 129 | hr = ScaWriteConfigID(IIS_WEBDIR); | ||
| 130 | ExitOnFailure(hr, "Failed to write WebDir ID"); | ||
| 131 | |||
| 132 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 133 | ExitOnFailure(hr, "Failed to write WebDir action ID"); | ||
| 134 | |||
| 135 | hr = ScaWriteConfigString(pswd->wzWebSite); | ||
| 136 | ExitOnFailure(hr, "Failed to write WebDir site"); | ||
| 137 | |||
| 138 | hr = ScaWriteConfigString(pswd->wzPath); | ||
| 139 | ExitOnFailure(hr, "Failed to write WebDir path"); | ||
| 140 | |||
| 141 | // get the security information for this web | ||
| 142 | if (pswd->fHasProperties) | ||
| 143 | { | ||
| 144 | ScaWriteWebDirProperties7(pswd->wzWebSite, pswd->wzPath, &pswd->swp); | ||
| 145 | ExitOnFailure(hr, "Failed to write properties for WebDir"); | ||
| 146 | } | ||
| 147 | |||
| 148 | // get the application information for this web directory | ||
| 149 | if (pswd->fHasApplication) | ||
| 150 | { | ||
| 151 | hr = ScaWriteWebApplication7(pswd->wzWebSite, pswd->wzPath, &pswd->swapp, psapList); | ||
| 152 | ExitOnFailure(hr, "Failed to write application for WebDir"); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | pswd = pswd->pswdNext; | ||
| 157 | } | ||
| 158 | |||
| 159 | LExit: | ||
| 160 | return hr; | ||
| 161 | } | ||
| 162 | |||
| 163 | |||
| 164 | HRESULT ScaWebDirsUninstall7(SCA_WEBDIR7* pswdList) | ||
| 165 | { | ||
| 166 | HRESULT hr = S_OK; | ||
| 167 | SCA_WEBDIR7* pswd = pswdList; | ||
| 168 | |||
| 169 | while (pswd) | ||
| 170 | { | ||
| 171 | if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction)) | ||
| 172 | { | ||
| 173 | hr = ScaWriteConfigID(IIS_WEBDIR); | ||
| 174 | ExitOnFailure(hr, "Failed to write WebDir ID"); | ||
| 175 | |||
| 176 | hr = ScaWriteConfigID(IIS_DELETE); | ||
| 177 | ExitOnFailure(hr, "Failed to write WebDir action ID"); | ||
| 178 | |||
| 179 | hr = ScaWriteConfigString(pswd->wzWebSite); | ||
| 180 | ExitOnFailure(hr, "Failed to write WebDir site"); | ||
| 181 | |||
| 182 | hr = ScaWriteConfigString(pswd->wzPath); | ||
| 183 | ExitOnFailure(hr, "Failed to write WebDir path"); | ||
| 184 | } | ||
| 185 | |||
| 186 | pswd = pswd->pswdNext; | ||
| 187 | } | ||
| 188 | |||
| 189 | LExit: | ||
| 190 | return hr; | ||
| 191 | } | ||
| 192 | |||
| 193 | |||
| 194 | void ScaWebDirsFreeList7(SCA_WEBDIR7* pswdList) | ||
| 195 | { | ||
| 196 | SCA_WEBDIR7* pswdDelete = pswdList; | ||
| 197 | while (pswdList) | ||
| 198 | { | ||
| 199 | pswdDelete = pswdList; | ||
| 200 | pswdList = pswdList->pswdNext; | ||
| 201 | |||
| 202 | MemFree(pswdDelete); | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | static HRESULT AddWebDirToList(SCA_WEBDIR7** ppswdList) | ||
| 208 | { | ||
| 209 | HRESULT hr = S_OK; | ||
| 210 | |||
| 211 | SCA_WEBDIR7* pswd = static_cast<SCA_WEBDIR7*>(MemAlloc(sizeof(SCA_WEBDIR7), TRUE)); | ||
| 212 | ExitOnNull(pswd, hr, E_OUTOFMEMORY, "failed to allocate element for web dir list"); | ||
| 213 | |||
| 214 | pswd->pswdNext = *ppswdList; | ||
| 215 | *ppswdList = pswd; | ||
| 216 | |||
| 217 | LExit: | ||
| 218 | return hr; | ||
| 219 | } | ||
diff --git a/src/ext/Iis/ca/scawebdir7.h b/src/ext/Iis/ca/scawebdir7.h new file mode 100644 index 00000000..c5c87e17 --- /dev/null +++ b/src/ext/Iis/ca/scawebdir7.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | struct SCA_WEBDIR7 | ||
| 6 | { | ||
| 7 | // darwin information | ||
| 8 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 9 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 10 | INSTALLSTATE isInstalled; | ||
| 11 | INSTALLSTATE isAction; | ||
| 12 | |||
| 13 | |||
| 14 | // iis configuation information | ||
| 15 | WCHAR wzPath[MAX_PATH]; | ||
| 16 | WCHAR wzWebSite[MAX_PATH]; | ||
| 17 | |||
| 18 | BOOL fHasProperties; | ||
| 19 | SCA_WEB_PROPERTIES swp; | ||
| 20 | |||
| 21 | BOOL fHasApplication; | ||
| 22 | SCA_WEB_APPLICATION swapp; | ||
| 23 | |||
| 24 | SCA_WEBDIR7* pswdNext; | ||
| 25 | }; | ||
| 26 | |||
| 27 | |||
| 28 | // prototypes | ||
| 29 | UINT __stdcall ScaWebDirsRead7( | ||
| 30 | __in SCA_WEB7* pswList, | ||
| 31 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 32 | __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, | ||
| 33 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 34 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 35 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 36 | __inout LPWSTR *ppwzCustomActionData, | ||
| 37 | __out SCA_WEBDIR7** ppswdList | ||
| 38 | ); | ||
| 39 | |||
| 40 | HRESULT ScaWebDirsInstall7( | ||
| 41 | __in SCA_WEBDIR7* pswdList, | ||
| 42 | __in SCA_APPPOOL* psapList | ||
| 43 | ); | ||
| 44 | |||
| 45 | HRESULT ScaWebDirsUninstall7( | ||
| 46 | __in SCA_WEBDIR7* pswdList | ||
| 47 | ); | ||
| 48 | |||
| 49 | void ScaWebDirsFreeList7( | ||
| 50 | __in SCA_WEBDIR7* pswdList | ||
| 51 | ); | ||
diff --git a/src/ext/Iis/ca/scaweberr.cpp b/src/ext/Iis/ca/scaweberr.cpp new file mode 100644 index 00000000..2441f006 --- /dev/null +++ b/src/ext/Iis/ca/scaweberr.cpp | |||
| @@ -0,0 +1,371 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | enum eWebErrorQuery { weqErrorCode = 1, weqSubCode, weqParentType, weqParentValue, weqFile, weqURL }; | ||
| 6 | |||
| 7 | static HRESULT AddWebErrorToList(SCA_WEB_ERROR** ppsweList); | ||
| 8 | |||
| 9 | void ScaWebErrorFreeList(SCA_WEB_ERROR *psweList) | ||
| 10 | { | ||
| 11 | SCA_WEB_ERROR *psweDelete = psweList; | ||
| 12 | while (psweList) | ||
| 13 | { | ||
| 14 | psweDelete = psweList; | ||
| 15 | psweList = psweList->psweNext; | ||
| 16 | |||
| 17 | MemFree(psweDelete); | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | HRESULT ScaWebErrorRead( | ||
| 22 | SCA_WEB_ERROR **ppsweList, | ||
| 23 | __inout LPWSTR *ppwzCustomActionData | ||
| 24 | ) | ||
| 25 | { | ||
| 26 | // AssertSz(0, "Debug ScaWebErrorRead here"); | ||
| 27 | HRESULT hr = S_OK; | ||
| 28 | MSIHANDLE hRec; | ||
| 29 | LPWSTR pwzData = NULL; | ||
| 30 | SCA_WEB_ERROR* pswe; | ||
| 31 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 32 | |||
| 33 | ExitOnNull(ppsweList, hr, E_INVALIDARG, "Failed to read web error, because no web error was provided to read"); | ||
| 34 | |||
| 35 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 36 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 37 | |||
| 38 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 39 | { | ||
| 40 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebErrorRead() - required tables not present."); | ||
| 41 | ExitFunction1(hr = S_FALSE); | ||
| 42 | } | ||
| 43 | |||
| 44 | // loop through all the web errors | ||
| 45 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 46 | { | ||
| 47 | hr = AddWebErrorToList(ppsweList); | ||
| 48 | ExitOnFailure(hr, "failed to add web error to list"); | ||
| 49 | |||
| 50 | pswe = *ppsweList; | ||
| 51 | |||
| 52 | hr = WcaGetRecordInteger(hRec, weqErrorCode, &(pswe->iErrorCode)); | ||
| 53 | ExitOnFailure(hr, "failed to get IIsWebError.ErrorCode"); | ||
| 54 | |||
| 55 | hr = WcaGetRecordInteger(hRec, weqSubCode, &(pswe->iSubCode)); | ||
| 56 | ExitOnFailure(hr, "failed to get IIsWebError.SubCode"); | ||
| 57 | |||
| 58 | hr = WcaGetRecordInteger(hRec, weqParentType, &(pswe->iParentType)); | ||
| 59 | ExitOnFailure(hr, "failed to get IIsWebError.ParentType"); | ||
| 60 | |||
| 61 | hr = WcaGetRecordString(hRec, weqParentValue, &pwzData); | ||
| 62 | ExitOnFailure(hr, "Failed to get IIsWebError.ParentValue"); | ||
| 63 | hr = ::StringCchCopyW(pswe->wzParentValue, countof(pswe->wzParentValue), pwzData); | ||
| 64 | ExitOnFailure(hr, "Failed to copy IIsWebError.ParentValue"); | ||
| 65 | |||
| 66 | hr = WcaGetRecordString(hRec, weqFile, &pwzData); | ||
| 67 | ExitOnFailure(hr, "Failed to get IIsWebError.File"); | ||
| 68 | hr = ::StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), pwzData); | ||
| 69 | ExitOnFailure(hr, "Failed to copy IIsWebError.File"); | ||
| 70 | |||
| 71 | hr = WcaGetRecordString(hRec, weqURL, &pwzData); | ||
| 72 | ExitOnFailure(hr, "Failed to get IIsWebError.URL"); | ||
| 73 | hr = ::StringCchCopyW(pswe->wzURL, countof(pswe->wzURL), pwzData); | ||
| 74 | ExitOnFailure(hr, "Failed to copy IIsWebError.URL"); | ||
| 75 | |||
| 76 | // If they've specified both a file and a URL, that's invalid | ||
| 77 | if (*(pswe->wzFile) && *(pswe->wzURL)) | ||
| 78 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA), "Both File and URL specified for web error. File: %ls, URL: %ls", pswe->wzFile, pswe->wzURL); | ||
| 79 | } | ||
| 80 | |||
| 81 | if (E_NOMOREITEMS == hr) | ||
| 82 | { | ||
| 83 | hr = S_OK; | ||
| 84 | } | ||
| 85 | ExitOnFailure(hr, "Failure while processing web errors"); | ||
| 86 | |||
| 87 | LExit: | ||
| 88 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 89 | |||
| 90 | ReleaseStr(pwzData); | ||
| 91 | |||
| 92 | return hr; | ||
| 93 | } | ||
| 94 | |||
| 95 | HRESULT ScaGetWebError(int iParentType, LPCWSTR wzParentValue, SCA_WEB_ERROR **ppsweList, SCA_WEB_ERROR **ppsweOut) | ||
| 96 | { | ||
| 97 | HRESULT hr = S_OK; | ||
| 98 | SCA_WEB_ERROR* psweAdd = NULL; | ||
| 99 | SCA_WEB_ERROR* psweLast = NULL; | ||
| 100 | |||
| 101 | *ppsweOut = NULL; | ||
| 102 | |||
| 103 | if (!*ppsweList) | ||
| 104 | return hr; | ||
| 105 | |||
| 106 | SCA_WEB_ERROR* pswe = *ppsweList; | ||
| 107 | while (pswe) | ||
| 108 | { | ||
| 109 | if (iParentType == pswe->iParentType && 0 == lstrcmpW(wzParentValue, pswe->wzParentValue)) | ||
| 110 | { | ||
| 111 | // Found a match, take this one out of the list and add it to the matched out list | ||
| 112 | psweAdd = pswe; | ||
| 113 | |||
| 114 | if (psweLast) | ||
| 115 | { | ||
| 116 | // If we're not at the beginning of the list tell the last node about it's new next (since we're taking away it's current next) | ||
| 117 | psweLast->psweNext = psweAdd->psweNext; | ||
| 118 | } | ||
| 119 | else | ||
| 120 | { | ||
| 121 | // If we are at the beginning (no psweLast) update the beginning (since we're taking it) | ||
| 122 | *ppsweList = pswe->psweNext; | ||
| 123 | } | ||
| 124 | pswe = pswe->psweNext; // move on | ||
| 125 | |||
| 126 | // Add the one we've removed to the beginning of the out list | ||
| 127 | psweAdd->psweNext = *ppsweOut; | ||
| 128 | *ppsweOut = psweAdd; | ||
| 129 | } | ||
| 130 | else | ||
| 131 | { | ||
| 132 | psweLast = pswe; // remember the last we that didn't match | ||
| 133 | pswe = pswe->psweNext; // move on | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | return hr; | ||
| 138 | } | ||
| 139 | |||
| 140 | HRESULT ScaWriteWebError(IMSAdminBase* piMetabase, int iParentType, LPCWSTR wzRoot, SCA_WEB_ERROR* psweList) | ||
| 141 | { | ||
| 142 | // AssertSz(0, "Debug ScaWriteWebError here"); | ||
| 143 | Assert(*wzRoot && psweList); | ||
| 144 | |||
| 145 | HRESULT hr = S_OK; | ||
| 146 | |||
| 147 | DWORD cchData = 0; | ||
| 148 | LPWSTR pwzSearchKey = NULL; | ||
| 149 | LPWSTR pwz = NULL; | ||
| 150 | LPWSTR pwzErrors = NULL; | ||
| 151 | |||
| 152 | LPWSTR pwzCodeSubCode = NULL; | ||
| 153 | LPWSTR pwzAcceptableCodeSubCode = NULL; | ||
| 154 | LPCWSTR wzFoundCodeSubCode = NULL; | ||
| 155 | DWORD_PTR dwFoundCodeSubCodeIndex = 0xFFFFFFFF; | ||
| 156 | BOOL fOldValueFound = FALSE; | ||
| 157 | LPWSTR pwzAcceptableErrors = NULL; | ||
| 158 | |||
| 159 | LPWSTR pwzNewError = NULL; | ||
| 160 | |||
| 161 | METADATA_RECORD mr; | ||
| 162 | ::ZeroMemory(&mr, sizeof(mr)); | ||
| 163 | |||
| 164 | ExitOnNull(piMetabase, hr, E_INVALIDARG, "Failed to write web error, because no metabase was provided"); | ||
| 165 | ExitOnNull(wzRoot, hr, E_INVALIDARG, "Failed to write web error, because no root was provided"); | ||
| 166 | |||
| 167 | // get the set of all valid custom errors from the metabase | ||
| 168 | mr.dwMDIdentifier = MD_CUSTOM_ERROR_DESC; | ||
| 169 | mr.dwMDAttributes = METADATA_INHERIT; | ||
| 170 | mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 171 | mr.dwMDDataType = ALL_METADATA; | ||
| 172 | mr.dwMDDataLen = cchData = 0; | ||
| 173 | mr.pbMDData = NULL; | ||
| 174 | |||
| 175 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/Info", &mr); | ||
| 176 | ExitOnFailure(hr, "Unable to get set of acceptable error codes for this server."); | ||
| 177 | |||
| 178 | pwzAcceptableErrors = reinterpret_cast<LPWSTR>(mr.pbMDData); | ||
| 179 | |||
| 180 | // Check if web errors already exist here | ||
| 181 | mr.dwMDIdentifier = MD_CUSTOM_ERROR; | ||
| 182 | mr.dwMDAttributes = METADATA_INHERIT; | ||
| 183 | mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 184 | mr.dwMDDataType = ALL_METADATA; | ||
| 185 | mr.dwMDDataLen = cchData = 0; | ||
| 186 | mr.pbMDData = NULL; | ||
| 187 | |||
| 188 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzRoot, &mr); | ||
| 189 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr) | ||
| 190 | { | ||
| 191 | // | ||
| 192 | // If we don't have one already, find an appropriate one to start with | ||
| 193 | // | ||
| 194 | |||
| 195 | // we can walk up key by key and look for custom errors to inherit | ||
| 196 | |||
| 197 | hr = StrAllocConcat(&pwzSearchKey, wzRoot, 0); | ||
| 198 | ExitOnFailure(hr, "Failed to copy root string: %ls", wzRoot); | ||
| 199 | |||
| 200 | pwz = pwzSearchKey + lstrlenW(pwzSearchKey); | ||
| 201 | |||
| 202 | while (NULL == pwzErrors) | ||
| 203 | { | ||
| 204 | // find the last slash | ||
| 205 | while (*pwz != '/' && pwz != pwzSearchKey) | ||
| 206 | pwz --; | ||
| 207 | |||
| 208 | if (pwz == pwzSearchKey) | ||
| 209 | break; | ||
| 210 | |||
| 211 | *pwz = L'\0'; | ||
| 212 | |||
| 213 | // Try here. If it's not found, keep walking up the path | ||
| 214 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, pwzSearchKey, &mr); | ||
| 215 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr) | ||
| 216 | hr = S_FALSE; | ||
| 217 | ExitOnFailure(hr, "failed to discover default error values to start with for web root: %ls while walking up the tree", wzRoot); | ||
| 218 | |||
| 219 | if (S_OK == hr) | ||
| 220 | { | ||
| 221 | pwzErrors = reinterpret_cast<LPWSTR>(mr.pbMDData); | ||
| 222 | break; | ||
| 223 | } | ||
| 224 | |||
| 225 | // Don't keep going if we're at the root | ||
| 226 | if (0 == lstrcmpW(pwz + 1, L"W3SVC")) | ||
| 227 | break; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | else | ||
| 231 | { | ||
| 232 | pwzErrors = reinterpret_cast<LPWSTR>(mr.pbMDData); | ||
| 233 | } | ||
| 234 | ExitOnFailure(hr, "failed to discover default error values to start with for web root: %ls", wzRoot); | ||
| 235 | |||
| 236 | // The above code should have come up with some value to start pwzErrors off with. Make sure it did. | ||
| 237 | if (NULL == pwzErrors) | ||
| 238 | { | ||
| 239 | ExitOnFailure(hr = E_UNEXPECTED, "failed to discover default error values to start with for web root: %ls", wzRoot); | ||
| 240 | } | ||
| 241 | |||
| 242 | // Loop through the web errors | ||
| 243 | for (SCA_WEB_ERROR* pswe = psweList; pswe; pswe = pswe->psweNext) | ||
| 244 | { | ||
| 245 | // Assume that we will have to replace | ||
| 246 | fOldValueFound = TRUE; | ||
| 247 | |||
| 248 | // If the subcode is 0, that means "*" in MD_CUSTOM_ERROR (thus the special formatting logic) | ||
| 249 | if (0 == pswe->iSubCode) | ||
| 250 | { | ||
| 251 | hr = StrAllocFormatted(&pwzCodeSubCode, L"%d,*", pswe->iErrorCode); | ||
| 252 | ExitOnFailure(hr, "failed to create error code string while installing web error"); | ||
| 253 | } | ||
| 254 | else | ||
| 255 | { | ||
| 256 | hr = StrAllocFormatted(&pwzCodeSubCode, L"%d,%d", pswe->iErrorCode, pswe->iSubCode); | ||
| 257 | ExitOnFailure(hr, "failed to create error code,subcode string while installing web error"); | ||
| 258 | } | ||
| 259 | |||
| 260 | hr = MultiSzFindSubstring(pwzErrors, pwzCodeSubCode, &dwFoundCodeSubCodeIndex, &wzFoundCodeSubCode); | ||
| 261 | ExitOnFailure(hr, "failed to find existing error code,subcode: %ls", pwzCodeSubCode); | ||
| 262 | |||
| 263 | // If we didn't find this error code/sub code pair in the list already, make sure it's acceptable to add | ||
| 264 | if (S_FALSE == hr) | ||
| 265 | { | ||
| 266 | // | ||
| 267 | // Make sure this error code/sub code pair is in the "acceptable" list | ||
| 268 | // | ||
| 269 | |||
| 270 | // If the subcode is 0, that means "0" in MD_CUSTOM_ERROR_DESC (no special formatting logic needed) | ||
| 271 | hr = StrAllocFormatted(&pwzAcceptableCodeSubCode, L"%d,%d", pswe->iErrorCode, pswe->iSubCode); | ||
| 272 | ExitOnFailure(hr, "failed to create error code,subcode string while installing web error"); | ||
| 273 | |||
| 274 | // We don't care where it is, just whether it's there or not | ||
| 275 | hr = MultiSzFindSubstring(pwzAcceptableErrors, pwzAcceptableCodeSubCode, NULL, NULL); | ||
| 276 | ExitOnFailure(hr, "failed to find whether or not error code, subcode: %ls is supported", pwzCodeSubCode); | ||
| 277 | |||
| 278 | if (S_FALSE == hr) | ||
| 279 | { | ||
| 280 | WcaLog(LOGMSG_VERBOSE, "Skipping error code, subcode: %ls because it is not supported by the server.", pwzCodeSubCode); | ||
| 281 | continue; | ||
| 282 | } | ||
| 283 | |||
| 284 | // If we didn't find it (and its an acceptable error) then we have nothing to replace | ||
| 285 | fOldValueFound = FALSE; | ||
| 286 | } | ||
| 287 | |||
| 288 | // Set up the new error string if needed | ||
| 289 | if (*(pswe->wzFile)) | ||
| 290 | { | ||
| 291 | hr = StrAllocFormatted(&pwzNewError, L"%s,FILE,%s", pwzCodeSubCode, pswe->wzFile); | ||
| 292 | ExitOnFailure(hr, "failed to create new error code string with code,subcode: %ls, file: %ls", pwzCodeSubCode, pswe->wzFile); | ||
| 293 | } | ||
| 294 | else if (*(pswe->wzURL)) | ||
| 295 | { | ||
| 296 | hr = StrAllocFormatted(&pwzNewError, L"%s,URL,%s", pwzCodeSubCode, pswe->wzURL); | ||
| 297 | ExitOnFailure(hr, "failed to create new error code string with code,subcode: %ls, file: %ls", pwzCodeSubCode, pswe->wzFile); | ||
| 298 | } | ||
| 299 | else if (fOldValueFound) | ||
| 300 | { | ||
| 301 | // If no File or URL was specified, they want a default error so remove the old value from the MULTISZ and move on | ||
| 302 | hr = MultiSzRemoveString(&pwzErrors, dwFoundCodeSubCodeIndex); | ||
| 303 | ExitOnFailure(hr, "failed to remove string for error code sub code: %ls in order to make it 'default'", pwzCodeSubCode); | ||
| 304 | continue; | ||
| 305 | } | ||
| 306 | |||
| 307 | // If we have something to replace, replace it, otherwise, put it at the beginning (order shouldn't matter) | ||
| 308 | if (fOldValueFound) | ||
| 309 | { | ||
| 310 | hr = MultiSzReplaceString(&pwzErrors, dwFoundCodeSubCodeIndex, pwzNewError); | ||
| 311 | ExitOnFailure(hr, "failed to replace old error string with new error string for error code,subcode: %ls", pwzCodeSubCode); | ||
| 312 | } | ||
| 313 | else | ||
| 314 | { | ||
| 315 | hr = MultiSzPrepend(&pwzErrors, NULL, pwzNewError); | ||
| 316 | ExitOnFailure(hr, "failed to prepend new error string for error code,subcode: %ls", pwzCodeSubCode); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | // now write the CustomErrors to the metabase | ||
| 321 | if (weptWeb == iParentType) | ||
| 322 | { | ||
| 323 | hr = ScaWriteMetabaseValue(piMetabase, wzRoot, L"/Root", MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzErrors); | ||
| 324 | ExitOnFailure(hr, "Failed to write Web Error to /Root"); | ||
| 325 | } | ||
| 326 | else | ||
| 327 | { | ||
| 328 | hr = ScaWriteMetabaseValue(piMetabase, wzRoot, NULL, MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzErrors); | ||
| 329 | ExitOnFailure(hr, "Failed to write Web Error"); | ||
| 330 | } | ||
| 331 | |||
| 332 | LExit: | ||
| 333 | ReleaseStr(pwzErrors); | ||
| 334 | ReleaseStr(pwzSearchKey); | ||
| 335 | ReleaseStr(pwzCodeSubCode); | ||
| 336 | ReleaseStr(pwzAcceptableCodeSubCode); | ||
| 337 | ReleaseStr(pwzAcceptableErrors); | ||
| 338 | |||
| 339 | return hr; | ||
| 340 | } | ||
| 341 | |||
| 342 | static HRESULT AddWebErrorToList(SCA_WEB_ERROR** ppsweList) | ||
| 343 | { | ||
| 344 | HRESULT hr = S_OK; | ||
| 345 | |||
| 346 | SCA_WEB_ERROR* pswe = static_cast<SCA_WEB_ERROR*>(MemAlloc(sizeof(SCA_WEB_ERROR), TRUE)); | ||
| 347 | ExitOnNull(pswe, hr, E_OUTOFMEMORY, "failed to allocate memory for new web error list element"); | ||
| 348 | |||
| 349 | pswe->psweNext = *ppsweList; | ||
| 350 | *ppsweList = pswe; | ||
| 351 | |||
| 352 | LExit: | ||
| 353 | return hr; | ||
| 354 | } | ||
| 355 | |||
| 356 | HRESULT ScaWebErrorCheckList(SCA_WEB_ERROR* psweList) | ||
| 357 | { | ||
| 358 | if (!psweList) | ||
| 359 | { | ||
| 360 | return S_OK; | ||
| 361 | } | ||
| 362 | |||
| 363 | while (psweList) | ||
| 364 | { | ||
| 365 | WcaLog(LOGMSG_STANDARD, "WebError code: %d subcode: %d for parent: %ls not used!", psweList->iErrorCode, psweList->iSubCode, psweList->wzParentValue); | ||
| 366 | psweList = psweList->psweNext; | ||
| 367 | } | ||
| 368 | |||
| 369 | return E_FAIL; | ||
| 370 | } | ||
| 371 | |||
diff --git a/src/ext/Iis/ca/scaweberr.h b/src/ext/Iis/ca/scaweberr.h new file mode 100644 index 00000000..ad8ff4f5 --- /dev/null +++ b/src/ext/Iis/ca/scaweberr.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | enum eWebErrorParentType { weptVDir = 1, weptWeb }; | ||
| 6 | |||
| 7 | struct SCA_WEB_ERROR | ||
| 8 | { | ||
| 9 | int iErrorCode; | ||
| 10 | int iSubCode; | ||
| 11 | |||
| 12 | int iParentType; | ||
| 13 | WCHAR wzParentValue[MAX_DARWIN_KEY + 1]; | ||
| 14 | |||
| 15 | WCHAR wzFile[MAX_PATH]; | ||
| 16 | WCHAR wzURL[MAX_PATH]; // TODO: this needs to be bigger than MAX_PATH | ||
| 17 | |||
| 18 | SCA_WEB_ERROR *psweNext; | ||
| 19 | }; | ||
| 20 | |||
| 21 | // prototypes | ||
| 22 | HRESULT ScaWebErrorRead( | ||
| 23 | SCA_WEB_ERROR **ppsweList, | ||
| 24 | __inout LPWSTR *ppwzCustomActionData | ||
| 25 | ); | ||
| 26 | void ScaWebErrorFreeList(SCA_WEB_ERROR *psweList); | ||
| 27 | HRESULT ScaWebErrorCheckList(SCA_WEB_ERROR* psweList); | ||
| 28 | HRESULT ScaGetWebError(int iParentType, LPCWSTR wzParentValue, SCA_WEB_ERROR **ppsweList, SCA_WEB_ERROR **ppsweOut); | ||
| 29 | HRESULT ScaWriteWebError(IMSAdminBase* piMetabase, int iParentType, LPCWSTR wzRoot, SCA_WEB_ERROR* psweList); | ||
| 30 | |||
diff --git a/src/ext/Iis/ca/scaweberr7.cpp b/src/ext/Iis/ca/scaweberr7.cpp new file mode 100644 index 00000000..33c2f1bd --- /dev/null +++ b/src/ext/Iis/ca/scaweberr7.cpp | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | HRESULT ScaWriteWebError7( | ||
| 6 | __in_z LPCWSTR wzWebName, | ||
| 7 | __in_z LPCWSTR wzRoot, | ||
| 8 | SCA_WEB_ERROR* psweList | ||
| 9 | ) | ||
| 10 | { | ||
| 11 | HRESULT hr = S_OK; | ||
| 12 | |||
| 13 | hr = ScaWriteConfigID(IIS_WEBERROR_BEGIN); | ||
| 14 | ExitOnFailure(hr, "Fail to write webError begin ID"); | ||
| 15 | |||
| 16 | hr = ScaWriteConfigString(wzWebName); | ||
| 17 | ExitOnFailure(hr, "Fail to write webError Web Key"); | ||
| 18 | |||
| 19 | hr = ScaWriteConfigString(wzRoot); | ||
| 20 | ExitOnFailure(hr, "Fail to write webError Vdir key"); | ||
| 21 | |||
| 22 | // Loop through the HTTP headers | ||
| 23 | for (SCA_WEB_ERROR* pswe = psweList; pswe; pswe = pswe->psweNext) | ||
| 24 | { | ||
| 25 | hr = ScaWriteConfigID(IIS_WEBERROR); | ||
| 26 | ExitOnFailure(hr, "Fail to write webError ID"); | ||
| 27 | |||
| 28 | hr = ScaWriteConfigInteger(pswe->iErrorCode); | ||
| 29 | ExitOnFailure(hr, "Fail to write webError code"); | ||
| 30 | |||
| 31 | hr = ScaWriteConfigInteger(pswe->iSubCode); | ||
| 32 | ExitOnFailure(hr, "Fail to write webError subcode"); | ||
| 33 | |||
| 34 | //just write one | ||
| 35 | if (*(pswe->wzFile)) | ||
| 36 | { | ||
| 37 | hr = ScaWriteConfigString(pswe->wzFile); | ||
| 38 | ExitOnFailure(hr, "Fail to write webError file"); | ||
| 39 | hr = ScaWriteConfigInteger(0); | ||
| 40 | ExitOnFailure(hr, "Fail to write webError file code"); | ||
| 41 | } | ||
| 42 | else if (*(pswe->wzURL)) | ||
| 43 | { | ||
| 44 | hr = ScaWriteConfigString(pswe->wzURL); | ||
| 45 | ExitOnFailure(hr, "Fail to write webError URL"); | ||
| 46 | hr = ScaWriteConfigInteger(1); | ||
| 47 | ExitOnFailure(hr, "Fail to write webError URL code"); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | hr = ScaWriteConfigID(IIS_WEBERROR_END); | ||
| 52 | ExitOnFailure(hr, "Fail to write httpHeader end ID"); | ||
| 53 | |||
| 54 | LExit: | ||
| 55 | return hr; | ||
| 56 | |||
| 57 | } | ||
| 58 | |||
| 59 | //static HRESULT AddWebErrorToList(SCA_WEB_ERROR** ppsweList) | ||
| 60 | //{ | ||
| 61 | // HRESULT hr = S_OK; | ||
| 62 | // | ||
| 63 | // SCA_WEB_ERROR* pswe = static_cast<SCA_WEB_ERROR*>(MemAlloc(sizeof(SCA_WEB_ERROR), TRUE)); | ||
| 64 | // ExitOnNull(pswe, hr, E_OUTOFMEMORY, "failed to allocate memory for new web error list element"); | ||
| 65 | // | ||
| 66 | // pswe->psweNext = *ppsweList; | ||
| 67 | // *ppsweList = pswe; | ||
| 68 | // | ||
| 69 | //LExit: | ||
| 70 | // return hr; | ||
| 71 | //} | ||
| 72 | |||
| 73 | HRESULT ScaWebErrorCheckList7(SCA_WEB_ERROR* psweList) | ||
| 74 | { | ||
| 75 | if (!psweList) | ||
| 76 | { | ||
| 77 | return S_OK; | ||
| 78 | } | ||
| 79 | |||
| 80 | while (psweList) | ||
| 81 | { | ||
| 82 | WcaLog(LOGMSG_STANDARD, "WebError code: %d subcode: %d for parent: %ls not used!", psweList->iErrorCode, psweList->iSubCode, psweList->wzParentValue); | ||
| 83 | psweList = psweList->psweNext; | ||
| 84 | } | ||
| 85 | |||
| 86 | return E_FAIL; | ||
| 87 | } | ||
| 88 | |||
diff --git a/src/ext/Iis/ca/scaweberr7.h b/src/ext/Iis/ca/scaweberr7.h new file mode 100644 index 00000000..62448211 --- /dev/null +++ b/src/ext/Iis/ca/scaweberr7.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaWriteWebError7( | ||
| 6 | __in_z LPCWSTR wzWebName, | ||
| 7 | __in_z LPCWSTR wzRoot, | ||
| 8 | SCA_WEB_ERROR* psweList | ||
| 9 | ); | ||
| 10 | |||
diff --git a/src/ext/Iis/ca/scaweblog.cpp b/src/ext/Iis/ca/scaweblog.cpp new file mode 100644 index 00000000..01147848 --- /dev/null +++ b/src/ext/Iis/ca/scaweblog.cpp | |||
| @@ -0,0 +1,177 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | enum eWebLogQuery { wlqLog = 1, wlqFormat }; | ||
| 6 | |||
| 7 | /* **************************************************************** | ||
| 8 | * LookupLogFormatGUID -Looks up a given IIS Log format type in | ||
| 9 | * the metabase and returns the GUID for it. | ||
| 10 | * ****************************************************************/ | ||
| 11 | static HRESULT LookupLogFormatGUID( | ||
| 12 | __in IMSAdminBase* piMetabase, | ||
| 13 | __in LPCWSTR wzLogFormat, | ||
| 14 | __out_ecount(cchGUID) LPWSTR wzGUID, | ||
| 15 | __in int cchGUID | ||
| 16 | ) | ||
| 17 | { | ||
| 18 | WCHAR wzKey[METADATA_MAX_NAME_LEN]; | ||
| 19 | HRESULT hr = S_OK; | ||
| 20 | |||
| 21 | METADATA_RECORD mrKeyType; | ||
| 22 | ::ZeroMemory(&mrKeyType, sizeof(mrKeyType)); | ||
| 23 | |||
| 24 | mrKeyType.dwMDIdentifier = MD_KEY_TYPE; | ||
| 25 | mrKeyType.dwMDAttributes = METADATA_NO_ATTRIBUTES; | ||
| 26 | mrKeyType.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 27 | mrKeyType.dwMDDataType = ALL_METADATA; | ||
| 28 | mrKeyType.dwMDDataLen = 0; | ||
| 29 | mrKeyType.pbMDData = NULL; | ||
| 30 | |||
| 31 | METADATA_RECORD mrPluginId; | ||
| 32 | ::ZeroMemory(&mrPluginId, sizeof(mrPluginId)); | ||
| 33 | |||
| 34 | mrPluginId.dwMDIdentifier = MD_LOG_PLUGIN_MOD_ID; | ||
| 35 | mrPluginId.dwMDAttributes = METADATA_INHERIT; | ||
| 36 | mrPluginId.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 37 | mrPluginId.dwMDDataType = ALL_METADATA; | ||
| 38 | mrPluginId.dwMDDataLen = 0; | ||
| 39 | mrPluginId.pbMDData = NULL; | ||
| 40 | |||
| 41 | hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/Logging/%s", wzLogFormat); | ||
| 42 | ExitOnFailure(hr, "failed to format logging metabase key name"); | ||
| 43 | |||
| 44 | // verify that we have this log format available in IIS | ||
| 45 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mrKeyType); | ||
| 46 | ExitOnFailure(hr, "Failed to find specified Log format key in IIS for log format: %ls", wzLogFormat); | ||
| 47 | ExitOnNull(mrKeyType.pbMDData, hr, E_POINTER, "Request for Log format key in IIS for log format returned success, but value was NULL"); | ||
| 48 | |||
| 49 | if (0 != lstrcmpW(L"IIsLogModule", (LPCWSTR)mrKeyType.pbMDData)) | ||
| 50 | { | ||
| 51 | ExitOnFailure(hr = E_UNEXPECTED, "Found invalid log format in IIS: %ls", (LPCWSTR)mrKeyType.pbMDData); | ||
| 52 | } | ||
| 53 | |||
| 54 | // find the GUID for that log format | ||
| 55 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mrPluginId); | ||
| 56 | ExitOnFailure(hr, "Failed to retrieve IISLog format GUID. Key: %ls", wzKey); | ||
| 57 | ExitOnNull(mrPluginId.pbMDData, hr, E_POINTER, "Retrieval of IISLog format GUID returned success, but value was NULL"); | ||
| 58 | |||
| 59 | hr = ::StringCchCopyW(wzGUID, cchGUID, (LPCWSTR)mrPluginId.pbMDData); | ||
| 60 | ExitOnFailure(hr, "failed to copy metabase value: %ls", (LPCWSTR)mrPluginId.pbMDData); | ||
| 61 | |||
| 62 | LExit: | ||
| 63 | |||
| 64 | if (mrKeyType.pbMDData) | ||
| 65 | { | ||
| 66 | MetaFreeValue(&mrKeyType); | ||
| 67 | } | ||
| 68 | |||
| 69 | if (mrPluginId.pbMDData) | ||
| 70 | { | ||
| 71 | MetaFreeValue(&mrPluginId); | ||
| 72 | } | ||
| 73 | |||
| 74 | return hr; | ||
| 75 | } | ||
| 76 | |||
| 77 | |||
| 78 | /* **************************************************************** | ||
| 79 | * ScaGetWebLog -Retrieves Log table data for the specified Log key | ||
| 80 | * | ||
| 81 | * ****************************************************************/ | ||
| 82 | HRESULT ScaGetWebLog( | ||
| 83 | IMSAdminBase* piMetabase, | ||
| 84 | LPCWSTR wzLog, | ||
| 85 | __in WCA_WRAPQUERY_HANDLE hWebLogQuery, | ||
| 86 | SCA_WEB_LOG* pswl | ||
| 87 | ) | ||
| 88 | { | ||
| 89 | HRESULT hr = S_OK; | ||
| 90 | LPWSTR pwzData = NULL; | ||
| 91 | MSIHANDLE hRec; | ||
| 92 | |||
| 93 | if (0 == WcaGetQueryRecords(hWebLogQuery)) | ||
| 94 | { | ||
| 95 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaGetWebLog() - no records to process"); | ||
| 96 | ExitFunction1(hr = S_FALSE); | ||
| 97 | } | ||
| 98 | |||
| 99 | WcaFetchWrappedReset(hWebLogQuery); | ||
| 100 | |||
| 101 | hr = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec); | ||
| 102 | if (E_NOMOREITEMS == hr) | ||
| 103 | { | ||
| 104 | ExitOnFailure(hr, "cannot locate IIsWebLog.Log='%ls'", wzLog); | ||
| 105 | } | ||
| 106 | HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec); | ||
| 107 | |||
| 108 | if (SUCCEEDED(hrTemp)) | ||
| 109 | { | ||
| 110 | ExitOnFailure(hr, "error - found multiple matching IIsWebLog rows"); | ||
| 111 | } | ||
| 112 | |||
| 113 | ::ZeroMemory(pswl, sizeof(SCA_WEB_LOG)); | ||
| 114 | |||
| 115 | // check that log key matches | ||
| 116 | hr = WcaGetRecordString(hRec, wlqLog, &pwzData); | ||
| 117 | ExitOnFailure(hr, "failed to get IIsWebLog.Log for Log: %ls", wzLog); | ||
| 118 | hr = ::StringCchCopyW(pswl->wzLog, countof(pswl->wzLog), pwzData); | ||
| 119 | ExitOnFailure(hr, "failed to copy log name: %ls", pwzData); | ||
| 120 | |||
| 121 | hr = WcaGetRecordString(hRec, wlqFormat, &pwzData); | ||
| 122 | ExitOnFailure(hr, "failed to get IIsWebLog.Format for Log:", wzLog); | ||
| 123 | hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), pwzData); | ||
| 124 | ExitOnFailure(hr, "failed to copy log format: %ls", pwzData); | ||
| 125 | |||
| 126 | // if they specified a log format, look up its GUID in the metabase | ||
| 127 | if (*pswl->wzFormat && 0 != lstrcmpW(pswl->wzFormat, L"none")) | ||
| 128 | { | ||
| 129 | hr = LookupLogFormatGUID(piMetabase, pswl->wzFormat, pswl->wzFormatGUID, countof(pswl->wzFormatGUID)); | ||
| 130 | ExitOnFailure(hr, "Failed to get Log Format GUID for Log: %ls", wzLog); | ||
| 131 | } | ||
| 132 | |||
| 133 | LExit: | ||
| 134 | ReleaseStr(pwzData); | ||
| 135 | |||
| 136 | return hr; | ||
| 137 | } | ||
| 138 | |||
| 139 | |||
| 140 | /* **************************************************************** | ||
| 141 | * ScaWriteWebLog -Writes the IIS log values to the metabase. | ||
| 142 | * | ||
| 143 | * ****************************************************************/ | ||
| 144 | HRESULT ScaWriteWebLog( | ||
| 145 | IMSAdminBase* piMetabase, | ||
| 146 | LPCWSTR wzWebBase, | ||
| 147 | SCA_WEB_LOG *pswl | ||
| 148 | ) | ||
| 149 | { | ||
| 150 | HRESULT hr = S_OK; | ||
| 151 | |||
| 152 | if (*pswl->wzFormat) | ||
| 153 | { | ||
| 154 | if (0 == lstrcmpW(pswl->wzFormat, L"none")) | ||
| 155 | { | ||
| 156 | // user wishes for Logging to be turned 'off' | ||
| 157 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_LOG_TYPE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)0)); | ||
| 158 | ExitOnFailure(hr, "Failed to write Log Type for Web: %ls", wzWebBase); | ||
| 159 | } | ||
| 160 | else | ||
| 161 | { | ||
| 162 | Assert(*pswl->wzFormatGUID); | ||
| 163 | |||
| 164 | // write the GUID for the log format for the web to the metabase | ||
| 165 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_LOG_PLUGIN_ORDER, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, pswl->wzFormatGUID); | ||
| 166 | ExitOnFailure(hr, "Failed to write Log GUID for Web: %ls", wzWebBase); | ||
| 167 | |||
| 168 | hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_LOG_TYPE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)1)); | ||
| 169 | ExitOnFailure(hr, "Failed to write Log Type for Web: %ls", wzWebBase); | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | LExit: | ||
| 174 | return hr; | ||
| 175 | } | ||
| 176 | |||
| 177 | |||
diff --git a/src/ext/Iis/ca/scaweblog.h b/src/ext/Iis/ca/scaweblog.h new file mode 100644 index 00000000..1a690cce --- /dev/null +++ b/src/ext/Iis/ca/scaweblog.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | struct SCA_WEB_LOG | ||
| 6 | { | ||
| 7 | // iis configuation information | ||
| 8 | WCHAR wzLog[MAX_DARWIN_KEY + 1]; | ||
| 9 | |||
| 10 | // for specifying the log format | ||
| 11 | WCHAR wzFormat[MAX_DARWIN_KEY + 1]; | ||
| 12 | WCHAR wzFormatGUID[MAX_DARWIN_KEY + 1]; | ||
| 13 | }; | ||
| 14 | |||
| 15 | |||
| 16 | // prototypes | ||
| 17 | HRESULT ScaGetWebLog( | ||
| 18 | IMSAdminBase* piMetabase, | ||
| 19 | LPCWSTR wzLog, | ||
| 20 | __in WCA_WRAPQUERY_HANDLE hWebLogQuery, | ||
| 21 | SCA_WEB_LOG* pswl | ||
| 22 | ); | ||
| 23 | HRESULT ScaWriteWebLog( | ||
| 24 | IMSAdminBase* piMetabase, | ||
| 25 | LPCWSTR wzRootOfWeb, | ||
| 26 | SCA_WEB_LOG *pswl | ||
| 27 | ); | ||
diff --git a/src/ext/Iis/ca/scaweblog7.cpp b/src/ext/Iis/ca/scaweblog7.cpp new file mode 100644 index 00000000..c857c46f --- /dev/null +++ b/src/ext/Iis/ca/scaweblog7.cpp | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | // sql queries | ||
| 5 | LPCWSTR vcsWebLogQuery7 = L"SELECT `Log`, `Format` " | ||
| 6 | L"FROM `IIsWebLog` WHERE `Log`=?"; | ||
| 7 | |||
| 8 | enum eWebLogQuery { wlqLog = 1, wlqFormat }; | ||
| 9 | |||
| 10 | /* **************************************************************** | ||
| 11 | * ScaGetWebLog7 -Retrieves Log table data for the specified Log key | ||
| 12 | * | ||
| 13 | * ****************************************************************/ | ||
| 14 | HRESULT ScaGetWebLog7( | ||
| 15 | __in_z LPCWSTR wzLog, | ||
| 16 | __in WCA_WRAPQUERY_HANDLE hWebLogQuery, | ||
| 17 | __out SCA_WEB_LOG* pswl | ||
| 18 | ) | ||
| 19 | { | ||
| 20 | HRESULT hr = S_OK; | ||
| 21 | LPWSTR pwzData = NULL; | ||
| 22 | MSIHANDLE hRec; | ||
| 23 | |||
| 24 | if (0 == WcaGetQueryRecords(hWebLogQuery)) | ||
| 25 | { | ||
| 26 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaGetWebLog() - no records to process"); | ||
| 27 | ExitFunction1(hr = S_FALSE); | ||
| 28 | } | ||
| 29 | |||
| 30 | WcaFetchWrappedReset(hWebLogQuery); | ||
| 31 | |||
| 32 | hr = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec); | ||
| 33 | if (E_NOMOREITEMS == hr) | ||
| 34 | { | ||
| 35 | ExitOnFailure(hr, "cannot locate IIsWebLog.Log='%ls'", wzLog); | ||
| 36 | } | ||
| 37 | HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec); | ||
| 38 | |||
| 39 | if (SUCCEEDED(hrTemp)) | ||
| 40 | { | ||
| 41 | ExitOnFailure(hr, "error - found multiple matching IIsWebLog rows"); | ||
| 42 | } | ||
| 43 | |||
| 44 | ::ZeroMemory(pswl, sizeof(SCA_WEB_LOG)); | ||
| 45 | |||
| 46 | // check that log key matches | ||
| 47 | hr = WcaGetRecordString(hRec, wlqLog, &pwzData); | ||
| 48 | ExitOnFailure(hr, "failed to get IIsWebLog.Log for Log: %ls", wzLog); | ||
| 49 | hr = ::StringCchCopyW(pswl->wzLog, countof(pswl->wzLog), pwzData); | ||
| 50 | ExitOnFailure(hr, "failed to copy log name: %ls", pwzData); | ||
| 51 | |||
| 52 | hr = WcaGetRecordString(hRec, wlqFormat, &pwzData); | ||
| 53 | ExitOnFailure(hr, "failed to get IIsWebLog.Format for Log:", wzLog); | ||
| 54 | |||
| 55 | //translate WIX log format name strings to IIS7 | ||
| 56 | if (0 == lstrcmpW(pwzData, L"Microsoft IIS Log File Format")) | ||
| 57 | { | ||
| 58 | hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"IIS"); | ||
| 59 | ExitOnFailure(hr, "failed to copy log format: %ls", pwzData); | ||
| 60 | } | ||
| 61 | else if (0 == lstrcmpW(pwzData, L"NCSA Common Log File Format")) | ||
| 62 | { | ||
| 63 | hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"NCSA"); | ||
| 64 | ExitOnFailure(hr, "failed to copy log format: %ls", pwzData); | ||
| 65 | } | ||
| 66 | else if (0 == lstrcmpW(pwzData, L"none")) | ||
| 67 | { | ||
| 68 | hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"none"); | ||
| 69 | ExitOnFailure(hr, "failed to copy log format: %ls", pwzData); | ||
| 70 | } | ||
| 71 | else if (0 == lstrcmpW(pwzData, L"ODBC Logging")) | ||
| 72 | { | ||
| 73 | hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"W3C"); | ||
| 74 | ExitOnFailure(hr, "failed to copy log format: %ls", pwzData); | ||
| 75 | } | ||
| 76 | else if (0 == lstrcmpW(pwzData, L"W3C Extended Log File Format")) | ||
| 77 | { | ||
| 78 | hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"W3C"); | ||
| 79 | ExitOnFailure(hr, "failed to copy log format: %ls", pwzData); | ||
| 80 | } | ||
| 81 | else | ||
| 82 | { | ||
| 83 | hr = HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); | ||
| 84 | ExitOnFailure(hr, "Invalid log file format: %ls", pwzData); | ||
| 85 | } | ||
| 86 | |||
| 87 | LExit: | ||
| 88 | ReleaseStr(pwzData); | ||
| 89 | |||
| 90 | return hr; | ||
| 91 | } | ||
| 92 | |||
| 93 | |||
| 94 | /* **************************************************************** | ||
| 95 | * ScaWriteWebLog -Writes the IIS log values to the metabase. | ||
| 96 | * | ||
| 97 | * ****************************************************************/ | ||
| 98 | HRESULT ScaWriteWebLog7( | ||
| 99 | LPCWSTR wzWebBase, | ||
| 100 | const SCA_WEB_LOG *pswl | ||
| 101 | ) | ||
| 102 | { | ||
| 103 | HRESULT hr = S_OK; | ||
| 104 | |||
| 105 | if (*pswl->wzFormat) | ||
| 106 | { | ||
| 107 | //write pswl->wzFormat | ||
| 108 | hr = ScaWriteConfigID(IIS_WEBLOG); | ||
| 109 | ExitOnFailure(hr, "Failed to write log format id"); | ||
| 110 | hr = ScaWriteConfigString(wzWebBase); | ||
| 111 | ExitOnFailure(hr, "Failed to write log web key"); | ||
| 112 | hr = ScaWriteConfigString(pswl->wzFormat); | ||
| 113 | ExitOnFailure(hr, "Failed to write log format string"); | ||
| 114 | } | ||
| 115 | |||
| 116 | LExit: | ||
| 117 | return hr; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
diff --git a/src/ext/Iis/ca/scaweblog7.h b/src/ext/Iis/ca/scaweblog7.h new file mode 100644 index 00000000..f2bb60d7 --- /dev/null +++ b/src/ext/Iis/ca/scaweblog7.h | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaGetWebLog7( | ||
| 6 | __in_z LPCWSTR wzLog, | ||
| 7 | __in WCA_WRAPQUERY_HANDLE hWebLogQuery, | ||
| 8 | __out SCA_WEB_LOG* pswl | ||
| 9 | ); | ||
| 10 | |||
| 11 | HRESULT ScaWriteWebLog7( | ||
| 12 | __in_z LPCWSTR wzRootOfWeb, | ||
| 13 | const SCA_WEB_LOG *pswl | ||
| 14 | ); | ||
diff --git a/src/ext/Iis/ca/scawebprop.cpp b/src/ext/Iis/ca/scawebprop.cpp new file mode 100644 index 00000000..b5e38467 --- /dev/null +++ b/src/ext/Iis/ca/scawebprop.cpp | |||
| @@ -0,0 +1,301 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // sql queries | ||
| 6 | enum eWebDirPropertiesQuery { wpqProperties = 1, wpqAccess, wpqAuthorization, wpqUser, wpqControlledPassword, wpqLogVisits, wpqIndex, wpqDefaultDoc, wpqAspDetailedError, wpqHttpExp, wpqCCMaxAge, wpqCCCustom, wpqNoCustomError, wpqAccessSSLFlags, wpqAuthenticationProviders }; | ||
| 7 | |||
| 8 | HRESULT ScaGetWebDirProperties( | ||
| 9 | __in LPCWSTR wzProperties, | ||
| 10 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 11 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 12 | __inout SCA_WEB_PROPERTIES* pswp | ||
| 13 | ) | ||
| 14 | { | ||
| 15 | Assert(*wzProperties && pswp); | ||
| 16 | |||
| 17 | HRESULT hr = S_OK; | ||
| 18 | MSIHANDLE hRec; | ||
| 19 | LPWSTR pwzData = NULL; | ||
| 20 | |||
| 21 | ExitOnNull(wzProperties, hr, E_INVALIDARG, "Failed to get web directory properties because no properties were provided to get"); | ||
| 22 | |||
| 23 | WcaFetchWrappedReset(hWebDirPropQuery); | ||
| 24 | |||
| 25 | hr = WcaFetchWrappedRecordWhereString(hWebDirPropQuery, 1, wzProperties, &hRec); | ||
| 26 | if (S_OK == hr) | ||
| 27 | { | ||
| 28 | hr = WcaGetRecordString(hRec, wpqProperties, &pwzData); | ||
| 29 | ExitOnFailure(hr, "Failed to get IIsWebDirProperties.DirProperties"); | ||
| 30 | hr = ::StringCchCopyW(pswp->wzKey, countof(pswp->wzKey), pwzData); | ||
| 31 | ExitOnFailure(hr, "Failed to copy key string to webdirproperties object"); | ||
| 32 | |||
| 33 | Assert(0 == lstrcmpW(pswp->wzKey, wzProperties)); | ||
| 34 | |||
| 35 | hr = WcaGetRecordInteger(hRec, wpqAccess, &pswp->iAccess); | ||
| 36 | ExitOnFailure(hr, "Failed to get access value"); | ||
| 37 | |||
| 38 | hr = WcaGetRecordInteger(hRec, wpqAuthorization, &pswp->iAuthorization); | ||
| 39 | ExitOnFailure(hr, "Failed to get authorization value"); | ||
| 40 | |||
| 41 | // if allow anonymous users | ||
| 42 | if (S_OK == hr && pswp->iAuthorization & 1) | ||
| 43 | { | ||
| 44 | // if there is an anonymous user specified | ||
| 45 | hr = WcaGetRecordString(hRec, wpqUser, &pwzData); | ||
| 46 | ExitOnFailure(hr, "Failed to get AnonymousUser_"); | ||
| 47 | if (pwzData && *pwzData) | ||
| 48 | { | ||
| 49 | hr = WcaGetRecordInteger(hRec, wpqControlledPassword, &pswp->fIIsControlledPassword); | ||
| 50 | ExitOnFailure(hr, "Failed to get IIsControlledPassword"); | ||
| 51 | if (S_FALSE == hr) | ||
| 52 | { | ||
| 53 | pswp->fIIsControlledPassword = FALSE; | ||
| 54 | hr = S_OK; | ||
| 55 | } | ||
| 56 | |||
| 57 | hr = ScaGetUserDeferred(pwzData, hUserQuery, &pswp->scau); | ||
| 58 | ExitOnFailure(hr, "Failed to get User information for Web"); | ||
| 59 | |||
| 60 | pswp->fHasUser = TRUE; | ||
| 61 | } | ||
| 62 | else | ||
| 63 | pswp->fHasUser = FALSE; | ||
| 64 | } | ||
| 65 | |||
| 66 | hr = WcaGetRecordInteger(hRec, wpqLogVisits, &pswp->fLogVisits); | ||
| 67 | ExitOnFailure(hr, "Failed to get IIsWebDirProperties.LogVisits"); | ||
| 68 | |||
| 69 | hr = WcaGetRecordInteger(hRec, wpqIndex, &pswp->fIndex); | ||
| 70 | ExitOnFailure(hr, "Failed to get IIsWebDirProperties.Index"); | ||
| 71 | |||
| 72 | hr = WcaGetRecordString(hRec, wpqDefaultDoc, &pwzData); | ||
| 73 | ExitOnFailure(hr, "Failed to get IIsWebDirProperties.DefaultDoc"); | ||
| 74 | if (pwzData && *pwzData) | ||
| 75 | { | ||
| 76 | pswp->fHasDefaultDoc = TRUE; | ||
| 77 | if (0 == lstrcmpW(L"-", pwzData)) // remove any existing default documents by setting them blank | ||
| 78 | { | ||
| 79 | pswp->wzDefaultDoc[0] = L'\0'; | ||
| 80 | } | ||
| 81 | else // set the default documents | ||
| 82 | { | ||
| 83 | hr = ::StringCchCopyW(pswp->wzDefaultDoc, countof(pswp->wzDefaultDoc), pwzData); | ||
| 84 | ExitOnFailure(hr, "Failed to copy default document string to webdirproperties object"); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | else | ||
| 88 | { | ||
| 89 | pswp->fHasDefaultDoc = FALSE; | ||
| 90 | } | ||
| 91 | |||
| 92 | hr = WcaGetRecordInteger(hRec, wpqAspDetailedError, &pswp->fAspDetailedError); | ||
| 93 | ExitOnFailure(hr, "Failed to get IIsWebDirProperties.AspDetailedError"); | ||
| 94 | |||
| 95 | hr = WcaGetRecordString(hRec, wpqHttpExp, &pwzData); | ||
| 96 | ExitOnFailure(hr, "Failed to get IIsWebDirProperties.HttpExp"); | ||
| 97 | if (pwzData && *pwzData) | ||
| 98 | { | ||
| 99 | pswp->fHasHttpExp = TRUE; | ||
| 100 | if (0 == lstrcmpW(L"-", pwzData)) // remove any existing default expiration settings by setting them blank | ||
| 101 | { | ||
| 102 | pswp->wzHttpExp[0] = L'\0'; | ||
| 103 | } | ||
| 104 | else // set the expiration setting | ||
| 105 | { | ||
| 106 | hr = ::StringCchCopyW(pswp->wzHttpExp, countof(pswp->wzHttpExp), pwzData); | ||
| 107 | ExitOnFailure(hr, "Failed to copy http expiration string to webdirproperties object"); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | else | ||
| 111 | { | ||
| 112 | pswp->fHasHttpExp = FALSE; | ||
| 113 | } | ||
| 114 | |||
| 115 | hr = WcaGetRecordInteger(hRec, wpqCCMaxAge, &pswp->iCacheControlMaxAge); | ||
| 116 | ExitOnFailure(hr, "failed to get IIsWebDirProperties.CacheControlMaxAge"); | ||
| 117 | |||
| 118 | hr = WcaGetRecordString(hRec, wpqCCCustom, &pwzData); | ||
| 119 | ExitOnFailure(hr, "Failed to get IIsWebDirProperties.CacheControlCustom"); | ||
| 120 | if (pwzData && *pwzData) | ||
| 121 | { | ||
| 122 | pswp->fHasCacheControlCustom = TRUE; | ||
| 123 | if (0 == lstrcmpW(L"-", pwzData)) // remove any existing default cache control custom settings by setting them blank | ||
| 124 | { | ||
| 125 | pswp->wzCacheControlCustom[0] = L'\0'; | ||
| 126 | } | ||
| 127 | else // set the custom cache control setting | ||
| 128 | { | ||
| 129 | hr = ::StringCchCopyW(pswp->wzCacheControlCustom, countof(pswp->wzCacheControlCustom), pwzData); | ||
| 130 | ExitOnFailure(hr, "Failed to copy cache control custom settings to webdirproperites object"); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | else | ||
| 134 | { | ||
| 135 | pswp->fHasCacheControlCustom = FALSE; | ||
| 136 | } | ||
| 137 | |||
| 138 | hr = WcaGetRecordInteger(hRec, wpqNoCustomError, &pswp->fNoCustomError); | ||
| 139 | ExitOnFailure(hr, "failed to get IIsWebDirProperties.NoCustomError"); | ||
| 140 | if (MSI_NULL_INTEGER == pswp->fNoCustomError) | ||
| 141 | pswp->fNoCustomError = FALSE; | ||
| 142 | |||
| 143 | hr = WcaGetRecordInteger(hRec, wpqAccessSSLFlags, &pswp->iAccessSSLFlags); | ||
| 144 | ExitOnFailure(hr, "failed to get IIsWebDirProperties.AccessSSLFlags"); | ||
| 145 | |||
| 146 | hr = WcaGetRecordString(hRec, wpqAuthenticationProviders, &pwzData); | ||
| 147 | ExitOnFailure(hr, "Failed to get IIsWebDirProperties.AuthenticationProviders"); | ||
| 148 | if (pwzData && *pwzData) | ||
| 149 | { | ||
| 150 | hr = ::StringCchCopyW(pswp->wzAuthenticationProviders, countof(pswp->wzAuthenticationProviders), pwzData); | ||
| 151 | ExitOnFailure(hr, "Failed to copy authentication providers string to webdirproperties object"); | ||
| 152 | } | ||
| 153 | else | ||
| 154 | { | ||
| 155 | pswp->wzAuthenticationProviders[0] = L'\0'; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | else if (E_NOMOREITEMS == hr) | ||
| 159 | { | ||
| 160 | WcaLog(LOGMSG_STANDARD, "Error: Cannot locate IIsWebDirProperties.DirProperties='%ls'", wzProperties); | ||
| 161 | hr = E_FAIL; | ||
| 162 | } | ||
| 163 | else | ||
| 164 | { | ||
| 165 | ExitOnFailure(hr, "Error getting appropriate webdirproperty"); | ||
| 166 | } | ||
| 167 | |||
| 168 | // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would | ||
| 169 | HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebDirPropQuery, 1, wzProperties, &hRec); | ||
| 170 | if (SUCCEEDED(hrTemp)) | ||
| 171 | { | ||
| 172 | AssertSz(E_NOMOREITEMS == hrTemp, "ScaGetWebDirProperties found more than one record"); | ||
| 173 | } | ||
| 174 | |||
| 175 | LExit: | ||
| 176 | ReleaseStr(pwzData); | ||
| 177 | |||
| 178 | return hr; | ||
| 179 | } | ||
| 180 | |||
| 181 | |||
| 182 | HRESULT ScaWriteWebDirProperties( | ||
| 183 | __in IMSAdminBase* piMetabase, | ||
| 184 | __in LPCWSTR wzRootOfWeb, | ||
| 185 | __inout SCA_WEB_PROPERTIES* pswp | ||
| 186 | ) | ||
| 187 | { | ||
| 188 | HRESULT hr = S_OK; | ||
| 189 | DWORD dw = 0; | ||
| 190 | WCHAR wz[METADATA_MAX_NAME_LEN + 1]; | ||
| 191 | |||
| 192 | // write the access permissions to the metabase | ||
| 193 | if (MSI_NULL_INTEGER != pswp->iAccess) | ||
| 194 | { | ||
| 195 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAccess)); | ||
| 196 | ExitOnFailure(hr, "Failed to write access permissions for Web"); | ||
| 197 | } | ||
| 198 | |||
| 199 | if (MSI_NULL_INTEGER != pswp->iAuthorization) | ||
| 200 | { | ||
| 201 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_AUTHORIZATION, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAuthorization)); | ||
| 202 | ExitOnFailure(hr, "Failed to write authorization for Web"); | ||
| 203 | } | ||
| 204 | |||
| 205 | if (pswp->fHasUser) | ||
| 206 | { | ||
| 207 | Assert(pswp->scau.wzName); | ||
| 208 | // write the user name | ||
| 209 | if (*pswp->scau.wzDomain) | ||
| 210 | { | ||
| 211 | hr = ::StringCchPrintfW(wz, countof(wz), L"%s\\%s", pswp->scau.wzDomain, pswp->scau.wzName); | ||
| 212 | ExitOnFailure(hr, "Failed to format domain\\username string"); | ||
| 213 | } | ||
| 214 | else | ||
| 215 | { | ||
| 216 | hr = ::StringCchCopyW(wz, countof(wz), pswp->scau.wzName); | ||
| 217 | ExitOnFailure(hr, "Failed to copy user name"); | ||
| 218 | } | ||
| 219 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_USER_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)wz); | ||
| 220 | ExitOnFailure(hr, "Failed to write anonymous user name for Web"); | ||
| 221 | |||
| 222 | // write the password | ||
| 223 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->scau.wzPassword); | ||
| 224 | ExitOnFailure(hr, "Failed to write anonymous user password for Web"); | ||
| 225 | |||
| 226 | // store whether IIs controls password | ||
| 227 | dw = (pswp->fIIsControlledPassword) ? TRUE : FALSE; | ||
| 228 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_USE_SUBAUTH, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw)); | ||
| 229 | ExitOnFailure(hr, "Failed to write if IIs controls user password for Web"); | ||
| 230 | } | ||
| 231 | |||
| 232 | if (MSI_NULL_INTEGER != pswp->fLogVisits) | ||
| 233 | { | ||
| 234 | // The sense of this boolean value is reversed - it is "don't log", not "log visits." | ||
| 235 | dw = (pswp->fLogVisits) ? FALSE : TRUE; | ||
| 236 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_DONT_LOG, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw)); | ||
| 237 | ExitOnFailure(hr, "Failed to write authorization for Web"); | ||
| 238 | } | ||
| 239 | |||
| 240 | if (MSI_NULL_INTEGER != pswp->fIndex) | ||
| 241 | { | ||
| 242 | dw = (pswp->fIndex) ? TRUE : FALSE; | ||
| 243 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_IS_CONTENT_INDEXED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw)); | ||
| 244 | ExitOnFailure(hr, "Failed to write authorization for Web"); | ||
| 245 | } | ||
| 246 | |||
| 247 | if (pswp->fHasDefaultDoc) | ||
| 248 | { | ||
| 249 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_DEFAULT_LOAD_FILE, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzDefaultDoc); | ||
| 250 | ExitOnFailure(hr, "Failed to write default documents for Web"); | ||
| 251 | } | ||
| 252 | |||
| 253 | if (MSI_NULL_INTEGER != pswp->fAspDetailedError) | ||
| 254 | { | ||
| 255 | dw = (pswp->fAspDetailedError) ? TRUE : FALSE; | ||
| 256 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTERRORSSENTTOBROWSER, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw)); | ||
| 257 | ExitOnFailure(hr, "Failed to write ASP script error for Web"); | ||
| 258 | } | ||
| 259 | |||
| 260 | if (pswp->fHasHttpExp) | ||
| 261 | { | ||
| 262 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_HTTP_EXPIRES, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzHttpExp); | ||
| 263 | ExitOnFailure(hr, "Failed to write HTTP Expiration for Web"); | ||
| 264 | } | ||
| 265 | |||
| 266 | if (MSI_NULL_INTEGER != pswp->iCacheControlMaxAge) | ||
| 267 | { | ||
| 268 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CC_MAX_AGE, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iCacheControlMaxAge)); | ||
| 269 | ExitOnFailure(hr, "Failed to write Cache Control Max Age for Web"); | ||
| 270 | } | ||
| 271 | |||
| 272 | if (pswp->fHasCacheControlCustom) | ||
| 273 | { | ||
| 274 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CC_OTHER, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzCacheControlCustom); | ||
| 275 | ExitOnFailure(hr, "Failed to write Cache Control Custom for Web"); | ||
| 276 | } | ||
| 277 | |||
| 278 | if (pswp->fNoCustomError) | ||
| 279 | { | ||
| 280 | memset(wz, 0, sizeof(wz)); | ||
| 281 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wz); | ||
| 282 | ExitOnFailure(hr, "Failed to write Custom Error for Web"); | ||
| 283 | } | ||
| 284 | |||
| 285 | if (MSI_NULL_INTEGER != pswp->iAccessSSLFlags) | ||
| 286 | { | ||
| 287 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_SSL_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAccessSSLFlags)); | ||
| 288 | ExitOnFailure(hr, "Failed to write AccessSSLFlags for Web"); | ||
| 289 | } | ||
| 290 | |||
| 291 | if (*pswp->wzAuthenticationProviders) | ||
| 292 | { | ||
| 293 | hr = ::StringCchCopyW(wz, countof(wz), pswp->wzAuthenticationProviders); | ||
| 294 | ExitOnFailure(hr, "Failed to copy authentication providers string"); | ||
| 295 | hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_NTAUTHENTICATION_PROVIDERS, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)wz); | ||
| 296 | ExitOnFailure(hr, "Failed to write AuthenticationProviders for Web"); | ||
| 297 | } | ||
| 298 | |||
| 299 | LExit: | ||
| 300 | return hr; | ||
| 301 | } | ||
diff --git a/src/ext/Iis/ca/scawebprop.h b/src/ext/Iis/ca/scawebprop.h new file mode 100644 index 00000000..7a3ae5c9 --- /dev/null +++ b/src/ext/Iis/ca/scawebprop.h | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scauser.h" | ||
| 6 | |||
| 7 | // global sql queries provided for optimization | ||
| 8 | extern LPCWSTR vcsWebDirPropertiesQuery; | ||
| 9 | |||
| 10 | |||
| 11 | // structs | ||
| 12 | struct SCA_WEB_PROPERTIES | ||
| 13 | { | ||
| 14 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 15 | |||
| 16 | int iAccess; | ||
| 17 | |||
| 18 | int iAuthorization; | ||
| 19 | BOOL fHasUser; | ||
| 20 | SCA_USER scau; | ||
| 21 | BOOL fIIsControlledPassword; | ||
| 22 | |||
| 23 | BOOL fLogVisits; | ||
| 24 | BOOL fIndex; | ||
| 25 | |||
| 26 | BOOL fHasDefaultDoc; | ||
| 27 | WCHAR wzDefaultDoc[MAX_DARWIN_COLUMN + 1]; | ||
| 28 | |||
| 29 | BOOL fHasHttpExp; | ||
| 30 | WCHAR wzHttpExp[MAX_DARWIN_COLUMN + 1]; | ||
| 31 | |||
| 32 | BOOL fAspDetailedError; | ||
| 33 | |||
| 34 | int iCacheControlMaxAge; | ||
| 35 | |||
| 36 | BOOL fHasCacheControlCustom; | ||
| 37 | WCHAR wzCacheControlCustom[MAX_DARWIN_COLUMN + 1]; | ||
| 38 | |||
| 39 | BOOL fNoCustomError; | ||
| 40 | |||
| 41 | int iAccessSSLFlags; | ||
| 42 | |||
| 43 | WCHAR wzAuthenticationProviders[MAX_DARWIN_COLUMN + 1]; | ||
| 44 | }; | ||
| 45 | |||
| 46 | |||
| 47 | // prototypes | ||
| 48 | HRESULT ScaGetWebDirProperties( | ||
| 49 | __in LPCWSTR pwzProperties, | ||
| 50 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 51 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 52 | __inout SCA_WEB_PROPERTIES* pswp | ||
| 53 | ); | ||
| 54 | |||
| 55 | HRESULT ScaWriteWebDirProperties( | ||
| 56 | __in IMSAdminBase* piMetabase, | ||
| 57 | __in LPCWSTR wzRootOfWeb, | ||
| 58 | __inout SCA_WEB_PROPERTIES* pswp | ||
| 59 | ); | ||
| 60 | |||
diff --git a/src/ext/Iis/ca/scawebprop7.cpp b/src/ext/Iis/ca/scawebprop7.cpp new file mode 100644 index 00000000..b8d99b0a --- /dev/null +++ b/src/ext/Iis/ca/scawebprop7.cpp | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | HRESULT ScaWriteWebDirProperties7( | ||
| 6 | __in_z LPCWSTR wzWebName, | ||
| 7 | __in_z LPCWSTR wzRootOfWeb, | ||
| 8 | __in const SCA_WEB_PROPERTIES* pswp | ||
| 9 | ) | ||
| 10 | { | ||
| 11 | HRESULT hr = S_OK; | ||
| 12 | WCHAR wz[METADATA_MAX_NAME_LEN + 1]; | ||
| 13 | |||
| 14 | //all go to same web/root location tag | ||
| 15 | hr = ScaWriteConfigID(IIS_DIRPROP_BEGIN); | ||
| 16 | ExitOnFailure(hr, "Failed to write DirProp begin id"); | ||
| 17 | hr = ScaWriteConfigString(wzWebName); //site name key | ||
| 18 | ExitOnFailure(hr, "Failed to write DirProp web key"); | ||
| 19 | hr = ScaWriteConfigString(wzRootOfWeb); //app path key | ||
| 20 | ExitOnFailure(hr, "Failed to write DirProp app key"); | ||
| 21 | |||
| 22 | // write the access permissions to the metabase | ||
| 23 | if (MSI_NULL_INTEGER != pswp->iAccess) | ||
| 24 | { | ||
| 25 | hr = ScaWriteConfigID(IIS_DIRPROP_ACCESS); | ||
| 26 | ExitOnFailure(hr, "Failed to write DirProp access id"); | ||
| 27 | hr = ScaWriteConfigInteger(pswp->iAccess); | ||
| 28 | ExitOnFailure(hr, "Failed to write access permissions for Web"); | ||
| 29 | } | ||
| 30 | |||
| 31 | if (MSI_NULL_INTEGER != pswp->iAuthorization) | ||
| 32 | { | ||
| 33 | hr = ScaWriteConfigID(IIS_DIRPROP_AUTH); | ||
| 34 | ExitOnFailure(hr, "Failed to write DirProp auth id"); | ||
| 35 | hr = ScaWriteConfigInteger(pswp->iAuthorization); | ||
| 36 | ExitOnFailure(hr, "Failed to write authorization for Web"); | ||
| 37 | } | ||
| 38 | |||
| 39 | if (pswp->fHasUser) | ||
| 40 | { | ||
| 41 | Assert(pswp->scau.wzName); | ||
| 42 | // write the user name | ||
| 43 | if (*pswp->scau.wzDomain) | ||
| 44 | { | ||
| 45 | hr = ::StringCchPrintfW(wz, countof(wz), L"%s\\%s", pswp->scau.wzDomain, pswp->scau.wzName); | ||
| 46 | ExitOnFailure(hr, "Failed to format domain\\username string"); | ||
| 47 | } | ||
| 48 | else | ||
| 49 | { | ||
| 50 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
| 51 | hr = ::StringCchCopyW(wz, countof(wz), pswp->scau.wzName); | ||
| 52 | ExitOnFailure(hr, "Failed to copy user name"); | ||
| 53 | } | ||
| 54 | hr = ScaWriteConfigID(IIS_DIRPROP_USER); | ||
| 55 | ExitOnFailure(hr, "Failed to write DirProp user id"); | ||
| 56 | hr = ScaWriteConfigString(wz); | ||
| 57 | ExitOnFailure(hr, "Failed to write anonymous user name for Web"); | ||
| 58 | |||
| 59 | // write the password | ||
| 60 | hr = ScaWriteConfigID(IIS_DIRPROP_PWD); | ||
| 61 | ExitOnFailure(hr, "Failed to write DirProp pwd id"); | ||
| 62 | hr = ScaWriteConfigString(pswp->scau.wzPassword); | ||
| 63 | ExitOnFailure(hr, "Failed to write anonymous user password for Web"); | ||
| 64 | |||
| 65 | if (pswp->fIIsControlledPassword) | ||
| 66 | { | ||
| 67 | //Not Supported by IIS7 : pswp->fIIsControlledPassword | ||
| 68 | WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: WebDirProperties.IIsControlledPassword, ignoring"); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | if (MSI_NULL_INTEGER != pswp->fLogVisits) | ||
| 73 | { | ||
| 74 | hr = ScaWriteConfigID(IIS_DIRPROP_LOGVISITS); | ||
| 75 | ExitOnFailure(hr, "Failed to write DirProp logVisits id"); | ||
| 76 | hr = ScaWriteConfigInteger(pswp->fLogVisits ? FALSE : TRUE); // we capture "should log" but IIS7 wants "should not log" | ||
| 77 | ExitOnFailure(hr, "Failed to write DirProp logVisits"); | ||
| 78 | } | ||
| 79 | |||
| 80 | if (MSI_NULL_INTEGER != pswp->fIndex) | ||
| 81 | { | ||
| 82 | //Not Supported by IIS7 : pswp->fIndex | ||
| 83 | WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: WebDirProperties.Index, ignoring"); | ||
| 84 | } | ||
| 85 | |||
| 86 | if (pswp->fHasDefaultDoc) | ||
| 87 | { | ||
| 88 | hr = ScaWriteConfigID(IIS_DIRPROP_DEFDOCS); | ||
| 89 | ExitOnFailure(hr, "Failed to write DirProp defdocs id"); | ||
| 90 | hr = ScaWriteConfigString(pswp->wzDefaultDoc); | ||
| 91 | ExitOnFailure(hr, "Failed to write default documents for Web"); | ||
| 92 | } | ||
| 93 | |||
| 94 | if (MSI_NULL_INTEGER != pswp->fAspDetailedError) | ||
| 95 | { | ||
| 96 | hr = ScaWriteConfigID(IIS_DIRPROP_ASPERROR); | ||
| 97 | ExitOnFailure(hr, "Failed to write ASP script error id"); | ||
| 98 | hr = ScaWriteConfigInteger(pswp->fAspDetailedError); | ||
| 99 | ExitOnFailure(hr, "Failed to write ASP script error for Web"); | ||
| 100 | } | ||
| 101 | |||
| 102 | if (pswp->fHasHttpExp) | ||
| 103 | { | ||
| 104 | hr = ScaWriteConfigID(IIS_DIRPROP_HTTPEXPIRES); | ||
| 105 | ExitOnFailure(hr, "Failed to write DirProp HttpExpires id"); | ||
| 106 | hr = ScaWriteConfigString(pswp->wzHttpExp); | ||
| 107 | ExitOnFailure(hr, "Failed to write DirProp HttpExpires value"); | ||
| 108 | } | ||
| 109 | |||
| 110 | if (MSI_NULL_INTEGER != pswp->iCacheControlMaxAge) | ||
| 111 | { | ||
| 112 | hr = ScaWriteConfigID(IIS_DIRPROP_MAXAGE); | ||
| 113 | ExitOnFailure(hr, "Failed to write DirProp MaxAge id"); | ||
| 114 | hr = ScaWriteConfigInteger(pswp->iCacheControlMaxAge); | ||
| 115 | ExitOnFailure(hr, "Failed to write DirProp MaxAge value"); | ||
| 116 | } | ||
| 117 | |||
| 118 | if (pswp->fHasCacheControlCustom) | ||
| 119 | { | ||
| 120 | hr = ScaWriteConfigID(IIS_DIRPROP_CACHECUST); | ||
| 121 | ExitOnFailure(hr, "Failed to write DirProp Cache Control Custom id"); | ||
| 122 | hr = ScaWriteConfigString(pswp->wzCacheControlCustom); | ||
| 123 | ExitOnFailure(hr, "Failed to write Cache Control Custom for Web"); | ||
| 124 | } | ||
| 125 | |||
| 126 | if (pswp->fNoCustomError) | ||
| 127 | { | ||
| 128 | hr = ScaWriteConfigID(IIS_DIRPROP_NOCUSTERROR); | ||
| 129 | ExitOnFailure(hr, "Failed to write DirProp clear Cust Errors id"); | ||
| 130 | } | ||
| 131 | |||
| 132 | if (MSI_NULL_INTEGER != pswp->iAccessSSLFlags) | ||
| 133 | { | ||
| 134 | hr = ScaWriteConfigID(IIS_DIRPROP_SSLFLAGS); | ||
| 135 | ExitOnFailure(hr, "Failed to write DirProp sslFlags id"); | ||
| 136 | hr = ScaWriteConfigInteger(pswp->iAccessSSLFlags); | ||
| 137 | ExitOnFailure(hr, "Failed to write AccessSSLFlags for Web"); | ||
| 138 | } | ||
| 139 | |||
| 140 | if (*pswp->wzAuthenticationProviders) | ||
| 141 | { | ||
| 142 | hr = ::StringCchCopyW(wz, countof(wz), pswp->wzAuthenticationProviders); | ||
| 143 | ExitOnFailure(hr, "Failed to copy authentication providers string"); | ||
| 144 | hr = ScaWriteConfigID(IIS_DIRPROP_AUTHPROVID); | ||
| 145 | ExitOnFailure(hr, "Failed to write DirProp AuthProvid id"); | ||
| 146 | hr = ScaWriteConfigString(wz); | ||
| 147 | ExitOnFailure(hr, "Failed to write AuthenticationProviders for Web"); | ||
| 148 | } | ||
| 149 | //End of Dir Properties | ||
| 150 | hr = ScaWriteConfigID(IIS_DIRPROP_END); | ||
| 151 | ExitOnFailure(hr, "Failed to write DirProp end id"); | ||
| 152 | |||
| 153 | LExit: | ||
| 154 | return hr; | ||
| 155 | } | ||
diff --git a/src/ext/Iis/ca/scawebprop7.h b/src/ext/Iis/ca/scawebprop7.h new file mode 100644 index 00000000..a97e8679 --- /dev/null +++ b/src/ext/Iis/ca/scawebprop7.h | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scauser.h" | ||
| 6 | |||
| 7 | HRESULT ScaWriteWebDirProperties7( | ||
| 8 | __in_z LPCWSTR wzwWebName, | ||
| 9 | __in_z LPCWSTR wzRootOfWeb, | ||
| 10 | const SCA_WEB_PROPERTIES* pswp | ||
| 11 | ); | ||
| 12 | |||
diff --git a/src/ext/Iis/ca/scawebsvcext.cpp b/src/ext/Iis/ca/scawebsvcext.cpp new file mode 100644 index 00000000..369e951b --- /dev/null +++ b/src/ext/Iis/ca/scawebsvcext.cpp | |||
| @@ -0,0 +1,343 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // sql queries | ||
| 6 | enum eWebSvcExtQuery { ldqComponent=1 , ldqFile, ldqDescription, ldqGroup, ldqAttributes, ldqInstalled, ldqAction }; | ||
| 7 | |||
| 8 | |||
| 9 | LPCWSTR vcsWebSvcExtRoot = L"/LM/W3SVC"; | ||
| 10 | |||
| 11 | // prototypes for private helper functions | ||
| 12 | static HRESULT AddWebSvcExtToList( | ||
| 13 | __in SCA_WEBSVCEXT** ppsWseList | ||
| 14 | ); | ||
| 15 | |||
| 16 | //static HRESULT ScaCheckWebSvcExtValue( | ||
| 17 | // __in IMSAdminBase* piMetabase, | ||
| 18 | // __in DWORD dwMDIdentifier | ||
| 19 | // ); | ||
| 20 | |||
| 21 | static HRESULT ScaWebSvcExtInstall( | ||
| 22 | __in LPWSTR *pwzWebSvcExtList, | ||
| 23 | __in DWORD_PTR *pcchWebSvcExtList, | ||
| 24 | __in SCA_WEBSVCEXT* psWseList | ||
| 25 | ); | ||
| 26 | |||
| 27 | static HRESULT ScaWebSvcExtUninstall( | ||
| 28 | __in LPWSTR *pwzWebSvcExtList, | ||
| 29 | __in const DWORD *pcchWebSvcExtList, | ||
| 30 | __in SCA_WEBSVCEXT* psWseList | ||
| 31 | ); | ||
| 32 | |||
| 33 | // functions | ||
| 34 | |||
| 35 | HRESULT __stdcall ScaWebSvcExtRead( | ||
| 36 | __in SCA_WEBSVCEXT** ppsWseList, | ||
| 37 | __inout LPWSTR *ppwzCustomActionData | ||
| 38 | ) | ||
| 39 | { | ||
| 40 | Assert(ppsWseList); | ||
| 41 | |||
| 42 | HRESULT hr = S_OK; | ||
| 43 | MSIHANDLE hRec; | ||
| 44 | LPWSTR pwzData = NULL; | ||
| 45 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
| 46 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
| 47 | SCA_WEBSVCEXT* psWebSvcExt = NULL; | ||
| 48 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 49 | |||
| 50 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 51 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebSvcExtRead"); | ||
| 52 | |||
| 53 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 54 | { | ||
| 55 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtRead() because IIsWebServiceExtension data not present"); | ||
| 56 | ExitFunction1(hr = S_FALSE); | ||
| 57 | } | ||
| 58 | |||
| 59 | // loop through all the web service extensions | ||
| 60 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 61 | { | ||
| 62 | // Get the Component first. If the Component is not being modified during | ||
| 63 | // this transaction, skip processing this whole record. | ||
| 64 | hr = WcaGetRecordString(hRec, ldqComponent, &pwzData); | ||
| 65 | ExitOnFailure(hr, "Failed to get Component for WebSvcExt"); | ||
| 66 | |||
| 67 | hr = WcaGetRecordInteger(hRec, ldqInstalled, (int *)&isInstalled); | ||
| 68 | ExitOnFailure(hr, "Failed to get Component installed state for WebSvcExt"); | ||
| 69 | |||
| 70 | hr = WcaGetRecordInteger(hRec, ldqAction, (int *)&isAction); | ||
| 71 | ExitOnFailure(hr, "Failed to get Component action state for WebSvcExt"); | ||
| 72 | |||
| 73 | if (!WcaIsInstalling(isInstalled, isAction) && | ||
| 74 | !WcaIsReInstalling(isInstalled, isAction) && | ||
| 75 | !WcaIsUninstalling(isInstalled, isAction)) | ||
| 76 | { | ||
| 77 | continue; // skip this record. | ||
| 78 | } | ||
| 79 | |||
| 80 | hr = AddWebSvcExtToList(ppsWseList); | ||
| 81 | ExitOnFailure(hr, "failed to add element to web svc ext list"); | ||
| 82 | |||
| 83 | psWebSvcExt = *ppsWseList; | ||
| 84 | Assert(psWebSvcExt); | ||
| 85 | |||
| 86 | psWebSvcExt->isInstalled = isInstalled; | ||
| 87 | psWebSvcExt->isAction = isAction; | ||
| 88 | |||
| 89 | hr = WcaGetRecordString(hRec, ldqFile, &pwzData); | ||
| 90 | ExitOnFailure(hr, "Failed to get File for WebSvcExt"); | ||
| 91 | hr = ::StringCchCopyW(psWebSvcExt->wzFile, countof(psWebSvcExt->wzFile), pwzData); | ||
| 92 | ExitOnFailure(hr, "Failed to copy File for WebSvcExt"); | ||
| 93 | |||
| 94 | hr = WcaGetRecordString(hRec, ldqDescription, &pwzData); | ||
| 95 | ExitOnFailure(hr, "Failed to get Description for WebSvcExt"); | ||
| 96 | hr = ::StringCchCopyW(psWebSvcExt->wzDescription, countof(psWebSvcExt->wzDescription), pwzData); | ||
| 97 | ExitOnFailure(hr, "Failed to copy Description for WebSvcExt"); | ||
| 98 | |||
| 99 | hr = WcaGetRecordString(hRec, ldqGroup, &pwzData); | ||
| 100 | ExitOnFailure(hr, "Failed to get Group for WebSvcExt"); | ||
| 101 | hr = ::StringCchCopyW(psWebSvcExt->wzGroup, countof(psWebSvcExt->wzGroup), pwzData); | ||
| 102 | ExitOnFailure(hr, "Failed to copy Group for WebSvcExt"); | ||
| 103 | |||
| 104 | hr = WcaGetRecordInteger(hRec, ldqAttributes, &psWebSvcExt->iAttributes); | ||
| 105 | ExitOnFailure(hr, "Failed to get Attributes for WebSvcExt"); | ||
| 106 | } | ||
| 107 | |||
| 108 | if (E_NOMOREITEMS == hr) | ||
| 109 | hr = S_OK; | ||
| 110 | ExitOnFailure(hr, "Failure while processing WebSvcExt"); | ||
| 111 | |||
| 112 | LExit: | ||
| 113 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 114 | |||
| 115 | ReleaseStr(pwzData); | ||
| 116 | |||
| 117 | return hr; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | // Commit does both install and uninstall | ||
| 122 | HRESULT __stdcall ScaWebSvcExtCommit( | ||
| 123 | __in IMSAdminBase* piMetabase, | ||
| 124 | __in SCA_WEBSVCEXT* psWseList | ||
| 125 | ) | ||
| 126 | { | ||
| 127 | Assert(piMetabase); | ||
| 128 | |||
| 129 | HRESULT hr = S_OK; | ||
| 130 | METADATA_RECORD mr; | ||
| 131 | |||
| 132 | LPWSTR wzWebSvcExtList = NULL; | ||
| 133 | DWORD cbWebSvcExtList = 0; | ||
| 134 | DWORD_PTR cchWebSvcExtList = 0; | ||
| 135 | |||
| 136 | if (!psWseList) | ||
| 137 | { | ||
| 138 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because there are no web service extensions in the list"); | ||
| 139 | ExitFunction(); | ||
| 140 | } | ||
| 141 | |||
| 142 | // Get current set of web service extensions. | ||
| 143 | ::ZeroMemory(&mr, sizeof(mr)); | ||
| 144 | mr.dwMDIdentifier = MD_WEB_SVC_EXT_RESTRICTION_LIST; | ||
| 145 | mr.dwMDAttributes = 0; | ||
| 146 | mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 147 | mr.dwMDDataType = ALL_METADATA; | ||
| 148 | mr.pbMDData = NULL; | ||
| 149 | mr.dwMDDataLen = 0; | ||
| 150 | |||
| 151 | hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cbWebSvcExtList); | ||
| 152 | if (MD_ERROR_DATA_NOT_FOUND == hr) | ||
| 153 | { | ||
| 154 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because WebSvcExtRestrictionList value is not present"); | ||
| 155 | ExitFunction1(hr = S_FALSE); | ||
| 156 | } | ||
| 157 | else if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr) | ||
| 158 | { | ||
| 159 | // cchWebSvcExtList is returned in bytes. Convert to WCHAR size to call StrAlloc | ||
| 160 | cchWebSvcExtList = cbWebSvcExtList / sizeof(WCHAR); | ||
| 161 | hr = StrAlloc(&wzWebSvcExtList, cchWebSvcExtList); | ||
| 162 | ExitOnFailure(hr, "Failed allocating space for web service extensions"); | ||
| 163 | } | ||
| 164 | else | ||
| 165 | { | ||
| 166 | ExitOnFailure(hr, "Failed retrieving web service extensions"); | ||
| 167 | } | ||
| 168 | |||
| 169 | mr.pbMDData = (unsigned char*)wzWebSvcExtList; | ||
| 170 | mr.dwMDDataLen = cbWebSvcExtList; | ||
| 171 | |||
| 172 | hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cbWebSvcExtList); | ||
| 173 | ExitOnFailure(hr, "Failed retrieving web service extensions"); | ||
| 174 | |||
| 175 | // Make changes to local copy of metabase | ||
| 176 | while (psWseList) | ||
| 177 | { | ||
| 178 | if (WcaIsInstalling(psWseList->isInstalled, psWseList->isAction)) | ||
| 179 | { | ||
| 180 | hr = ScaWebSvcExtInstall(&wzWebSvcExtList, &cchWebSvcExtList, psWseList); | ||
| 181 | ExitOnFailure(hr, "Failed to install Web Service extension"); | ||
| 182 | } | ||
| 183 | else if (WcaIsUninstalling(psWseList->isInstalled, psWseList->isAction)) | ||
| 184 | { | ||
| 185 | hr = ScaWebSvcExtUninstall(&wzWebSvcExtList, (DWORD *)&cchWebSvcExtList, psWseList); | ||
| 186 | ExitOnFailure(hr, "Failed to uninstall Web Service extension"); | ||
| 187 | } | ||
| 188 | |||
| 189 | psWseList = psWseList->psWseNext; | ||
| 190 | } | ||
| 191 | |||
| 192 | // Write Metabase | ||
| 193 | hr = ScaWriteMetabaseValue(piMetabase, vcsWebSvcExtRoot, NULL, MD_WEB_SVC_EXT_RESTRICTION_LIST, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzWebSvcExtList); | ||
| 194 | ExitOnFailure(hr, "Failed to write WebServiceExtensions: '%ls'", wzWebSvcExtList); | ||
| 195 | |||
| 196 | LExit: | ||
| 197 | ReleaseStr(wzWebSvcExtList); | ||
| 198 | |||
| 199 | return hr; | ||
| 200 | } | ||
| 201 | |||
| 202 | |||
| 203 | static HRESULT ScaWebSvcExtInstall( | ||
| 204 | __in LPWSTR *ppwzWebSvcExtList, | ||
| 205 | __in DWORD_PTR *pcchWebSvcExtList, | ||
| 206 | __in SCA_WEBSVCEXT* psWseList | ||
| 207 | ) | ||
| 208 | { | ||
| 209 | Assert( ppwzWebSvcExtList && pcchWebSvcExtList && psWseList); | ||
| 210 | Assert(*ppwzWebSvcExtList); | ||
| 211 | |||
| 212 | HRESULT hr = S_OK; | ||
| 213 | |||
| 214 | LPWSTR pwzWebSvcExt = NULL; | ||
| 215 | int iAllow; | ||
| 216 | int iUiDeletable; | ||
| 217 | |||
| 218 | BOOL fAlreadyExists = FALSE; | ||
| 219 | DWORD_PTR dwIndex = 0xFFFFFFFF; | ||
| 220 | LPCWSTR wzFoundString = NULL; | ||
| 221 | |||
| 222 | // Check if it's already in there | ||
| 223 | hr = MultiSzFindSubstring(*ppwzWebSvcExtList, psWseList->wzFile, &dwIndex, &wzFoundString); | ||
| 224 | ExitOnFailure(hr, "failed to search for string:%ls in web service extension MULTISZ", psWseList->wzFile); | ||
| 225 | |||
| 226 | if (S_FALSE != hr && NULL != wcsstr(wzFoundString, psWseList->wzGroup) && NULL != wcsstr(wzFoundString, psWseList->wzDescription)) | ||
| 227 | { | ||
| 228 | fAlreadyExists = TRUE; | ||
| 229 | } | ||
| 230 | |||
| 231 | // Construct the single string in the format required for the WebSvc Ext list in metabase | ||
| 232 | iAllow = (psWseList->iAttributes & 1); | ||
| 233 | iUiDeletable = ((psWseList->iAttributes >> 1) & 1); | ||
| 234 | hr = StrAllocFormatted(&pwzWebSvcExt, L"%d,%s,%d,%s,%s", iAllow, psWseList->wzFile, iUiDeletable, psWseList->wzGroup, psWseList->wzDescription); | ||
| 235 | ExitOnFailure(hr, "Failure allocating space for web service extensions"); | ||
| 236 | |||
| 237 | if (fAlreadyExists) | ||
| 238 | { | ||
| 239 | hr = MultiSzReplaceString(ppwzWebSvcExtList, dwIndex, pwzWebSvcExt); | ||
| 240 | ExitOnFailure(hr, "failed to update web service extension string: %ls", pwzWebSvcExt); | ||
| 241 | } | ||
| 242 | else | ||
| 243 | { | ||
| 244 | hr = MultiSzPrepend(ppwzWebSvcExtList, pcchWebSvcExtList, pwzWebSvcExt); | ||
| 245 | ExitOnFailure(hr, "failed to prepend web service extension string: %ls", pwzWebSvcExt); | ||
| 246 | } | ||
| 247 | |||
| 248 | LExit: | ||
| 249 | ReleaseStr(pwzWebSvcExt); | ||
| 250 | |||
| 251 | return hr; | ||
| 252 | } | ||
| 253 | |||
| 254 | |||
| 255 | static HRESULT ScaWebSvcExtUninstall( | ||
| 256 | __in LPWSTR *ppwzWebSvcExtList, | ||
| 257 | __in const DWORD* /*pcchWebSvcExtList*/, | ||
| 258 | __in SCA_WEBSVCEXT* psWseList | ||
| 259 | ) | ||
| 260 | { | ||
| 261 | Assert(ppwzWebSvcExtList && *ppwzWebSvcExtList && psWseList); | ||
| 262 | Assert(*ppwzWebSvcExtList); | ||
| 263 | |||
| 264 | HRESULT hr = S_OK; | ||
| 265 | DWORD_PTR dwIndex = 0xFFFFFFFF; | ||
| 266 | LPCWSTR wzFoundString = NULL; | ||
| 267 | |||
| 268 | // Find the string to remove | ||
| 269 | hr = MultiSzFindSubstring(*ppwzWebSvcExtList, psWseList->wzFile, &dwIndex, &wzFoundString); | ||
| 270 | ExitOnFailure(hr, "failed to search for string:%ls in web service extension MULTISZ", psWseList->wzFile); | ||
| 271 | |||
| 272 | // If we found a match (ignoring the Allow and Deletable flags) | ||
| 273 | if (S_FALSE != hr && NULL != wcsstr(wzFoundString, psWseList->wzGroup) && NULL != wcsstr(wzFoundString, psWseList->wzDescription)) | ||
| 274 | { | ||
| 275 | hr = MultiSzRemoveString(ppwzWebSvcExtList, dwIndex); | ||
| 276 | ExitOnFailure(hr, "failed to remove string: %d from web service extension MULTISZ", dwIndex); | ||
| 277 | } | ||
| 278 | |||
| 279 | LExit: | ||
| 280 | return hr; | ||
| 281 | } | ||
| 282 | |||
| 283 | |||
| 284 | //static HRESULT ScaCheckWebSvcExtValue( | ||
| 285 | // __in IMSAdminBase* piMetabase, | ||
| 286 | // __in DWORD dwMDIdentifier | ||
| 287 | // ) | ||
| 288 | //{ | ||
| 289 | // if (!piMetabase) | ||
| 290 | // { | ||
| 291 | // return E_INVALIDARG; | ||
| 292 | // } | ||
| 293 | // | ||
| 294 | // HRESULT hr = S_OK; | ||
| 295 | // METADATA_RECORD mr = { 0 }; | ||
| 296 | // DWORD cch = 0; | ||
| 297 | // | ||
| 298 | // mr.dwMDIdentifier = dwMDIdentifier; | ||
| 299 | // mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
| 300 | // | ||
| 301 | // hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cch); | ||
| 302 | // if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr) | ||
| 303 | // { | ||
| 304 | // hr = S_OK; | ||
| 305 | // } | ||
| 306 | // else if (MD_ERROR_DATA_NOT_FOUND == hr) | ||
| 307 | // { | ||
| 308 | // hr = S_FALSE; | ||
| 309 | // } | ||
| 310 | // | ||
| 311 | // return hr; | ||
| 312 | //} | ||
| 313 | |||
| 314 | |||
| 315 | void ScaWebSvcExtFreeList( | ||
| 316 | __in SCA_WEBSVCEXT* psWseList | ||
| 317 | ) | ||
| 318 | { | ||
| 319 | SCA_WEBSVCEXT* psWseDelete = psWseList; | ||
| 320 | while (psWseList) | ||
| 321 | { | ||
| 322 | psWseDelete = psWseList; | ||
| 323 | psWseList = psWseList->psWseNext; | ||
| 324 | MemFree(psWseDelete); | ||
| 325 | } | ||
| 326 | } | ||
| 327 | |||
| 328 | |||
| 329 | static HRESULT AddWebSvcExtToList( | ||
| 330 | __in SCA_WEBSVCEXT** ppsWseList | ||
| 331 | ) | ||
| 332 | { | ||
| 333 | HRESULT hr = S_OK; | ||
| 334 | |||
| 335 | SCA_WEBSVCEXT* psWse = static_cast<SCA_WEBSVCEXT*>(MemAlloc(sizeof(SCA_WEBSVCEXT), TRUE)); | ||
| 336 | ExitOnNull(psWse, hr, E_OUTOFMEMORY, "failed to allocate element for web svc ext list"); | ||
| 337 | |||
| 338 | psWse->psWseNext = *ppsWseList; | ||
| 339 | *ppsWseList = psWse; | ||
| 340 | |||
| 341 | LExit: | ||
| 342 | return hr; | ||
| 343 | } | ||
diff --git a/src/ext/Iis/ca/scawebsvcext.h b/src/ext/Iis/ca/scawebsvcext.h new file mode 100644 index 00000000..4d225b09 --- /dev/null +++ b/src/ext/Iis/ca/scawebsvcext.h | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | enum SCA_WEBSVCEXT_ATTRIBUTES { SWSEATTRIB_ALLOW = 1, SWSEATTRIB_UIDELETABLE = 2 }; | ||
| 6 | |||
| 7 | struct SCA_WEBSVCEXT | ||
| 8 | { | ||
| 9 | // darwin information | ||
| 10 | INSTALLSTATE isInstalled; | ||
| 11 | INSTALLSTATE isAction; | ||
| 12 | |||
| 13 | // iis configuation information | ||
| 14 | WCHAR wzFile[MAX_PATH + 1]; | ||
| 15 | WCHAR wzDescription[MAX_DARWIN_COLUMN + 1]; | ||
| 16 | WCHAR wzGroup[MAX_DARWIN_COLUMN + 1]; | ||
| 17 | |||
| 18 | int iAttributes; | ||
| 19 | |||
| 20 | SCA_WEBSVCEXT* psWseNext; | ||
| 21 | }; | ||
| 22 | |||
| 23 | HRESULT __stdcall ScaWebSvcExtRead( | ||
| 24 | __in SCA_WEBSVCEXT** ppsWseList, | ||
| 25 | __inout LPWSTR *ppwzCustomActionData | ||
| 26 | ); | ||
| 27 | |||
| 28 | HRESULT ScaWebSvcExtCommit( | ||
| 29 | __in IMSAdminBase* piMetabase, | ||
| 30 | __in SCA_WEBSVCEXT* psWseList | ||
| 31 | ); | ||
| 32 | |||
| 33 | void ScaWebSvcExtFreeList( | ||
| 34 | __in SCA_WEBSVCEXT* psWseList | ||
| 35 | ); | ||
diff --git a/src/ext/Iis/ca/scawebsvcext7.cpp b/src/ext/Iis/ca/scawebsvcext7.cpp new file mode 100644 index 00000000..dcf2f7f8 --- /dev/null +++ b/src/ext/Iis/ca/scawebsvcext7.cpp | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | static HRESULT ScaWebSvcExtInstall( | ||
| 6 | const SCA_WEBSVCEXT* psWseList | ||
| 7 | ); | ||
| 8 | |||
| 9 | static HRESULT ScaWebSvcExtUninstall( | ||
| 10 | const SCA_WEBSVCEXT* psWseList | ||
| 11 | ); | ||
| 12 | |||
| 13 | // functions | ||
| 14 | // Commit does both install and uninstall | ||
| 15 | HRESULT __stdcall ScaWebSvcExtCommit7( | ||
| 16 | __in SCA_WEBSVCEXT* psWseList | ||
| 17 | ) | ||
| 18 | { | ||
| 19 | HRESULT hr = S_OK; | ||
| 20 | |||
| 21 | if (!psWseList) | ||
| 22 | { | ||
| 23 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because there are no web service extensions in the list"); | ||
| 24 | ExitFunction(); | ||
| 25 | } | ||
| 26 | |||
| 27 | // Make changes to local copy of metabase | ||
| 28 | while (psWseList) | ||
| 29 | { | ||
| 30 | if (WcaIsInstalling(psWseList->isInstalled, psWseList->isAction)) | ||
| 31 | { | ||
| 32 | hr = ScaWebSvcExtInstall(psWseList); | ||
| 33 | ExitOnFailure(hr, "Failed to install Web Service extension"); | ||
| 34 | } | ||
| 35 | else if (WcaIsUninstalling(psWseList->isInstalled, psWseList->isAction)) | ||
| 36 | { | ||
| 37 | hr = ScaWebSvcExtUninstall(psWseList); | ||
| 38 | ExitOnFailure(hr, "Failed to uninstall Web Service extension"); | ||
| 39 | } | ||
| 40 | |||
| 41 | psWseList = psWseList->psWseNext; | ||
| 42 | } | ||
| 43 | |||
| 44 | |||
| 45 | LExit: | ||
| 46 | |||
| 47 | return hr; | ||
| 48 | } | ||
| 49 | |||
| 50 | |||
| 51 | static HRESULT ScaWebSvcExtInstall( | ||
| 52 | const SCA_WEBSVCEXT* psWseList | ||
| 53 | ) | ||
| 54 | { | ||
| 55 | HRESULT hr = S_OK; | ||
| 56 | int iAllow; | ||
| 57 | |||
| 58 | //Write CAData actions | ||
| 59 | hr = ScaWriteConfigID(IIS_WEB_SVC_EXT); | ||
| 60 | ExitOnFailure(hr, "failed add web svc ext ID"); | ||
| 61 | hr = ScaWriteConfigID(IIS_CREATE); | ||
| 62 | ExitOnFailure(hr, "failed add web svc ext action"); | ||
| 63 | |||
| 64 | // write File path | ||
| 65 | hr = ScaWriteConfigString(psWseList->wzFile); | ||
| 66 | ExitOnFailure(hr, "failed add web svc ext file path"); | ||
| 67 | |||
| 68 | // write allowed | ||
| 69 | // unDeleatable n/a in IIS7 | ||
| 70 | iAllow = (psWseList->iAttributes & 1); | ||
| 71 | hr = ScaWriteConfigInteger(iAllow); | ||
| 72 | ExitOnFailure(hr, "failed add web svc ext Allowed"); | ||
| 73 | |||
| 74 | //write group | ||
| 75 | hr = ScaWriteConfigString(psWseList->wzGroup); | ||
| 76 | ExitOnFailure(hr, "failed add web svc ext group"); | ||
| 77 | |||
| 78 | //write description | ||
| 79 | hr = ScaWriteConfigString(psWseList->wzDescription); | ||
| 80 | ExitOnFailure(hr, "failed add web svc ext description"); | ||
| 81 | |||
| 82 | LExit: | ||
| 83 | |||
| 84 | return hr; | ||
| 85 | } | ||
| 86 | |||
| 87 | |||
| 88 | static HRESULT ScaWebSvcExtUninstall( | ||
| 89 | const SCA_WEBSVCEXT* psWseList | ||
| 90 | ) | ||
| 91 | { | ||
| 92 | HRESULT hr = S_OK; | ||
| 93 | |||
| 94 | //Write CAData actions | ||
| 95 | hr = ScaWriteConfigID(IIS_WEB_SVC_EXT); | ||
| 96 | ExitOnFailure(hr, "failed add web svc ext ID"); | ||
| 97 | hr = ScaWriteConfigID(IIS_DELETE); | ||
| 98 | ExitOnFailure(hr, "failed add web svc ext action"); | ||
| 99 | |||
| 100 | // write File path (Key) | ||
| 101 | hr = ScaWriteConfigString(psWseList->wzFile); | ||
| 102 | ExitOnFailure(hr, "failed add web svc ext file path"); | ||
| 103 | |||
| 104 | LExit: | ||
| 105 | return hr; | ||
| 106 | } | ||
diff --git a/src/ext/Iis/ca/scawebsvcext7.h b/src/ext/Iis/ca/scawebsvcext7.h new file mode 100644 index 00000000..1a686aed --- /dev/null +++ b/src/ext/Iis/ca/scawebsvcext7.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT ScaWebSvcExtCommit7( | ||
| 6 | __in SCA_WEBSVCEXT* psWseList | ||
| 7 | ); | ||
| 8 | |||
diff --git a/src/ext/Iis/nuget.config b/src/ext/Iis/nuget.config new file mode 100644 index 00000000..db7aba29 --- /dev/null +++ b/src/ext/Iis/nuget.config | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <configuration> | ||
| 3 | <packageSources> | ||
| 4 | <clear /> | ||
| 5 | <add key="wixtoolset-burn" value="https://ci.appveyor.com/nuget/wixtoolset-burn" /> | ||
| 6 | <add key="wixtoolset-data" value="https://ci.appveyor.com/nuget/wixtoolset-data" /> | ||
| 7 | <add key="wixtoolset-extensibility" value="https://ci.appveyor.com/nuget/wixtoolset-extensibility" /> | ||
| 8 | <add key="wixtoolset-core" value="https://ci.appveyor.com/nuget/wixtoolset-core" /> | ||
| 9 | <add key="wixtoolset-core-native" value="https://ci.appveyor.com/nuget/wixtoolset-core-native" /> | ||
| 10 | <add key="wixtoolset-dtf" value="https://ci.appveyor.com/nuget/wixtoolset-dtf" /> | ||
| 11 | <add key="wixtoolset-dutil" value="https://ci.appveyor.com/nuget/wixtoolset-dutil" /> | ||
| 12 | <add key="wixtoolset-wcautil" value="https://ci.appveyor.com/nuget/wixtoolset-wcautil" /> | ||
| 13 | <add key="wixtoolset-tools" value="https://ci.appveyor.com/nuget/wixtoolset-tools" /> | ||
| 14 | <add key="wixbuildtools" value="https://ci.appveyor.com/nuget/wixbuildtools" /> | ||
| 15 | <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> | ||
| 16 | </packageSources> | ||
| 17 | </configuration> \ No newline at end of file | ||
diff --git a/src/ext/Iis/test/WixToolsetTest.Iis/IisExtensionFixture.cs b/src/ext/Iis/test/WixToolsetTest.Iis/IisExtensionFixture.cs new file mode 100644 index 00000000..685e7126 --- /dev/null +++ b/src/ext/Iis/test/WixToolsetTest.Iis/IisExtensionFixture.cs | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolsetTest.Iis | ||
| 4 | { | ||
| 5 | using System.Linq; | ||
| 6 | using WixBuildTools.TestSupport; | ||
| 7 | using WixToolset.Core.TestPackage; | ||
| 8 | using WixToolset.Iis; | ||
| 9 | using Xunit; | ||
| 10 | |||
| 11 | public class IisExtensionFixture | ||
| 12 | { | ||
| 13 | [Fact] | ||
| 14 | public void CanBuildUsingIIsWebAddress() | ||
| 15 | { | ||
| 16 | var folder = TestData.Get(@"TestData\UsingIis"); | ||
| 17 | var build = new Builder(folder, typeof(IisExtensionFactory), new[] { folder }); | ||
| 18 | |||
| 19 | var results = build.BuildAndQuery(Build, "IIsWebAddress"); | ||
| 20 | Assert.Equal(new[] | ||
| 21 | { | ||
| 22 | "IIsWebAddress:TestAddress\tTest\t\t[PORT]\t\t0", | ||
| 23 | }, results); | ||
| 24 | } | ||
| 25 | |||
| 26 | private static void Build(string[] args) | ||
| 27 | { | ||
| 28 | var result = WixRunner.Execute(args) | ||
| 29 | .AssertSuccess(); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | } | ||
diff --git a/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/Package.en-us.wxl b/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/Package.en-us.wxl new file mode 100644 index 00000000..38c12ac1 --- /dev/null +++ b/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/Package.en-us.wxl | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | |||
| 3 | <!-- | ||
| 4 | This file contains the declaration of all the localizable strings. | ||
| 5 | --> | ||
| 6 | <WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US"> | ||
| 7 | |||
| 8 | <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String> | ||
| 9 | <String Id="FeatureTitle">MsiPackage</String> | ||
| 10 | |||
| 11 | </WixLocalization> | ||
diff --git a/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/Package.wxs b/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/Package.wxs new file mode 100644 index 00000000..f36aafef --- /dev/null +++ b/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/Package.wxs | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 2 | <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" InstallerVersion="200"> | ||
| 3 | <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" /> | ||
| 4 | |||
| 5 | <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)"> | ||
| 6 | <ComponentGroupRef Id="ProductComponents" /> | ||
| 7 | </Feature> | ||
| 8 | </Package> | ||
| 9 | |||
| 10 | <Fragment> | ||
| 11 | <StandardDirectory Id="ProgramFilesFolder"> | ||
| 12 | <Directory Id="INSTALLFOLDER" Name="MsiPackage"> | ||
| 13 | <Directory Id="TestWebSiteProductDirectory" /> | ||
| 14 | </Directory> | ||
| 15 | </StandardDirectory> | ||
| 16 | </Fragment> | ||
| 17 | </Wix> | ||
diff --git a/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/PackageComponents.wxs b/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/PackageComponents.wxs new file mode 100644 index 00000000..03203b50 --- /dev/null +++ b/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/PackageComponents.wxs | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" | ||
| 3 | xmlns:iis="http://wixtoolset.org/schemas/v4/wxs/iis"> | ||
| 4 | <Fragment> | ||
| 5 | <Property Id="PORT" Value="3062" /> | ||
| 6 | <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER"> | ||
| 7 | <Component> | ||
| 8 | <File Source="example.txt" /> | ||
| 9 | <iis:WebSite Id="Test" Description="Test web server" Directory="TestWebSiteProductDirectory" AutoStart="yes" DirProperties="ReadAndExecute" ConfigureIfExists="no" > | ||
| 10 | <iis:WebAddress Id="TestAddress" Port="[PORT]" Secure="no" /> | ||
| 11 | </iis:WebSite> | ||
| 12 | </Component> | ||
| 13 | </ComponentGroup> | ||
| 14 | <iis:WebDirProperties Id="ReadAndExecute" /> | ||
| 15 | </Fragment> | ||
| 16 | </Wix> | ||
diff --git a/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/example.txt b/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/example.txt | |||
| @@ -0,0 +1 @@ | |||
| This is example.txt. \ No newline at end of file | |||
diff --git a/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj b/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj new file mode 100644 index 00000000..49ed89bc --- /dev/null +++ b/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | <Project Sdk="Microsoft.NET.Sdk"> | ||
| 5 | <PropertyGroup> | ||
| 6 | <TargetFramework>netcoreapp3.1</TargetFramework> | ||
| 7 | <IsPackable>false</IsPackable> | ||
| 8 | </PropertyGroup> | ||
| 9 | |||
| 10 | <PropertyGroup> | ||
| 11 | <NoWarn>NU1701</NoWarn> | ||
| 12 | </PropertyGroup> | ||
| 13 | |||
| 14 | <ItemGroup> | ||
| 15 | <Content Include="TestData\UsingIis\example.txt" CopyToOutputDirectory="PreserveNewest" /> | ||
| 16 | <Content Include="TestData\UsingIis\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" /> | ||
| 17 | <Content Include="TestData\UsingIis\Package.wxs" CopyToOutputDirectory="PreserveNewest" /> | ||
| 18 | <Content Include="TestData\UsingIis\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" /> | ||
| 19 | </ItemGroup> | ||
| 20 | |||
| 21 | <ItemGroup> | ||
| 22 | <ProjectReference Include="..\..\wixext\WixToolset.Iis.wixext.csproj" /> | ||
| 23 | </ItemGroup> | ||
| 24 | |||
| 25 | <ItemGroup> | ||
| 26 | <PackageReference Include="WixToolset.Core" Version="4.0.*" /> | ||
| 27 | <PackageReference Include="WixToolset.Core.Burn" Version="4.0.*" /> | ||
| 28 | <PackageReference Include="WixToolset.Core.WindowsInstaller" Version="4.0.*" /> | ||
| 29 | <PackageReference Include="WixToolset.Core.TestPackage" Version="4.0.*" /> | ||
| 30 | </ItemGroup> | ||
| 31 | |||
| 32 | <ItemGroup> | ||
| 33 | <PackageReference Include="WixBuildTools.TestSupport" Version="4.0.*" /> | ||
| 34 | </ItemGroup> | ||
| 35 | |||
| 36 | <ItemGroup> | ||
| 37 | <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" /> | ||
| 38 | <PackageReference Include="xunit" Version="2.4.1" /> | ||
| 39 | <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" PrivateAssets="All" /> | ||
| 40 | </ItemGroup> | ||
| 41 | </Project> | ||
diff --git a/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.v3.ncrunchproject b/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.v3.ncrunchproject new file mode 100644 index 00000000..7b5b2139 --- /dev/null +++ b/src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.v3.ncrunchproject | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | <ProjectConfiguration> | ||
| 2 | <Settings> | ||
| 3 | <CopyReferencedAssembliesToWorkspace>True</CopyReferencedAssembliesToWorkspace> | ||
| 4 | </Settings> | ||
| 5 | </ProjectConfiguration> \ No newline at end of file | ||
diff --git a/src/ext/Iis/wix.snk b/src/ext/Iis/wix.snk new file mode 100644 index 00000000..3908a66a --- /dev/null +++ b/src/ext/Iis/wix.snk | |||
| Binary files differ | |||
diff --git a/src/ext/Iis/wixext/IIsCompiler.cs b/src/ext/Iis/wixext/IIsCompiler.cs new file mode 100644 index 00000000..cb573ad1 --- /dev/null +++ b/src/ext/Iis/wixext/IIsCompiler.cs | |||
| @@ -0,0 +1,2620 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.Globalization; | ||
| 8 | using System.Xml.Linq; | ||
| 9 | using WixToolset.Data; | ||
| 10 | using WixToolset.Extensibility; | ||
| 11 | using WixToolset.Extensibility.Data; | ||
| 12 | using WixToolset.Iis.Symbols; | ||
| 13 | |||
| 14 | /// <summary> | ||
| 15 | /// The compiler for the WiX Toolset Internet Information Services Extension. | ||
| 16 | /// </summary> | ||
| 17 | public sealed class IIsCompiler : BaseCompilerExtension | ||
| 18 | { | ||
| 19 | public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/iis"; | ||
| 20 | |||
| 21 | /// <summary> | ||
| 22 | /// Types of objects that custom HTTP Headers can be applied to. | ||
| 23 | /// </summary> | ||
| 24 | /// <remarks>Note that this must be kept in sync with the eHttpHeaderParentType in scahttpheader.h.</remarks> | ||
| 25 | private enum HttpHeaderParentType | ||
| 26 | { | ||
| 27 | /// <summary>Custom HTTP Header is to be applied to a Web Virtual Directory.</summary> | ||
| 28 | WebVirtualDir = 1, | ||
| 29 | /// <summary>Custom HTTP Header is to be applied to a Web Site.</summary> | ||
| 30 | WebSite = 2, | ||
| 31 | } | ||
| 32 | |||
| 33 | /// <summary> | ||
| 34 | /// Types of objects that MimeMaps can be applied to. | ||
| 35 | /// </summary> | ||
| 36 | /// <remarks>Note that this must be kept in sync with the eMimeMapParentType in scamimemap.h.</remarks> | ||
| 37 | private enum MimeMapParentType | ||
| 38 | { | ||
| 39 | /// <summary>MimeMap is to be applied to a Web Virtual Directory.</summary> | ||
| 40 | WebVirtualDir = 1, | ||
| 41 | WebSite = 2, | ||
| 42 | } | ||
| 43 | |||
| 44 | /// <summary> | ||
| 45 | /// Types of objects that custom WebErrors can be applied to. | ||
| 46 | /// </summary> | ||
| 47 | /// <remarks>Note that this must be kept in sync with the eWebErrorParentType in scaweberror.h.</remarks> | ||
| 48 | private enum WebErrorParentType | ||
| 49 | { | ||
| 50 | /// <summary>Custom WebError is to be applied to a Web Virtual Directory.</summary> | ||
| 51 | WebVirtualDir = 1, | ||
| 52 | |||
| 53 | /// <summary>Custom WebError is to be applied to a Web Site.</summary> | ||
| 54 | WebSite = 2, | ||
| 55 | } | ||
| 56 | |||
| 57 | /// <summary> | ||
| 58 | /// Processes an element for the Compiler. | ||
| 59 | /// </summary> | ||
| 60 | /// <param name="sourceLineNumbers">Source line number for the parent element.</param> | ||
| 61 | /// <param name="parentElement">Parent element of element to process.</param> | ||
| 62 | /// <param name="element">Element to process.</param> | ||
| 63 | /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param> | ||
| 64 | public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context) | ||
| 65 | { | ||
| 66 | switch (parentElement.Name.LocalName) | ||
| 67 | { | ||
| 68 | case "Component": | ||
| 69 | var componentId = context["ComponentId"]; | ||
| 70 | var directoryId = context["DirectoryId"]; | ||
| 71 | |||
| 72 | switch (element.Name.LocalName) | ||
| 73 | { | ||
| 74 | case "Certificate": | ||
| 75 | this.ParseCertificateElement(intermediate, section, element, componentId); | ||
| 76 | break; | ||
| 77 | case "WebAppPool": | ||
| 78 | this.ParseWebAppPoolElement(intermediate, section, element, componentId); | ||
| 79 | break; | ||
| 80 | case "WebDir": | ||
| 81 | this.ParseWebDirElement(intermediate, section, element, componentId, null); | ||
| 82 | break; | ||
| 83 | case "WebFilter": | ||
| 84 | this.ParseWebFilterElement(intermediate, section, element, componentId, null); | ||
| 85 | break; | ||
| 86 | case "WebProperty": | ||
| 87 | this.ParseWebPropertyElement(intermediate, section, element, componentId); | ||
| 88 | break; | ||
| 89 | case "WebServiceExtension": | ||
| 90 | this.ParseWebServiceExtensionElement(intermediate, section, element, componentId); | ||
| 91 | break; | ||
| 92 | case "WebSite": | ||
| 93 | this.ParseWebSiteElement(intermediate, section, element, componentId); | ||
| 94 | break; | ||
| 95 | case "WebVirtualDir": | ||
| 96 | this.ParseWebVirtualDirElement(intermediate, section, element, componentId, null, null); | ||
| 97 | break; | ||
| 98 | default: | ||
| 99 | this.ParseHelper.UnexpectedElement(parentElement, element); | ||
| 100 | break; | ||
| 101 | } | ||
| 102 | break; | ||
| 103 | case "Fragment": | ||
| 104 | case "Module": | ||
| 105 | case "Package": | ||
| 106 | switch (element.Name.LocalName) | ||
| 107 | { | ||
| 108 | case "WebApplication": | ||
| 109 | this.ParseWebApplicationElement(intermediate, section, element); | ||
| 110 | break; | ||
| 111 | case "WebAppPool": | ||
| 112 | this.ParseWebAppPoolElement(intermediate, section, element, null); | ||
| 113 | break; | ||
| 114 | case "WebDirProperties": | ||
| 115 | this.ParseWebDirPropertiesElement(intermediate, section, element, null); | ||
| 116 | break; | ||
| 117 | case "WebLog": | ||
| 118 | this.ParseWebLogElement(intermediate, section, element); | ||
| 119 | break; | ||
| 120 | case "WebSite": | ||
| 121 | this.ParseWebSiteElement(intermediate, section, element, null); | ||
| 122 | break; | ||
| 123 | default: | ||
| 124 | this.ParseHelper.UnexpectedElement(parentElement, element); | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | break; | ||
| 128 | default: | ||
| 129 | this.ParseHelper.UnexpectedElement(parentElement, element); | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | /// <summary> | ||
| 135 | /// Parses a certificate element. | ||
| 136 | /// </summary> | ||
| 137 | /// <param name="element">Element to parse.</param> | ||
| 138 | /// <param name="componentId">Identifier for parent component.</param> | ||
| 139 | private void ParseCertificateElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) | ||
| 140 | { | ||
| 141 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 142 | Identifier id = null; | ||
| 143 | int attributes = 8; // SCA_CERT_ATTRIBUTE_VITAL | ||
| 144 | string binaryRef = null; | ||
| 145 | string certificatePath = null; | ||
| 146 | string name = null; | ||
| 147 | string pfxPassword = null; | ||
| 148 | int storeLocation = 0; | ||
| 149 | string storeName = null; | ||
| 150 | |||
| 151 | foreach (var attrib in element.Attributes()) | ||
| 152 | { | ||
| 153 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 154 | { | ||
| 155 | switch (attrib.Name.LocalName) | ||
| 156 | { | ||
| 157 | case "Id": | ||
| 158 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 159 | break; | ||
| 160 | case "BinaryRef": | ||
| 161 | attributes |= 2; // SCA_CERT_ATTRIBUTE_BINARYDATA | ||
| 162 | binaryRef = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 163 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Binary, binaryRef); | ||
| 164 | break; | ||
| 165 | case "CertificatePath": | ||
| 166 | certificatePath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 167 | break; | ||
| 168 | case "Name": | ||
| 169 | name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 170 | break; | ||
| 171 | case "Overwrite": | ||
| 172 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 173 | { | ||
| 174 | attributes |= 4; // SCA_CERT_ATTRIBUTE_OVERWRITE | ||
| 175 | } | ||
| 176 | else | ||
| 177 | { | ||
| 178 | attributes &= ~4; // SCA_CERT_ATTRIBUTE_OVERWRITE | ||
| 179 | } | ||
| 180 | break; | ||
| 181 | case "PFXPassword": | ||
| 182 | pfxPassword = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 183 | break; | ||
| 184 | case "Request": | ||
| 185 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 186 | { | ||
| 187 | attributes |= 1; // SCA_CERT_ATTRIBUTE_REQUEST | ||
| 188 | } | ||
| 189 | else | ||
| 190 | { | ||
| 191 | attributes &= ~1; // SCA_CERT_ATTRIBUTE_REQUEST | ||
| 192 | } | ||
| 193 | break; | ||
| 194 | case "StoreLocation": | ||
| 195 | var storeLocationValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 196 | if (0 < storeLocationValue.Length) | ||
| 197 | { | ||
| 198 | switch (storeLocationValue) | ||
| 199 | { | ||
| 200 | case "currentUser": | ||
| 201 | storeLocation = 1; // SCA_CERTSYSTEMSTORE_CURRENTUSER | ||
| 202 | break; | ||
| 203 | case "localMachine": | ||
| 204 | storeLocation = 2; // SCA_CERTSYSTEMSTORE_LOCALMACHINE | ||
| 205 | break; | ||
| 206 | default: | ||
| 207 | storeLocation = -1; | ||
| 208 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "StoreLocation", storeLocationValue, "currentUser", "localMachine")); | ||
| 209 | break; | ||
| 210 | } | ||
| 211 | } | ||
| 212 | break; | ||
| 213 | case "StoreName": | ||
| 214 | var storeNameValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 215 | if (0 < storeNameValue.Length) | ||
| 216 | { | ||
| 217 | switch (storeNameValue) | ||
| 218 | { | ||
| 219 | case "ca": | ||
| 220 | storeName = "CA"; | ||
| 221 | break; | ||
| 222 | case "my": | ||
| 223 | case "personal": | ||
| 224 | storeName = "MY"; | ||
| 225 | break; | ||
| 226 | case "request": | ||
| 227 | storeName = "REQUEST"; | ||
| 228 | break; | ||
| 229 | case "root": | ||
| 230 | storeName = "Root"; | ||
| 231 | break; | ||
| 232 | case "otherPeople": | ||
| 233 | storeName = "AddressBook"; | ||
| 234 | break; | ||
| 235 | case "trustedPeople": | ||
| 236 | storeName = "TrustedPeople"; | ||
| 237 | break; | ||
| 238 | case "trustedPublisher": | ||
| 239 | storeName = "TrustedPublisher"; | ||
| 240 | break; | ||
| 241 | default: | ||
| 242 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "StoreName", storeNameValue, "ca", "my", "request", "root", "otherPeople", "trustedPeople", "trustedPublisher")); | ||
| 243 | break; | ||
| 244 | } | ||
| 245 | } | ||
| 246 | break; | ||
| 247 | case "Vital": | ||
| 248 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 249 | { | ||
| 250 | attributes |= 8; // SCA_CERT_ATTRIBUTE_VITAL | ||
| 251 | } | ||
| 252 | else | ||
| 253 | { | ||
| 254 | attributes &= ~8; // SCA_CERT_ATTRIBUTE_VITAL | ||
| 255 | } | ||
| 256 | break; | ||
| 257 | default: | ||
| 258 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 259 | break; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | else | ||
| 263 | { | ||
| 264 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | |||
| 269 | if (null == id) | ||
| 270 | { | ||
| 271 | id = this.ParseHelper.CreateIdentifier("crt", componentId, binaryRef, certificatePath); | ||
| 272 | } | ||
| 273 | |||
| 274 | if (null == name) | ||
| 275 | { | ||
| 276 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); | ||
| 277 | } | ||
| 278 | |||
| 279 | if (0 == storeLocation) | ||
| 280 | { | ||
| 281 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "StoreLocation")); | ||
| 282 | } | ||
| 283 | |||
| 284 | if (null == storeName) | ||
| 285 | { | ||
| 286 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "StoreName")); | ||
| 287 | } | ||
| 288 | |||
| 289 | if (null != binaryRef && null != certificatePath) | ||
| 290 | { | ||
| 291 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "BinaryRef", "CertificatePath", certificatePath)); | ||
| 292 | } | ||
| 293 | else if (null == binaryRef && null == certificatePath) | ||
| 294 | { | ||
| 295 | this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "BinaryRef", "CertificatePath")); | ||
| 296 | } | ||
| 297 | |||
| 298 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 299 | |||
| 300 | // Reference InstallCertificates and UninstallCertificates since nothing will happen without them | ||
| 301 | this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4InstallCertificates", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); | ||
| 302 | this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4UninstallCertificates", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); | ||
| 303 | this.ParseHelper.EnsureTable(section, sourceLineNumbers, IisTableDefinitions.CertificateHash); // Certificate CustomActions require the CertificateHash table | ||
| 304 | |||
| 305 | if (!this.Messaging.EncounteredError) | ||
| 306 | { | ||
| 307 | section.AddSymbol(new CertificateSymbol(sourceLineNumbers, id) | ||
| 308 | { | ||
| 309 | ComponentRef = componentId, | ||
| 310 | Name = name, | ||
| 311 | StoreLocation = storeLocation, | ||
| 312 | StoreName = storeName, | ||
| 313 | Attributes = attributes, | ||
| 314 | BinaryRef = binaryRef, | ||
| 315 | CertificatePath = certificatePath, | ||
| 316 | PFXPassword = pfxPassword, | ||
| 317 | }); | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | /// <summary> | ||
| 322 | /// Parses a CertificateRef extension element. | ||
| 323 | /// </summary> | ||
| 324 | /// <param name="element">Element to parse.</param> | ||
| 325 | /// <param name="webId">Identifier for parent web site.</param> | ||
| 326 | private void ParseCertificateRefElement(Intermediate intermediate, IntermediateSection section, XElement element, string webId) | ||
| 327 | { | ||
| 328 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 329 | Identifier id = null; | ||
| 330 | |||
| 331 | foreach (var attrib in element.Attributes()) | ||
| 332 | { | ||
| 333 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 334 | { | ||
| 335 | switch (attrib.Name.LocalName) | ||
| 336 | { | ||
| 337 | case "Id": | ||
| 338 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 339 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.Certificate, id.Id); | ||
| 340 | break; | ||
| 341 | default: | ||
| 342 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | } | ||
| 346 | else | ||
| 347 | { | ||
| 348 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | if (null == id) | ||
| 353 | { | ||
| 354 | id = this.ParseHelper.CreateIdentifier("wsc", webId); | ||
| 355 | } | ||
| 356 | |||
| 357 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 358 | |||
| 359 | if (!this.Messaging.EncounteredError) | ||
| 360 | { | ||
| 361 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.Certificate, id.Id); | ||
| 362 | |||
| 363 | section.AddSymbol(new IIsWebSiteCertificatesSymbol(sourceLineNumbers) | ||
| 364 | { | ||
| 365 | WebRef = webId, | ||
| 366 | CertificateRef = id.Id, | ||
| 367 | }); | ||
| 368 | } | ||
| 369 | } | ||
| 370 | |||
| 371 | /// <summary> | ||
| 372 | /// Parses a mime map element. | ||
| 373 | /// </summary> | ||
| 374 | /// <param name="element">Element to parse.</param> | ||
| 375 | /// <param name="parentId">Identifier for parent symbol.</param> | ||
| 376 | /// <param name="parentType">Type that parentId refers to.</param> | ||
| 377 | private void ParseMimeMapElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentId, MimeMapParentType parentType) | ||
| 378 | { | ||
| 379 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 380 | Identifier id = null; | ||
| 381 | string extension = null; | ||
| 382 | string type = null; | ||
| 383 | |||
| 384 | foreach (var attrib in element.Attributes()) | ||
| 385 | { | ||
| 386 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 387 | { | ||
| 388 | switch (attrib.Name.LocalName) | ||
| 389 | { | ||
| 390 | case "Id": | ||
| 391 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 392 | break; | ||
| 393 | case "Extension": | ||
| 394 | extension = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 395 | break; | ||
| 396 | case "Type": | ||
| 397 | type = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 398 | break; | ||
| 399 | default: | ||
| 400 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 401 | break; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | else | ||
| 405 | { | ||
| 406 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | if (null == id) | ||
| 411 | { | ||
| 412 | id = this.ParseHelper.CreateIdentifier("imm", parentId, type, extension); | ||
| 413 | } | ||
| 414 | |||
| 415 | if (null == extension) | ||
| 416 | { | ||
| 417 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Extension")); | ||
| 418 | } | ||
| 419 | else if (0 < extension.Length) | ||
| 420 | { | ||
| 421 | if (!extension.StartsWith(".", StringComparison.Ordinal)) | ||
| 422 | { | ||
| 423 | this.Messaging.Write(IIsErrors.MimeMapExtensionMissingPeriod(sourceLineNumbers, element.Name.LocalName, "Extension", extension)); | ||
| 424 | } | ||
| 425 | } | ||
| 426 | |||
| 427 | if (null == type) | ||
| 428 | { | ||
| 429 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Type")); | ||
| 430 | } | ||
| 431 | |||
| 432 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 433 | |||
| 434 | if (!this.Messaging.EncounteredError) | ||
| 435 | { | ||
| 436 | section.AddSymbol(new IIsMimeMapSymbol(sourceLineNumbers, id) | ||
| 437 | { | ||
| 438 | ParentType = (int)parentType, | ||
| 439 | ParentValue = parentId, | ||
| 440 | MimeType = type, | ||
| 441 | Extension = extension, | ||
| 442 | }); | ||
| 443 | } | ||
| 444 | } | ||
| 445 | |||
| 446 | /// <summary> | ||
| 447 | /// Parses a recycle time element. | ||
| 448 | /// </summary> | ||
| 449 | /// <param name="element">Element to parse.</param> | ||
| 450 | /// <returns>Recycle time value.</returns> | ||
| 451 | private string ParseRecycleTimeElement(Intermediate intermediate, IntermediateSection section, XElement element) | ||
| 452 | { | ||
| 453 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 454 | string value = null; | ||
| 455 | |||
| 456 | foreach (var attrib in element.Attributes()) | ||
| 457 | { | ||
| 458 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 459 | { | ||
| 460 | switch (attrib.Name.LocalName) | ||
| 461 | { | ||
| 462 | case "Value": | ||
| 463 | value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 464 | break; | ||
| 465 | default: | ||
| 466 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 467 | break; | ||
| 468 | } | ||
| 469 | } | ||
| 470 | else | ||
| 471 | { | ||
| 472 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | |||
| 476 | if (null == value) | ||
| 477 | { | ||
| 478 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value")); | ||
| 479 | } | ||
| 480 | |||
| 481 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 482 | |||
| 483 | return value; | ||
| 484 | } | ||
| 485 | |||
| 486 | /// <summary> | ||
| 487 | /// Parses a web address element. | ||
| 488 | /// </summary> | ||
| 489 | /// <param name="element">Element to parse.</param> | ||
| 490 | /// <param name="parentWeb">Identifier of parent web site.</param> | ||
| 491 | /// <returns>Identifier for web address.</returns> | ||
| 492 | private string ParseWebAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentWeb) | ||
| 493 | { | ||
| 494 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 495 | Identifier id = null; | ||
| 496 | string header = null; | ||
| 497 | string ip = null; | ||
| 498 | string port = null; | ||
| 499 | var secure = false; | ||
| 500 | |||
| 501 | foreach (var attrib in element.Attributes()) | ||
| 502 | { | ||
| 503 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 504 | { | ||
| 505 | switch (attrib.Name.LocalName) | ||
| 506 | { | ||
| 507 | case "Id": | ||
| 508 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 509 | break; | ||
| 510 | case "Header": | ||
| 511 | header = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 512 | break; | ||
| 513 | case "IP": | ||
| 514 | ip = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 515 | break; | ||
| 516 | case "Port": | ||
| 517 | port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 518 | break; | ||
| 519 | case "Secure": | ||
| 520 | secure = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
| 521 | break; | ||
| 522 | default: | ||
| 523 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 524 | break; | ||
| 525 | } | ||
| 526 | } | ||
| 527 | else | ||
| 528 | { | ||
| 529 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 530 | } | ||
| 531 | } | ||
| 532 | |||
| 533 | if (null == id) | ||
| 534 | { | ||
| 535 | id = this.ParseHelper.CreateIdentifier("iwa", parentWeb, ip, port); | ||
| 536 | } | ||
| 537 | |||
| 538 | if (null == port) | ||
| 539 | { | ||
| 540 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Port")); | ||
| 541 | } | ||
| 542 | |||
| 543 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 544 | |||
| 545 | if (!this.Messaging.EncounteredError) | ||
| 546 | { | ||
| 547 | section.AddSymbol(new IIsWebAddressSymbol(sourceLineNumbers, id) | ||
| 548 | { | ||
| 549 | WebRef = parentWeb, | ||
| 550 | IP = ip, | ||
| 551 | Port = port, | ||
| 552 | Header = header, | ||
| 553 | Secure = secure ? 1 : 0, | ||
| 554 | }); | ||
| 555 | } | ||
| 556 | |||
| 557 | return id?.Id; | ||
| 558 | } | ||
| 559 | |||
| 560 | /// <summary> | ||
| 561 | /// Parses a web application element. | ||
| 562 | /// </summary> | ||
| 563 | /// <param name="element">Element to parse.</param> | ||
| 564 | /// <returns>Identifier for web application.</returns> | ||
| 565 | private string ParseWebApplicationElement(Intermediate intermediate, IntermediateSection section, XElement element) | ||
| 566 | { | ||
| 567 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 568 | Identifier id = null; | ||
| 569 | var allowSessions = YesNoDefaultType.Default; | ||
| 570 | string appPool = null; | ||
| 571 | var buffer = YesNoDefaultType.Default; | ||
| 572 | var clientDebugging = YesNoDefaultType.Default; | ||
| 573 | string defaultScript = null; | ||
| 574 | int isolation = 0; | ||
| 575 | string name = null; | ||
| 576 | var parentPaths = YesNoDefaultType.Default; | ||
| 577 | var scriptTimeout = CompilerConstants.IntegerNotSet; | ||
| 578 | var sessionTimeout = CompilerConstants.IntegerNotSet; | ||
| 579 | var serverDebugging = YesNoDefaultType.Default; | ||
| 580 | |||
| 581 | foreach (var attrib in element.Attributes()) | ||
| 582 | { | ||
| 583 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 584 | { | ||
| 585 | switch (attrib.Name.LocalName) | ||
| 586 | { | ||
| 587 | case "Id": | ||
| 588 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 589 | break; | ||
| 590 | case "AllowSessions": | ||
| 591 | allowSessions = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib); | ||
| 592 | break; | ||
| 593 | case "Buffer": | ||
| 594 | buffer = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib); | ||
| 595 | break; | ||
| 596 | case "ClientDebugging": | ||
| 597 | clientDebugging = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib); | ||
| 598 | break; | ||
| 599 | case "DefaultScript": | ||
| 600 | defaultScript = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 601 | if (0 < defaultScript.Length) | ||
| 602 | { | ||
| 603 | switch (defaultScript) | ||
| 604 | { | ||
| 605 | case "JScript": | ||
| 606 | case "VBScript": | ||
| 607 | // these are valid values | ||
| 608 | break; | ||
| 609 | default: | ||
| 610 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, defaultScript, "JScript", "VBScript")); | ||
| 611 | break; | ||
| 612 | } | ||
| 613 | } | ||
| 614 | break; | ||
| 615 | case "Isolation": | ||
| 616 | string isolationValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 617 | if (0 < isolationValue.Length) | ||
| 618 | { | ||
| 619 | switch (isolationValue) | ||
| 620 | { | ||
| 621 | case "low": | ||
| 622 | isolation = 0; | ||
| 623 | break; | ||
| 624 | case "medium": | ||
| 625 | isolation = 2; | ||
| 626 | break; | ||
| 627 | case "high": | ||
| 628 | isolation = 1; | ||
| 629 | break; | ||
| 630 | default: | ||
| 631 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, isolationValue, "low", "medium", "high")); | ||
| 632 | break; | ||
| 633 | } | ||
| 634 | } | ||
| 635 | break; | ||
| 636 | case "Name": | ||
| 637 | name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 638 | break; | ||
| 639 | case "ParentPaths": | ||
| 640 | parentPaths = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib); | ||
| 641 | break; | ||
| 642 | case "ScriptTimeout": | ||
| 643 | scriptTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); | ||
| 644 | break; | ||
| 645 | case "ServerDebugging": | ||
| 646 | serverDebugging = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib); | ||
| 647 | break; | ||
| 648 | case "SessionTimeout": | ||
| 649 | sessionTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); | ||
| 650 | break; | ||
| 651 | case "WebAppPool": | ||
| 652 | appPool = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 653 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsAppPool, appPool); | ||
| 654 | break; | ||
| 655 | default: | ||
| 656 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 657 | break; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | else | ||
| 661 | { | ||
| 662 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 663 | } | ||
| 664 | } | ||
| 665 | |||
| 666 | if (null == id) | ||
| 667 | { | ||
| 668 | id = this.ParseHelper.CreateIdentifier("wap", name, appPool); | ||
| 669 | } | ||
| 670 | |||
| 671 | if (null == name) | ||
| 672 | { | ||
| 673 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); | ||
| 674 | } | ||
| 675 | else if (-1 != name.IndexOf("\\", StringComparison.Ordinal)) | ||
| 676 | { | ||
| 677 | this.Messaging.Write(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, element.Name.LocalName, "Name", name, '\\')); | ||
| 678 | } | ||
| 679 | |||
| 680 | foreach (var child in element.Elements()) | ||
| 681 | { | ||
| 682 | if (this.Namespace == child.Name.Namespace) | ||
| 683 | { | ||
| 684 | switch (child.Name.LocalName) | ||
| 685 | { | ||
| 686 | case "WebApplicationExtension": | ||
| 687 | this.ParseWebApplicationExtensionElement(intermediate, section, child, id?.Id); | ||
| 688 | break; | ||
| 689 | default: | ||
| 690 | this.ParseHelper.UnexpectedElement(element, child); | ||
| 691 | break; | ||
| 692 | } | ||
| 693 | } | ||
| 694 | else | ||
| 695 | { | ||
| 696 | this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); | ||
| 697 | } | ||
| 698 | } | ||
| 699 | |||
| 700 | if (!this.Messaging.EncounteredError) | ||
| 701 | { | ||
| 702 | var symbol = section.AddSymbol(new IIsWebApplicationSymbol(sourceLineNumbers, id) | ||
| 703 | { | ||
| 704 | Name = name, | ||
| 705 | Isolation = isolation, | ||
| 706 | DefaultScript = defaultScript, | ||
| 707 | AppPoolRef = appPool, | ||
| 708 | }); | ||
| 709 | |||
| 710 | if (YesNoDefaultType.Default != allowSessions) | ||
| 711 | { | ||
| 712 | symbol.AllowSessions = YesNoDefaultType.Yes == allowSessions ? 1 : 0; | ||
| 713 | } | ||
| 714 | |||
| 715 | if (CompilerConstants.IntegerNotSet != sessionTimeout) | ||
| 716 | { | ||
| 717 | symbol.SessionTimeout = sessionTimeout; | ||
| 718 | } | ||
| 719 | |||
| 720 | if (YesNoDefaultType.Default != buffer) | ||
| 721 | { | ||
| 722 | symbol.Buffer = YesNoDefaultType.Yes == buffer ? 1 : 0; | ||
| 723 | } | ||
| 724 | |||
| 725 | if (YesNoDefaultType.Default != parentPaths) | ||
| 726 | { | ||
| 727 | symbol.ParentPaths = YesNoDefaultType.Yes == parentPaths ? 1 : 0; | ||
| 728 | } | ||
| 729 | |||
| 730 | if (CompilerConstants.IntegerNotSet != scriptTimeout) | ||
| 731 | { | ||
| 732 | symbol.ScriptTimeout = scriptTimeout; | ||
| 733 | } | ||
| 734 | |||
| 735 | if (YesNoDefaultType.Default != serverDebugging) | ||
| 736 | { | ||
| 737 | symbol.ServerDebugging = YesNoDefaultType.Yes == serverDebugging ? 1 : 0; | ||
| 738 | } | ||
| 739 | |||
| 740 | if (YesNoDefaultType.Default != clientDebugging) | ||
| 741 | { | ||
| 742 | symbol.ClientDebugging = YesNoDefaultType.Yes == clientDebugging ? 1 : 0; | ||
| 743 | } | ||
| 744 | } | ||
| 745 | |||
| 746 | return id?.Id; | ||
| 747 | } | ||
| 748 | |||
| 749 | /// <summary> | ||
| 750 | /// Parses a web application extension element. | ||
| 751 | /// </summary> | ||
| 752 | /// <param name="element">Element to parse.</param> | ||
| 753 | /// <param name="application">Identifier for parent web application.</param> | ||
| 754 | private void ParseWebApplicationExtensionElement(Intermediate intermediate, IntermediateSection section, XElement element, string application) | ||
| 755 | { | ||
| 756 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 757 | int attributes = 0; | ||
| 758 | string executable = null; | ||
| 759 | string extension = null; | ||
| 760 | string verbs = null; | ||
| 761 | |||
| 762 | foreach (var attrib in element.Attributes()) | ||
| 763 | { | ||
| 764 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 765 | { | ||
| 766 | switch (attrib.Name.LocalName) | ||
| 767 | { | ||
| 768 | case "CheckPath": | ||
| 769 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 770 | { | ||
| 771 | attributes |= 4; | ||
| 772 | } | ||
| 773 | else | ||
| 774 | { | ||
| 775 | attributes &= ~4; | ||
| 776 | } | ||
| 777 | break; | ||
| 778 | case "Executable": | ||
| 779 | executable = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 780 | break; | ||
| 781 | case "Extension": | ||
| 782 | extension = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 783 | break; | ||
| 784 | case "Script": | ||
| 785 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 786 | { | ||
| 787 | attributes |= 1; | ||
| 788 | } | ||
| 789 | else | ||
| 790 | { | ||
| 791 | attributes &= ~1; | ||
| 792 | } | ||
| 793 | break; | ||
| 794 | case "Verbs": | ||
| 795 | verbs = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 796 | break; | ||
| 797 | default: | ||
| 798 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 799 | break; | ||
| 800 | } | ||
| 801 | } | ||
| 802 | else | ||
| 803 | { | ||
| 804 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 805 | } | ||
| 806 | } | ||
| 807 | |||
| 808 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 809 | |||
| 810 | if (!this.Messaging.EncounteredError) | ||
| 811 | { | ||
| 812 | var symbol = section.AddSymbol(new IIsWebApplicationExtensionSymbol(sourceLineNumbers) | ||
| 813 | { | ||
| 814 | ApplicationRef = application, | ||
| 815 | Extension = extension, | ||
| 816 | Verbs = verbs, | ||
| 817 | Executable = executable, | ||
| 818 | }); | ||
| 819 | |||
| 820 | if (0 < attributes) | ||
| 821 | { | ||
| 822 | symbol.Attributes = attributes; | ||
| 823 | } | ||
| 824 | } | ||
| 825 | } | ||
| 826 | |||
| 827 | /// <summary> | ||
| 828 | /// Parses web application pool element. | ||
| 829 | /// </summary> | ||
| 830 | /// <param name="element">Element to parse.</param> | ||
| 831 | /// <param name="componentId">Optional identifier of parent component.</param> | ||
| 832 | private void ParseWebAppPoolElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) | ||
| 833 | { | ||
| 834 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 835 | Identifier id = null; | ||
| 836 | int attributes = 0; | ||
| 837 | var cpuAction = CompilerConstants.IntegerNotSet; | ||
| 838 | string cpuMon = null; | ||
| 839 | var idleTimeout = CompilerConstants.IntegerNotSet; | ||
| 840 | int maxCpuUsage = 0; | ||
| 841 | var maxWorkerProcs = CompilerConstants.IntegerNotSet; | ||
| 842 | string managedRuntimeVersion = null; | ||
| 843 | string managedPipelineMode = null; | ||
| 844 | string name = null; | ||
| 845 | var privateMemory = CompilerConstants.IntegerNotSet; | ||
| 846 | var queueLimit = CompilerConstants.IntegerNotSet; | ||
| 847 | var recycleMinutes = CompilerConstants.IntegerNotSet; | ||
| 848 | var recycleRequests = CompilerConstants.IntegerNotSet; | ||
| 849 | string recycleTimes = null; | ||
| 850 | var refreshCpu = CompilerConstants.IntegerNotSet; | ||
| 851 | string user = null; | ||
| 852 | var virtualMemory = CompilerConstants.IntegerNotSet; | ||
| 853 | |||
| 854 | foreach (var attrib in element.Attributes()) | ||
| 855 | { | ||
| 856 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 857 | { | ||
| 858 | switch (attrib.Name.LocalName) | ||
| 859 | { | ||
| 860 | case "Id": | ||
| 861 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 862 | break; | ||
| 863 | case "CpuAction": | ||
| 864 | if (null == componentId) | ||
| 865 | { | ||
| 866 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 867 | } | ||
| 868 | |||
| 869 | var cpuActionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 870 | if (0 < cpuActionValue.Length) | ||
| 871 | { | ||
| 872 | switch (cpuActionValue) | ||
| 873 | { | ||
| 874 | case "shutdown": | ||
| 875 | cpuAction = 1; | ||
| 876 | break; | ||
| 877 | case "none": | ||
| 878 | cpuAction = 0; | ||
| 879 | break; | ||
| 880 | default: | ||
| 881 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, cpuActionValue, "shutdown", "none")); | ||
| 882 | break; | ||
| 883 | } | ||
| 884 | } | ||
| 885 | break; | ||
| 886 | case "Identity": | ||
| 887 | if (null == componentId) | ||
| 888 | { | ||
| 889 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 890 | } | ||
| 891 | |||
| 892 | var identityValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 893 | if (0 < identityValue.Length) | ||
| 894 | { | ||
| 895 | switch (identityValue) | ||
| 896 | { | ||
| 897 | case "networkService": | ||
| 898 | attributes |= 1; | ||
| 899 | break; | ||
| 900 | case "localService": | ||
| 901 | attributes |= 2; | ||
| 902 | break; | ||
| 903 | case "localSystem": | ||
| 904 | attributes |= 4; | ||
| 905 | break; | ||
| 906 | case "other": | ||
| 907 | attributes |= 8; | ||
| 908 | break; | ||
| 909 | case "applicationPoolIdentity": | ||
| 910 | attributes |= 0x10; | ||
| 911 | break; | ||
| 912 | default: | ||
| 913 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, identityValue, "networkService", "localService", "localSystem", "other", "applicationPoolIdentity")); | ||
| 914 | break; | ||
| 915 | } | ||
| 916 | } | ||
| 917 | break; | ||
| 918 | case "IdleTimeout": | ||
| 919 | if (null == componentId) | ||
| 920 | { | ||
| 921 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 922 | } | ||
| 923 | |||
| 924 | idleTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); | ||
| 925 | break; | ||
| 926 | case "ManagedPipelineMode": | ||
| 927 | if (null == componentId) | ||
| 928 | { | ||
| 929 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 930 | } | ||
| 931 | |||
| 932 | managedPipelineMode = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 933 | |||
| 934 | |||
| 935 | if (!String.IsNullOrEmpty(managedPipelineMode)) | ||
| 936 | { | ||
| 937 | switch (managedPipelineMode) | ||
| 938 | { | ||
| 939 | // In 3.5 we allowed lower case values (per camel case enum style), we now use formatted fields, | ||
| 940 | // so the value needs to match exactly what we pass in to IIS which uses pascal case. | ||
| 941 | case "classic": | ||
| 942 | managedPipelineMode = "Classic"; | ||
| 943 | break; | ||
| 944 | case "integrated": | ||
| 945 | managedPipelineMode = "Integrated"; | ||
| 946 | break; | ||
| 947 | case "Classic": | ||
| 948 | break; | ||
| 949 | case "Integrated": | ||
| 950 | break; | ||
| 951 | default: | ||
| 952 | if (!this.ParseHelper.ContainsProperty(managedPipelineMode)) | ||
| 953 | { | ||
| 954 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, managedPipelineMode, "Classic", "Integrated")); | ||
| 955 | } | ||
| 956 | break; | ||
| 957 | } | ||
| 958 | } | ||
| 959 | |||
| 960 | break; | ||
| 961 | case "ManagedRuntimeVersion": | ||
| 962 | if (null == componentId) | ||
| 963 | { | ||
| 964 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 965 | } | ||
| 966 | |||
| 967 | managedRuntimeVersion = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 968 | break; | ||
| 969 | case "MaxCpuUsage": | ||
| 970 | if (null == componentId) | ||
| 971 | { | ||
| 972 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 973 | } | ||
| 974 | |||
| 975 | maxCpuUsage = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 100); | ||
| 976 | break; | ||
| 977 | case "MaxWorkerProcesses": | ||
| 978 | if (null == componentId) | ||
| 979 | { | ||
| 980 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 981 | } | ||
| 982 | |||
| 983 | maxWorkerProcs = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); | ||
| 984 | break; | ||
| 985 | case "Name": | ||
| 986 | name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 987 | break; | ||
| 988 | case "PrivateMemory": | ||
| 989 | if (null == componentId) | ||
| 990 | { | ||
| 991 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 992 | } | ||
| 993 | |||
| 994 | privateMemory = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967); | ||
| 995 | break; | ||
| 996 | case "QueueLimit": | ||
| 997 | if (null == componentId) | ||
| 998 | { | ||
| 999 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | queueLimit = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); | ||
| 1003 | break; | ||
| 1004 | case "RecycleMinutes": | ||
| 1005 | if (null == componentId) | ||
| 1006 | { | ||
| 1007 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | recycleMinutes = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); | ||
| 1011 | break; | ||
| 1012 | case "RecycleRequests": | ||
| 1013 | if (null == componentId) | ||
| 1014 | { | ||
| 1015 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | recycleRequests = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); | ||
| 1019 | break; | ||
| 1020 | case "RefreshCpu": | ||
| 1021 | if (null == componentId) | ||
| 1022 | { | ||
| 1023 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | refreshCpu = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue); | ||
| 1027 | break; | ||
| 1028 | case "User": | ||
| 1029 | if (null == componentId) | ||
| 1030 | { | ||
| 1031 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1035 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user); | ||
| 1036 | break; | ||
| 1037 | case "VirtualMemory": | ||
| 1038 | if (null == componentId) | ||
| 1039 | { | ||
| 1040 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | virtualMemory = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967); | ||
| 1044 | break; | ||
| 1045 | default: | ||
| 1046 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 1047 | break; | ||
| 1048 | } | ||
| 1049 | } | ||
| 1050 | else | ||
| 1051 | { | ||
| 1052 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 1053 | } | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | if (null == id) | ||
| 1057 | { | ||
| 1058 | id = this.ParseHelper.CreateIdentifier("iap", name, componentId, user); | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | if (null == name) | ||
| 1062 | { | ||
| 1063 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | if (null == user && 8 == (attributes & 0x1F)) | ||
| 1067 | { | ||
| 1068 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User", "Identity", "other")); | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | if (null != user && 8 != (attributes & 0x1F)) | ||
| 1072 | { | ||
| 1073 | this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithoutOtherAttribute(sourceLineNumbers, element.Name.LocalName, "User", user, "Identity", "other")); | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | cpuMon = maxCpuUsage.ToString(CultureInfo.InvariantCulture.NumberFormat); | ||
| 1077 | if (CompilerConstants.IntegerNotSet != refreshCpu) | ||
| 1078 | { | ||
| 1079 | cpuMon = String.Concat(cpuMon, ",", refreshCpu.ToString(CultureInfo.InvariantCulture.NumberFormat)); | ||
| 1080 | if (CompilerConstants.IntegerNotSet != cpuAction) | ||
| 1081 | { | ||
| 1082 | cpuMon = String.Concat(cpuMon, ",", cpuAction.ToString(CultureInfo.InvariantCulture.NumberFormat)); | ||
| 1083 | } | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | foreach (var child in element.Elements()) | ||
| 1087 | { | ||
| 1088 | if (this.Namespace == child.Name.Namespace) | ||
| 1089 | { | ||
| 1090 | switch (child.Name.LocalName) | ||
| 1091 | { | ||
| 1092 | case "RecycleTime": | ||
| 1093 | if (null == componentId) | ||
| 1094 | { | ||
| 1095 | var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child); | ||
| 1096 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, element.Name.LocalName)); | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | if (null == recycleTimes) | ||
| 1100 | { | ||
| 1101 | recycleTimes = this.ParseRecycleTimeElement(intermediate, section, child); | ||
| 1102 | } | ||
| 1103 | else | ||
| 1104 | { | ||
| 1105 | recycleTimes = String.Concat(recycleTimes, ",", this.ParseRecycleTimeElement(intermediate, section, child)); | ||
| 1106 | } | ||
| 1107 | break; | ||
| 1108 | default: | ||
| 1109 | this.ParseHelper.UnexpectedElement(element, child); | ||
| 1110 | break; | ||
| 1111 | } | ||
| 1112 | } | ||
| 1113 | else | ||
| 1114 | { | ||
| 1115 | this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); | ||
| 1116 | } | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | if (null != componentId) | ||
| 1120 | { | ||
| 1121 | // Reference ConfigureIIs since nothing will happen without it | ||
| 1122 | this.AddReferenceToConfigureIIs(section, sourceLineNumbers); | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | if (!this.Messaging.EncounteredError) | ||
| 1126 | { | ||
| 1127 | var symbol = section.AddSymbol(new IIsAppPoolSymbol(sourceLineNumbers, id) | ||
| 1128 | { | ||
| 1129 | Name = name, | ||
| 1130 | ComponentRef = componentId, | ||
| 1131 | Attributes = attributes, | ||
| 1132 | UserRef = user, | ||
| 1133 | RecycleTimes = recycleTimes, | ||
| 1134 | CPUMon = cpuMon, | ||
| 1135 | ManagedRuntimeVersion = managedRuntimeVersion, | ||
| 1136 | ManagedPipelineMode = managedPipelineMode, | ||
| 1137 | }); | ||
| 1138 | |||
| 1139 | if (CompilerConstants.IntegerNotSet != recycleMinutes) | ||
| 1140 | { | ||
| 1141 | symbol.RecycleMinutes = recycleMinutes; | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | if (CompilerConstants.IntegerNotSet != recycleRequests) | ||
| 1145 | { | ||
| 1146 | symbol.RecycleRequests = recycleRequests; | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | if (CompilerConstants.IntegerNotSet != idleTimeout) | ||
| 1150 | { | ||
| 1151 | symbol.IdleTimeout = idleTimeout; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | if (CompilerConstants.IntegerNotSet != queueLimit) | ||
| 1155 | { | ||
| 1156 | symbol.QueueLimit = queueLimit; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | if (CompilerConstants.IntegerNotSet != maxWorkerProcs) | ||
| 1160 | { | ||
| 1161 | symbol.MaxProc = maxWorkerProcs; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | if (CompilerConstants.IntegerNotSet != virtualMemory) | ||
| 1165 | { | ||
| 1166 | symbol.VirtualMemory = virtualMemory; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | if (CompilerConstants.IntegerNotSet != privateMemory) | ||
| 1170 | { | ||
| 1171 | symbol.PrivateMemory = privateMemory; | ||
| 1172 | } | ||
| 1173 | } | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | /// <summary> | ||
| 1177 | /// Parses a web directory element. | ||
| 1178 | /// </summary> | ||
| 1179 | /// <param name="element">Element to parse.</param> | ||
| 1180 | /// <param name="componentId">Identifier for parent component.</param> | ||
| 1181 | /// <param name="parentWeb">Optional identifier for parent web site.</param> | ||
| 1182 | private void ParseWebDirElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb) | ||
| 1183 | { | ||
| 1184 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 1185 | Identifier id = null; | ||
| 1186 | string dirProperties = null; | ||
| 1187 | string path = null; | ||
| 1188 | string application = null; | ||
| 1189 | |||
| 1190 | foreach (var attrib in element.Attributes()) | ||
| 1191 | { | ||
| 1192 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1193 | { | ||
| 1194 | switch (attrib.Name.LocalName) | ||
| 1195 | { | ||
| 1196 | case "Id": | ||
| 1197 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 1198 | break; | ||
| 1199 | case "DirProperties": | ||
| 1200 | dirProperties = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1201 | break; | ||
| 1202 | case "Path": | ||
| 1203 | path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1204 | break; | ||
| 1205 | case "WebApplication": | ||
| 1206 | application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1207 | break; | ||
| 1208 | case "WebSite": | ||
| 1209 | if (null != parentWeb) | ||
| 1210 | { | ||
| 1211 | this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName)); | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1215 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb); | ||
| 1216 | break; | ||
| 1217 | default: | ||
| 1218 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 1219 | break; | ||
| 1220 | } | ||
| 1221 | } | ||
| 1222 | else | ||
| 1223 | { | ||
| 1224 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 1225 | } | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | if (null == id) | ||
| 1229 | { | ||
| 1230 | id = this.ParseHelper.CreateIdentifier("iwd", componentId, parentWeb, dirProperties, application); | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | if (null == path) | ||
| 1234 | { | ||
| 1235 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path")); | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | if (null == parentWeb) | ||
| 1239 | { | ||
| 1240 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "WebSite")); | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | foreach (var child in element.Elements()) | ||
| 1244 | { | ||
| 1245 | if (this.Namespace == child.Name.Namespace) | ||
| 1246 | { | ||
| 1247 | var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child); | ||
| 1248 | switch (child.Name.LocalName) | ||
| 1249 | { | ||
| 1250 | case "WebApplication": | ||
| 1251 | if (null != application) | ||
| 1252 | { | ||
| 1253 | this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName)); | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | application = this.ParseWebApplicationElement(intermediate, section, child); | ||
| 1257 | break; | ||
| 1258 | case "WebDirProperties": | ||
| 1259 | if (null == componentId) | ||
| 1260 | { | ||
| 1261 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId); | ||
| 1265 | if (null == dirProperties) | ||
| 1266 | { | ||
| 1267 | dirProperties = childWebDirProperties; | ||
| 1268 | } | ||
| 1269 | else | ||
| 1270 | { | ||
| 1271 | this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, child.Name.LocalName, "DirProperties", child.Name.LocalName)); | ||
| 1272 | } | ||
| 1273 | break; | ||
| 1274 | default: | ||
| 1275 | this.ParseHelper.UnexpectedElement(element, child); | ||
| 1276 | break; | ||
| 1277 | } | ||
| 1278 | } | ||
| 1279 | else | ||
| 1280 | { | ||
| 1281 | this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); | ||
| 1282 | } | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | if (null == dirProperties) | ||
| 1286 | { | ||
| 1287 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "DirProperties")); | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | if (null != application) | ||
| 1291 | { | ||
| 1292 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application); | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties); | ||
| 1296 | |||
| 1297 | // Reference ConfigureIIs since nothing will happen without it | ||
| 1298 | this.AddReferenceToConfigureIIs(section, sourceLineNumbers); | ||
| 1299 | |||
| 1300 | if (!this.Messaging.EncounteredError) | ||
| 1301 | { | ||
| 1302 | section.AddSymbol(new IIsWebDirSymbol(sourceLineNumbers, id) | ||
| 1303 | { | ||
| 1304 | ComponentRef = componentId, | ||
| 1305 | WebRef = parentWeb, | ||
| 1306 | Path = path, | ||
| 1307 | DirPropertiesRef = dirProperties, | ||
| 1308 | ApplicationRef = application, | ||
| 1309 | }); | ||
| 1310 | } | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | /// <summary> | ||
| 1314 | /// Parses a web directory properties element. | ||
| 1315 | /// </summary> | ||
| 1316 | /// <param name="element">Element to parse.</param> | ||
| 1317 | /// <returns>The identifier for this WebDirProperties.</returns> | ||
| 1318 | private string ParseWebDirPropertiesElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) | ||
| 1319 | { | ||
| 1320 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 1321 | Identifier id = null; | ||
| 1322 | int access = 0; | ||
| 1323 | var accessSet = false; | ||
| 1324 | int accessSSLFlags = 0; | ||
| 1325 | var accessSSLFlagsSet = false; | ||
| 1326 | string anonymousUser = null; | ||
| 1327 | var aspDetailedError = YesNoType.NotSet; | ||
| 1328 | string authenticationProviders = null; | ||
| 1329 | int authorization = 0; | ||
| 1330 | var authorizationSet = false; | ||
| 1331 | string cacheControlCustom = null; | ||
| 1332 | var cacheControlMaxAge = CompilerConstants.LongNotSet; | ||
| 1333 | string defaultDocuments = null; | ||
| 1334 | string httpExpires = null; | ||
| 1335 | var iisControlledPassword = false; | ||
| 1336 | var index = YesNoType.NotSet; | ||
| 1337 | var logVisits = YesNoType.NotSet; | ||
| 1338 | var notCustomError = YesNoType.NotSet; | ||
| 1339 | |||
| 1340 | foreach (var attrib in element.Attributes()) | ||
| 1341 | { | ||
| 1342 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1343 | { | ||
| 1344 | switch (attrib.Name.LocalName) | ||
| 1345 | { | ||
| 1346 | case "Id": | ||
| 1347 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 1348 | break; | ||
| 1349 | case "AnonymousUser": | ||
| 1350 | anonymousUser = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1351 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", anonymousUser); | ||
| 1352 | break; | ||
| 1353 | case "AspDetailedError": | ||
| 1354 | aspDetailedError = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
| 1355 | break; | ||
| 1356 | case "AuthenticationProviders": | ||
| 1357 | authenticationProviders = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1358 | break; | ||
| 1359 | case "CacheControlCustom": | ||
| 1360 | cacheControlCustom = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1361 | break; | ||
| 1362 | case "CacheControlMaxAge": | ||
| 1363 | cacheControlMaxAge = this.ParseHelper.GetAttributeLongValue(sourceLineNumbers, attrib, 0, uint.MaxValue); // 4294967295 (uint.MaxValue) represents unlimited | ||
| 1364 | break; | ||
| 1365 | case "ClearCustomError": | ||
| 1366 | notCustomError = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
| 1367 | break; | ||
| 1368 | case "DefaultDocuments": | ||
| 1369 | defaultDocuments = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1370 | break; | ||
| 1371 | case "HttpExpires": | ||
| 1372 | httpExpires = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1373 | break; | ||
| 1374 | case "IIsControlledPassword": | ||
| 1375 | iisControlledPassword = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
| 1376 | break; | ||
| 1377 | case "Index": | ||
| 1378 | index = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
| 1379 | break; | ||
| 1380 | case "LogVisits": | ||
| 1381 | logVisits = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
| 1382 | break; | ||
| 1383 | |||
| 1384 | // Access attributes | ||
| 1385 | case "Execute": | ||
| 1386 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1387 | { | ||
| 1388 | access |= 4; | ||
| 1389 | } | ||
| 1390 | else | ||
| 1391 | { | ||
| 1392 | access &= ~4; | ||
| 1393 | } | ||
| 1394 | accessSet = true; | ||
| 1395 | break; | ||
| 1396 | case "Read": | ||
| 1397 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1398 | { | ||
| 1399 | access |= 1; | ||
| 1400 | } | ||
| 1401 | else | ||
| 1402 | { | ||
| 1403 | access &= ~1; | ||
| 1404 | } | ||
| 1405 | accessSet = true; | ||
| 1406 | break; | ||
| 1407 | case "Script": | ||
| 1408 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1409 | { | ||
| 1410 | access |= 512; | ||
| 1411 | } | ||
| 1412 | else | ||
| 1413 | { | ||
| 1414 | access &= ~512; | ||
| 1415 | } | ||
| 1416 | accessSet = true; | ||
| 1417 | break; | ||
| 1418 | case "Write": | ||
| 1419 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1420 | { | ||
| 1421 | access |= 2; | ||
| 1422 | } | ||
| 1423 | else | ||
| 1424 | { | ||
| 1425 | access &= ~2; | ||
| 1426 | } | ||
| 1427 | accessSet = true; | ||
| 1428 | break; | ||
| 1429 | |||
| 1430 | // AccessSSL Attributes | ||
| 1431 | case "AccessSSL": | ||
| 1432 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1433 | { | ||
| 1434 | accessSSLFlags |= 8; | ||
| 1435 | } | ||
| 1436 | else | ||
| 1437 | { | ||
| 1438 | accessSSLFlags &= ~8; | ||
| 1439 | } | ||
| 1440 | accessSSLFlagsSet = true; | ||
| 1441 | break; | ||
| 1442 | case "AccessSSL128": | ||
| 1443 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1444 | { | ||
| 1445 | accessSSLFlags |= 256; | ||
| 1446 | } | ||
| 1447 | else | ||
| 1448 | { | ||
| 1449 | accessSSLFlags &= ~256; | ||
| 1450 | } | ||
| 1451 | accessSSLFlagsSet = true; | ||
| 1452 | break; | ||
| 1453 | case "AccessSSLMapCert": | ||
| 1454 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1455 | { | ||
| 1456 | accessSSLFlags |= 128; | ||
| 1457 | } | ||
| 1458 | else | ||
| 1459 | { | ||
| 1460 | accessSSLFlags &= ~128; | ||
| 1461 | } | ||
| 1462 | accessSSLFlagsSet = true; | ||
| 1463 | break; | ||
| 1464 | case "AccessSSLNegotiateCert": | ||
| 1465 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1466 | { | ||
| 1467 | accessSSLFlags |= 32; | ||
| 1468 | } | ||
| 1469 | else | ||
| 1470 | { | ||
| 1471 | accessSSLFlags &= ~32; | ||
| 1472 | } | ||
| 1473 | accessSSLFlagsSet = true; | ||
| 1474 | break; | ||
| 1475 | case "AccessSSLRequireCert": | ||
| 1476 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1477 | { | ||
| 1478 | accessSSLFlags |= 64; | ||
| 1479 | } | ||
| 1480 | else | ||
| 1481 | { | ||
| 1482 | accessSSLFlags &= ~64; | ||
| 1483 | } | ||
| 1484 | accessSSLFlagsSet = true; | ||
| 1485 | break; | ||
| 1486 | |||
| 1487 | // Authorization attributes | ||
| 1488 | case "AnonymousAccess": | ||
| 1489 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1490 | { | ||
| 1491 | authorization |= 1; | ||
| 1492 | } | ||
| 1493 | else | ||
| 1494 | { | ||
| 1495 | authorization &= ~1; | ||
| 1496 | } | ||
| 1497 | authorizationSet = true; | ||
| 1498 | break; | ||
| 1499 | case "BasicAuthentication": | ||
| 1500 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1501 | { | ||
| 1502 | authorization |= 2; | ||
| 1503 | } | ||
| 1504 | else | ||
| 1505 | { | ||
| 1506 | authorization &= ~2; | ||
| 1507 | } | ||
| 1508 | authorizationSet = true; | ||
| 1509 | break; | ||
| 1510 | case "DigestAuthentication": | ||
| 1511 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1512 | { | ||
| 1513 | authorization |= 16; | ||
| 1514 | } | ||
| 1515 | else | ||
| 1516 | { | ||
| 1517 | authorization &= ~16; | ||
| 1518 | } | ||
| 1519 | authorizationSet = true; | ||
| 1520 | break; | ||
| 1521 | case "PassportAuthentication": | ||
| 1522 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1523 | { | ||
| 1524 | authorization |= 64; | ||
| 1525 | } | ||
| 1526 | else | ||
| 1527 | { | ||
| 1528 | authorization &= ~64; | ||
| 1529 | } | ||
| 1530 | authorizationSet = true; | ||
| 1531 | break; | ||
| 1532 | case "WindowsAuthentication": | ||
| 1533 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1534 | { | ||
| 1535 | authorization |= 4; | ||
| 1536 | } | ||
| 1537 | else | ||
| 1538 | { | ||
| 1539 | authorization &= ~4; | ||
| 1540 | } | ||
| 1541 | authorizationSet = true; | ||
| 1542 | break; | ||
| 1543 | default: | ||
| 1544 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 1545 | break; | ||
| 1546 | } | ||
| 1547 | } | ||
| 1548 | else | ||
| 1549 | { | ||
| 1550 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 1551 | } | ||
| 1552 | } | ||
| 1553 | |||
| 1554 | if (null == id) | ||
| 1555 | { | ||
| 1556 | if (null == componentId) | ||
| 1557 | { | ||
| 1558 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id")); | ||
| 1559 | id = Identifier.Invalid; | ||
| 1560 | } | ||
| 1561 | else | ||
| 1562 | { | ||
| 1563 | id = this.ParseHelper.CreateIdentifier("wdp", componentId); | ||
| 1564 | } | ||
| 1565 | } | ||
| 1566 | |||
| 1567 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 1568 | |||
| 1569 | if (!this.Messaging.EncounteredError) | ||
| 1570 | { | ||
| 1571 | var symbol = section.AddSymbol(new IIsWebDirPropertiesSymbol(sourceLineNumbers, id) | ||
| 1572 | { | ||
| 1573 | AnonymousUserRef = anonymousUser, | ||
| 1574 | IIsControlledPassword = iisControlledPassword ? 1 : 0, | ||
| 1575 | DefaultDoc = defaultDocuments, | ||
| 1576 | HttpExpires = httpExpires, | ||
| 1577 | CacheControlCustom = cacheControlCustom, | ||
| 1578 | }); | ||
| 1579 | |||
| 1580 | if (accessSet) | ||
| 1581 | { | ||
| 1582 | symbol.Access = access; | ||
| 1583 | } | ||
| 1584 | |||
| 1585 | if (authorizationSet) | ||
| 1586 | { | ||
| 1587 | symbol.Authorization = authorization; | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | if (YesNoType.NotSet != logVisits) | ||
| 1591 | { | ||
| 1592 | symbol.LogVisits = YesNoType.Yes == logVisits ? 1 : 0; | ||
| 1593 | } | ||
| 1594 | |||
| 1595 | if (YesNoType.NotSet != index) | ||
| 1596 | { | ||
| 1597 | symbol.Index = YesNoType.Yes == index ? 1 : 0; | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | if (YesNoType.NotSet != aspDetailedError) | ||
| 1601 | { | ||
| 1602 | symbol.AspDetailedError = YesNoType.Yes == aspDetailedError ? 1 : 0; | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | if (CompilerConstants.LongNotSet != cacheControlMaxAge) | ||
| 1606 | { | ||
| 1607 | symbol.CacheControlMaxAge = unchecked((int)cacheControlMaxAge); | ||
| 1608 | } | ||
| 1609 | |||
| 1610 | if (YesNoType.NotSet != notCustomError) | ||
| 1611 | { | ||
| 1612 | symbol.NoCustomError = YesNoType.Yes == notCustomError ? 1 : 0; | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | if (accessSSLFlagsSet) | ||
| 1616 | { | ||
| 1617 | symbol.AccessSSLFlags = accessSSLFlags; | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | if (null != authenticationProviders) | ||
| 1621 | { | ||
| 1622 | symbol.AuthenticationProviders = authenticationProviders; | ||
| 1623 | } | ||
| 1624 | } | ||
| 1625 | |||
| 1626 | return id?.Id; | ||
| 1627 | } | ||
| 1628 | |||
| 1629 | /// <summary> | ||
| 1630 | /// Parses a web error element. | ||
| 1631 | /// </summary> | ||
| 1632 | /// <param name="element">Element to parse.</param> | ||
| 1633 | /// <param name="parentType">Type of the parent.</param> | ||
| 1634 | /// <param name="parent">Id of the parent.</param> | ||
| 1635 | private void ParseWebErrorElement(Intermediate intermediate, IntermediateSection section, XElement element, WebErrorParentType parentType, string parent) | ||
| 1636 | { | ||
| 1637 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 1638 | var errorCode = CompilerConstants.IntegerNotSet; | ||
| 1639 | string file = null; | ||
| 1640 | string url = null; | ||
| 1641 | var subCode = CompilerConstants.IntegerNotSet; | ||
| 1642 | |||
| 1643 | foreach (var attrib in element.Attributes()) | ||
| 1644 | { | ||
| 1645 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1646 | { | ||
| 1647 | switch (attrib.Name.LocalName) | ||
| 1648 | { | ||
| 1649 | case "ErrorCode": | ||
| 1650 | errorCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 400, 599); | ||
| 1651 | break; | ||
| 1652 | case "File": | ||
| 1653 | file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1654 | break; | ||
| 1655 | case "SubCode": | ||
| 1656 | subCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue); | ||
| 1657 | break; | ||
| 1658 | case "URL": | ||
| 1659 | url = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1660 | break; | ||
| 1661 | default: | ||
| 1662 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 1663 | break; | ||
| 1664 | } | ||
| 1665 | } | ||
| 1666 | else | ||
| 1667 | { | ||
| 1668 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 1669 | } | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | if (CompilerConstants.IntegerNotSet == errorCode) | ||
| 1673 | { | ||
| 1674 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ErrorCode")); | ||
| 1675 | errorCode = CompilerConstants.IllegalInteger; | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | if (CompilerConstants.IntegerNotSet == subCode) | ||
| 1679 | { | ||
| 1680 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SubCode")); | ||
| 1681 | subCode = CompilerConstants.IllegalInteger; | ||
| 1682 | } | ||
| 1683 | |||
| 1684 | if (String.IsNullOrEmpty(file) && String.IsNullOrEmpty(url)) | ||
| 1685 | { | ||
| 1686 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "URL")); | ||
| 1687 | } | ||
| 1688 | |||
| 1689 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 1690 | |||
| 1691 | // Reference ConfigureIIs since nothing will happen without it | ||
| 1692 | this.AddReferenceToConfigureIIs(section, sourceLineNumbers); | ||
| 1693 | |||
| 1694 | if (!this.Messaging.EncounteredError) | ||
| 1695 | { | ||
| 1696 | section.AddSymbol(new IIsWebErrorSymbol(sourceLineNumbers) | ||
| 1697 | { | ||
| 1698 | ErrorCode = errorCode, | ||
| 1699 | SubCode = subCode, | ||
| 1700 | ParentType = (int)parentType, | ||
| 1701 | ParentValue = parent, | ||
| 1702 | File = file, | ||
| 1703 | URL = url, | ||
| 1704 | }); | ||
| 1705 | } | ||
| 1706 | } | ||
| 1707 | |||
| 1708 | /// <summary> | ||
| 1709 | /// Parses a web filter element. | ||
| 1710 | /// </summary> | ||
| 1711 | /// <param name="element">Element to parse.</param> | ||
| 1712 | /// <param name="componentId">Identifier of parent component.</param> | ||
| 1713 | /// <param name="parentWeb">Optional identifier of parent web site.</param> | ||
| 1714 | private void ParseWebFilterElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb) | ||
| 1715 | { | ||
| 1716 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 1717 | Identifier id = null; | ||
| 1718 | string description = null; | ||
| 1719 | int flags = 0; | ||
| 1720 | var loadOrder = CompilerConstants.IntegerNotSet; | ||
| 1721 | string name = null; | ||
| 1722 | string path = null; | ||
| 1723 | |||
| 1724 | foreach (var attrib in element.Attributes()) | ||
| 1725 | { | ||
| 1726 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1727 | { | ||
| 1728 | switch (attrib.Name.LocalName) | ||
| 1729 | { | ||
| 1730 | case "Id": | ||
| 1731 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 1732 | break; | ||
| 1733 | case "Description": | ||
| 1734 | description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1735 | break; | ||
| 1736 | case "Flags": | ||
| 1737 | flags = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue); | ||
| 1738 | break; | ||
| 1739 | case "LoadOrder": | ||
| 1740 | string loadOrderValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1741 | if (0 < loadOrderValue.Length) | ||
| 1742 | { | ||
| 1743 | switch (loadOrderValue) | ||
| 1744 | { | ||
| 1745 | case "first": | ||
| 1746 | loadOrder = 0; | ||
| 1747 | break; | ||
| 1748 | case "last": | ||
| 1749 | loadOrder = -1; | ||
| 1750 | break; | ||
| 1751 | default: | ||
| 1752 | loadOrder = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue); | ||
| 1753 | break; | ||
| 1754 | } | ||
| 1755 | } | ||
| 1756 | break; | ||
| 1757 | case "Name": | ||
| 1758 | name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1759 | break; | ||
| 1760 | case "Path": | ||
| 1761 | path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1762 | break; | ||
| 1763 | case "WebSite": | ||
| 1764 | if (null != parentWeb) | ||
| 1765 | { | ||
| 1766 | this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName)); | ||
| 1767 | } | ||
| 1768 | |||
| 1769 | parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1770 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb); | ||
| 1771 | break; | ||
| 1772 | default: | ||
| 1773 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 1774 | break; | ||
| 1775 | } | ||
| 1776 | } | ||
| 1777 | else | ||
| 1778 | { | ||
| 1779 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 1780 | } | ||
| 1781 | } | ||
| 1782 | |||
| 1783 | if (null == id) | ||
| 1784 | { | ||
| 1785 | id = this.ParseHelper.CreateIdentifier("ifl", name, componentId, path, parentWeb); | ||
| 1786 | } | ||
| 1787 | |||
| 1788 | if (null == name) | ||
| 1789 | { | ||
| 1790 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | if (null == path) | ||
| 1794 | { | ||
| 1795 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path")); | ||
| 1796 | } | ||
| 1797 | |||
| 1798 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 1799 | |||
| 1800 | // Reference ConfigureIIs since nothing will happen without it | ||
| 1801 | this.AddReferenceToConfigureIIs(section, sourceLineNumbers); | ||
| 1802 | |||
| 1803 | if (!this.Messaging.EncounteredError) | ||
| 1804 | { | ||
| 1805 | var symbol = section.AddSymbol(new IIsFilterSymbol(sourceLineNumbers, id) | ||
| 1806 | { | ||
| 1807 | Name = name, | ||
| 1808 | ComponentRef = componentId, | ||
| 1809 | Path = path, | ||
| 1810 | WebRef = parentWeb, | ||
| 1811 | Description = description, | ||
| 1812 | Flags = flags, | ||
| 1813 | }); | ||
| 1814 | |||
| 1815 | if (CompilerConstants.IntegerNotSet != loadOrder) | ||
| 1816 | { | ||
| 1817 | symbol.LoadOrder = loadOrder; | ||
| 1818 | } | ||
| 1819 | } | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | /// <summary> | ||
| 1823 | /// Parses web log element. | ||
| 1824 | /// </summary> | ||
| 1825 | /// <param name="element">Node to be parsed.</param> | ||
| 1826 | private void ParseWebLogElement(Intermediate intermediate, IntermediateSection section, XElement element) | ||
| 1827 | { | ||
| 1828 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 1829 | Identifier id = null; | ||
| 1830 | string type = null; | ||
| 1831 | |||
| 1832 | foreach (var attrib in element.Attributes()) | ||
| 1833 | { | ||
| 1834 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1835 | { | ||
| 1836 | switch (attrib.Name.LocalName) | ||
| 1837 | { | ||
| 1838 | case "Id": | ||
| 1839 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 1840 | break; | ||
| 1841 | case "Type": | ||
| 1842 | var typeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1843 | if (0 < typeValue.Length) | ||
| 1844 | { | ||
| 1845 | switch (typeValue) | ||
| 1846 | { | ||
| 1847 | case "IIS": | ||
| 1848 | type = "Microsoft IIS Log File Format"; | ||
| 1849 | break; | ||
| 1850 | case "NCSA": | ||
| 1851 | type = "NCSA Common Log File Format"; | ||
| 1852 | break; | ||
| 1853 | case "none": | ||
| 1854 | type = "none"; | ||
| 1855 | break; | ||
| 1856 | case "ODBC": | ||
| 1857 | type = "ODBC Logging"; | ||
| 1858 | break; | ||
| 1859 | case "W3C": | ||
| 1860 | type = "W3C Extended Log File Format"; | ||
| 1861 | break; | ||
| 1862 | default: | ||
| 1863 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Type", typeValue, "IIS", "NCSA", "none", "ODBC", "W3C")); | ||
| 1864 | break; | ||
| 1865 | } | ||
| 1866 | } | ||
| 1867 | break; | ||
| 1868 | default: | ||
| 1869 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 1870 | break; | ||
| 1871 | } | ||
| 1872 | } | ||
| 1873 | else | ||
| 1874 | { | ||
| 1875 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 1876 | } | ||
| 1877 | } | ||
| 1878 | |||
| 1879 | if (null == id) | ||
| 1880 | { | ||
| 1881 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id")); | ||
| 1882 | } | ||
| 1883 | |||
| 1884 | if (null == type) | ||
| 1885 | { | ||
| 1886 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Type")); | ||
| 1887 | } | ||
| 1888 | |||
| 1889 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 1890 | |||
| 1891 | if (!this.Messaging.EncounteredError) | ||
| 1892 | { | ||
| 1893 | section.AddSymbol(new IIsWebLogSymbol(sourceLineNumbers, id) | ||
| 1894 | { | ||
| 1895 | Format = type, | ||
| 1896 | }); | ||
| 1897 | } | ||
| 1898 | } | ||
| 1899 | |||
| 1900 | /// <summary> | ||
| 1901 | /// Parses a web property element. | ||
| 1902 | /// </summary> | ||
| 1903 | /// <param name="element">Element to parse.</param> | ||
| 1904 | /// <param name="componentId">Identifier for parent component.</param> | ||
| 1905 | private void ParseWebPropertyElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) | ||
| 1906 | { | ||
| 1907 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 1908 | Identifier id = null; | ||
| 1909 | string value = null; | ||
| 1910 | |||
| 1911 | foreach (var attrib in element.Attributes()) | ||
| 1912 | { | ||
| 1913 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1914 | { | ||
| 1915 | switch (attrib.Name.LocalName) | ||
| 1916 | { | ||
| 1917 | case "Id": | ||
| 1918 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 1919 | break; | ||
| 1920 | case "Value": | ||
| 1921 | value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1922 | break; | ||
| 1923 | default: | ||
| 1924 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 1925 | break; | ||
| 1926 | } | ||
| 1927 | } | ||
| 1928 | else | ||
| 1929 | { | ||
| 1930 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 1931 | } | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | switch (id?.Id) | ||
| 1935 | { | ||
| 1936 | case "ETagChangeNumber": | ||
| 1937 | case "MaxGlobalBandwidth": | ||
| 1938 | // Must specify a value for these | ||
| 1939 | if (null == value) | ||
| 1940 | { | ||
| 1941 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value", "Id", id.Id)); | ||
| 1942 | } | ||
| 1943 | break; | ||
| 1944 | case "IIs5IsolationMode": | ||
| 1945 | case "LogInUTF8": | ||
| 1946 | // Can't specify a value for these | ||
| 1947 | if (null != value) | ||
| 1948 | { | ||
| 1949 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Value", "Id", id.Id)); | ||
| 1950 | } | ||
| 1951 | break; | ||
| 1952 | default: | ||
| 1953 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Id", id?.Id, "ETagChangeNumber", "IIs5IsolationMode", "LogInUTF8", "MaxGlobalBandwidth")); | ||
| 1954 | break; | ||
| 1955 | } | ||
| 1956 | |||
| 1957 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 1958 | |||
| 1959 | // Reference ConfigureIIs since nothing will happen without it | ||
| 1960 | this.AddReferenceToConfigureIIs(section, sourceLineNumbers); | ||
| 1961 | |||
| 1962 | if (!this.Messaging.EncounteredError) | ||
| 1963 | { | ||
| 1964 | section.AddSymbol(new IIsPropertySymbol(sourceLineNumbers, id) | ||
| 1965 | { | ||
| 1966 | ComponentRef = componentId, | ||
| 1967 | Attributes = 0, | ||
| 1968 | Value = value, | ||
| 1969 | }); | ||
| 1970 | } | ||
| 1971 | } | ||
| 1972 | |||
| 1973 | /// <summary> | ||
| 1974 | /// Parses a web service extension element. | ||
| 1975 | /// </summary> | ||
| 1976 | /// <param name="element">Element to parse.</param> | ||
| 1977 | /// <param name="componentId">Identifier for parent component.</param> | ||
| 1978 | private void ParseWebServiceExtensionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) | ||
| 1979 | { | ||
| 1980 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 1981 | Identifier id = null; | ||
| 1982 | int attributes = 0; | ||
| 1983 | string description = null; | ||
| 1984 | string file = null; | ||
| 1985 | string group = null; | ||
| 1986 | |||
| 1987 | foreach (XAttribute attrib in element.Attributes()) | ||
| 1988 | { | ||
| 1989 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1990 | { | ||
| 1991 | switch (attrib.Name.LocalName) | ||
| 1992 | { | ||
| 1993 | case "Id": | ||
| 1994 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 1995 | break; | ||
| 1996 | case "Allow": | ||
| 1997 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1998 | { | ||
| 1999 | attributes |= 1; | ||
| 2000 | } | ||
| 2001 | else | ||
| 2002 | { | ||
| 2003 | attributes &= ~1; | ||
| 2004 | } | ||
| 2005 | break; | ||
| 2006 | case "Description": | ||
| 2007 | description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2008 | break; | ||
| 2009 | case "File": | ||
| 2010 | file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2011 | break; | ||
| 2012 | case "Group": | ||
| 2013 | group = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2014 | break; | ||
| 2015 | case "UIDeletable": | ||
| 2016 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 2017 | { | ||
| 2018 | attributes |= 2; | ||
| 2019 | } | ||
| 2020 | else | ||
| 2021 | { | ||
| 2022 | attributes &= ~2; | ||
| 2023 | } | ||
| 2024 | break; | ||
| 2025 | default: | ||
| 2026 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 2027 | break; | ||
| 2028 | } | ||
| 2029 | } | ||
| 2030 | else | ||
| 2031 | { | ||
| 2032 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 2033 | } | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | if (null == id) | ||
| 2037 | { | ||
| 2038 | id = this.ParseHelper.CreateIdentifier("iwe", componentId, file); | ||
| 2039 | } | ||
| 2040 | |||
| 2041 | if (null == file) | ||
| 2042 | { | ||
| 2043 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File")); | ||
| 2044 | } | ||
| 2045 | |||
| 2046 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 2047 | |||
| 2048 | // Reference ConfigureIIs since nothing will happen without it | ||
| 2049 | this.AddReferenceToConfigureIIs(section, sourceLineNumbers); | ||
| 2050 | |||
| 2051 | if (!this.Messaging.EncounteredError) | ||
| 2052 | { | ||
| 2053 | section.AddSymbol(new IIsWebServiceExtensionSymbol(sourceLineNumbers, id) | ||
| 2054 | { | ||
| 2055 | ComponentRef = componentId, | ||
| 2056 | File = file, | ||
| 2057 | Description = description, | ||
| 2058 | Group = group, | ||
| 2059 | Attributes = attributes, | ||
| 2060 | }); | ||
| 2061 | } | ||
| 2062 | } | ||
| 2063 | |||
| 2064 | /// <summary> | ||
| 2065 | /// Parses a web site element. | ||
| 2066 | /// </summary> | ||
| 2067 | /// <param name="element">Element to parse.</param> | ||
| 2068 | /// <param name="componentId">Optional identifier of parent component.</param> | ||
| 2069 | private void ParseWebSiteElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) | ||
| 2070 | { | ||
| 2071 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 2072 | Identifier id = null; | ||
| 2073 | string application = null; | ||
| 2074 | int attributes = 0; | ||
| 2075 | var connectionTimeout = CompilerConstants.IntegerNotSet; | ||
| 2076 | string description = null; | ||
| 2077 | string directory = null; | ||
| 2078 | string dirProperties = null; | ||
| 2079 | string keyAddress = null; | ||
| 2080 | string log = null; | ||
| 2081 | string siteId = null; | ||
| 2082 | var sequence = CompilerConstants.IntegerNotSet; | ||
| 2083 | var state = CompilerConstants.IntegerNotSet; | ||
| 2084 | |||
| 2085 | foreach (var attrib in element.Attributes()) | ||
| 2086 | { | ||
| 2087 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 2088 | { | ||
| 2089 | switch (attrib.Name.LocalName) | ||
| 2090 | { | ||
| 2091 | case "Id": | ||
| 2092 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 2093 | break; | ||
| 2094 | case "AutoStart": | ||
| 2095 | if (null == componentId) | ||
| 2096 | { | ||
| 2097 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 2101 | { | ||
| 2102 | state = 2; | ||
| 2103 | } | ||
| 2104 | else if (state != 1) | ||
| 2105 | { | ||
| 2106 | state = 0; | ||
| 2107 | } | ||
| 2108 | break; | ||
| 2109 | case "ConfigureIfExists": | ||
| 2110 | if (null == componentId) | ||
| 2111 | { | ||
| 2112 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 2113 | } | ||
| 2114 | |||
| 2115 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 2116 | { | ||
| 2117 | attributes &= ~2; | ||
| 2118 | } | ||
| 2119 | else | ||
| 2120 | { | ||
| 2121 | attributes |= 2; | ||
| 2122 | } | ||
| 2123 | break; | ||
| 2124 | case "ConnectionTimeout": | ||
| 2125 | connectionTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); | ||
| 2126 | break; | ||
| 2127 | case "Description": | ||
| 2128 | description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2129 | break; | ||
| 2130 | case "Directory": | ||
| 2131 | directory = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 2132 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, directory); | ||
| 2133 | break; | ||
| 2134 | case "DirProperties": | ||
| 2135 | if (null == componentId) | ||
| 2136 | { | ||
| 2137 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 2138 | } | ||
| 2139 | |||
| 2140 | dirProperties = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2141 | break; | ||
| 2142 | case "SiteId": | ||
| 2143 | siteId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2144 | if ("*" == siteId) | ||
| 2145 | { | ||
| 2146 | siteId = "-1"; | ||
| 2147 | } | ||
| 2148 | break; | ||
| 2149 | case "Sequence": | ||
| 2150 | sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue); | ||
| 2151 | break; | ||
| 2152 | case "StartOnInstall": | ||
| 2153 | if (null == componentId) | ||
| 2154 | { | ||
| 2155 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 2156 | } | ||
| 2157 | |||
| 2158 | // when state is set to 2 it implies 1, so don't set it to 1 | ||
| 2159 | if (2 != state && YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 2160 | { | ||
| 2161 | state = 1; | ||
| 2162 | } | ||
| 2163 | else if (2 != state) | ||
| 2164 | { | ||
| 2165 | state = 0; | ||
| 2166 | } | ||
| 2167 | break; | ||
| 2168 | case "WebApplication": | ||
| 2169 | if (null == componentId) | ||
| 2170 | { | ||
| 2171 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 2172 | } | ||
| 2173 | |||
| 2174 | application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2175 | break; | ||
| 2176 | case "WebLog": | ||
| 2177 | if (null == componentId) | ||
| 2178 | { | ||
| 2179 | this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 2180 | } | ||
| 2181 | |||
| 2182 | log = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 2183 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebLog, log); | ||
| 2184 | break; | ||
| 2185 | default: | ||
| 2186 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 2187 | break; | ||
| 2188 | } | ||
| 2189 | } | ||
| 2190 | else | ||
| 2191 | { | ||
| 2192 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 2193 | } | ||
| 2194 | } | ||
| 2195 | |||
| 2196 | if (null == id) | ||
| 2197 | { | ||
| 2198 | id = this.ParseHelper.CreateIdentifier("iws", description, componentId, siteId, application); | ||
| 2199 | } | ||
| 2200 | |||
| 2201 | if (null == description) | ||
| 2202 | { | ||
| 2203 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Description")); | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | if (null == directory && null != componentId) | ||
| 2207 | { | ||
| 2208 | this.Messaging.Write(IIsErrors.RequiredAttributeUnderComponent(sourceLineNumbers, element.Name.LocalName, "Directory")); | ||
| 2209 | } | ||
| 2210 | |||
| 2211 | foreach (var child in element.Elements()) | ||
| 2212 | { | ||
| 2213 | if (this.Namespace == child.Name.Namespace) | ||
| 2214 | { | ||
| 2215 | var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child); | ||
| 2216 | switch (child.Name.LocalName) | ||
| 2217 | { | ||
| 2218 | case "CertificateRef": | ||
| 2219 | if (null == componentId) | ||
| 2220 | { | ||
| 2221 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 2222 | } | ||
| 2223 | |||
| 2224 | this.ParseCertificateRefElement(intermediate, section, child, id?.Id); | ||
| 2225 | break; | ||
| 2226 | case "HttpHeader": | ||
| 2227 | if (null == componentId) | ||
| 2228 | { | ||
| 2229 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | this.ParseHttpHeaderElement(intermediate, section, child, HttpHeaderParentType.WebSite, id?.Id); | ||
| 2233 | break; | ||
| 2234 | case "WebAddress": | ||
| 2235 | string address = this.ParseWebAddressElement(intermediate, section, child, id?.Id); | ||
| 2236 | if (null == keyAddress) | ||
| 2237 | { | ||
| 2238 | keyAddress = address; | ||
| 2239 | } | ||
| 2240 | break; | ||
| 2241 | case "WebApplication": | ||
| 2242 | if (null == componentId) | ||
| 2243 | { | ||
| 2244 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | if (null != application) | ||
| 2248 | { | ||
| 2249 | this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName)); | ||
| 2250 | } | ||
| 2251 | |||
| 2252 | application = this.ParseWebApplicationElement(intermediate, section, child); | ||
| 2253 | break; | ||
| 2254 | case "WebDir": | ||
| 2255 | if (null == componentId) | ||
| 2256 | { | ||
| 2257 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 2258 | } | ||
| 2259 | |||
| 2260 | this.ParseWebDirElement(intermediate, section, child, componentId, id?.Id); | ||
| 2261 | break; | ||
| 2262 | case "WebDirProperties": | ||
| 2263 | if (null == componentId) | ||
| 2264 | { | ||
| 2265 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 2266 | } | ||
| 2267 | |||
| 2268 | string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId); | ||
| 2269 | if (null == dirProperties) | ||
| 2270 | { | ||
| 2271 | dirProperties = childWebDirProperties; | ||
| 2272 | } | ||
| 2273 | else | ||
| 2274 | { | ||
| 2275 | this.Messaging.Write(ErrorMessages.IllegalParentAttributeWhenNested(sourceLineNumbers, "WebSite", "DirProperties", child.Name.LocalName)); | ||
| 2276 | } | ||
| 2277 | break; | ||
| 2278 | case "WebError": | ||
| 2279 | if (null == componentId) | ||
| 2280 | { | ||
| 2281 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 2282 | } | ||
| 2283 | |||
| 2284 | this.ParseWebErrorElement(intermediate, section, child, WebErrorParentType.WebSite, id?.Id); | ||
| 2285 | break; | ||
| 2286 | case "WebFilter": | ||
| 2287 | if (null == componentId) | ||
| 2288 | { | ||
| 2289 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 2290 | } | ||
| 2291 | |||
| 2292 | this.ParseWebFilterElement(intermediate, section, child, componentId, id?.Id); | ||
| 2293 | break; | ||
| 2294 | case "WebVirtualDir": | ||
| 2295 | if (null == componentId) | ||
| 2296 | { | ||
| 2297 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 2298 | } | ||
| 2299 | |||
| 2300 | this.ParseWebVirtualDirElement(intermediate, section, child, componentId, id?.Id, null); | ||
| 2301 | break; | ||
| 2302 | case "MimeMap": | ||
| 2303 | this.ParseMimeMapElement(intermediate, section, child, id?.Id, MimeMapParentType.WebSite); | ||
| 2304 | break; | ||
| 2305 | default: | ||
| 2306 | this.ParseHelper.UnexpectedElement(element, child); | ||
| 2307 | break; | ||
| 2308 | } | ||
| 2309 | } | ||
| 2310 | else | ||
| 2311 | { | ||
| 2312 | this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); | ||
| 2313 | } | ||
| 2314 | } | ||
| 2315 | |||
| 2316 | |||
| 2317 | if (null == keyAddress) | ||
| 2318 | { | ||
| 2319 | this.Messaging.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, element.Name.LocalName, "WebAddress")); | ||
| 2320 | } | ||
| 2321 | |||
| 2322 | if (null != application) | ||
| 2323 | { | ||
| 2324 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application); | ||
| 2325 | } | ||
| 2326 | |||
| 2327 | if (null != dirProperties) | ||
| 2328 | { | ||
| 2329 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties); | ||
| 2330 | } | ||
| 2331 | |||
| 2332 | if (null != componentId) | ||
| 2333 | { | ||
| 2334 | // Reference ConfigureIIs since nothing will happen without it | ||
| 2335 | this.AddReferenceToConfigureIIs(section, sourceLineNumbers); | ||
| 2336 | } | ||
| 2337 | |||
| 2338 | if (!this.Messaging.EncounteredError) | ||
| 2339 | { | ||
| 2340 | var symbol = section.AddSymbol(new IIsWebSiteSymbol(sourceLineNumbers, id) | ||
| 2341 | { | ||
| 2342 | ComponentRef = componentId, | ||
| 2343 | Description = description, | ||
| 2344 | DirectoryRef = directory, | ||
| 2345 | KeyAddressRef = keyAddress, | ||
| 2346 | DirPropertiesRef = dirProperties, | ||
| 2347 | ApplicationRef = application, | ||
| 2348 | LogRef = log, | ||
| 2349 | WebsiteId = siteId, | ||
| 2350 | }); | ||
| 2351 | |||
| 2352 | if (CompilerConstants.IntegerNotSet != connectionTimeout) | ||
| 2353 | { | ||
| 2354 | symbol.ConnectionTimeout = connectionTimeout; | ||
| 2355 | } | ||
| 2356 | |||
| 2357 | if (CompilerConstants.IntegerNotSet != state) | ||
| 2358 | { | ||
| 2359 | symbol.State = state; | ||
| 2360 | } | ||
| 2361 | |||
| 2362 | if (0 != attributes) | ||
| 2363 | { | ||
| 2364 | symbol.Attributes = attributes; | ||
| 2365 | } | ||
| 2366 | |||
| 2367 | if (CompilerConstants.IntegerNotSet != sequence) | ||
| 2368 | { | ||
| 2369 | symbol.Sequence = sequence; | ||
| 2370 | } | ||
| 2371 | } | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | /// <summary> | ||
| 2375 | /// Parses a HTTP Header element. | ||
| 2376 | /// </summary> | ||
| 2377 | /// <param name="element">Element to parse.</param> | ||
| 2378 | /// <param name="parentType">Type of the parent.</param> | ||
| 2379 | /// <param name="parent">Id of the parent.</param> | ||
| 2380 | private void ParseHttpHeaderElement(Intermediate intermediate, IntermediateSection section, XElement element, HttpHeaderParentType parentType, string parent) | ||
| 2381 | { | ||
| 2382 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 2383 | Identifier id = null; | ||
| 2384 | string headerName = null; | ||
| 2385 | string headerValue = null; | ||
| 2386 | |||
| 2387 | foreach (var attrib in element.Attributes()) | ||
| 2388 | { | ||
| 2389 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 2390 | { | ||
| 2391 | switch (attrib.Name.LocalName) | ||
| 2392 | { | ||
| 2393 | case "Id": | ||
| 2394 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 2395 | break; | ||
| 2396 | case "Name": | ||
| 2397 | headerName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2398 | break; | ||
| 2399 | case "Value": | ||
| 2400 | headerValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2401 | break; | ||
| 2402 | default: | ||
| 2403 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 2404 | break; | ||
| 2405 | } | ||
| 2406 | } | ||
| 2407 | else | ||
| 2408 | { | ||
| 2409 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 2410 | } | ||
| 2411 | } | ||
| 2412 | |||
| 2413 | if (null == headerName) | ||
| 2414 | { | ||
| 2415 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); | ||
| 2416 | } | ||
| 2417 | else if (null == id) | ||
| 2418 | { | ||
| 2419 | id = this.ParseHelper.CreateIdentifierFromFilename(headerName); | ||
| 2420 | } | ||
| 2421 | |||
| 2422 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 2423 | |||
| 2424 | // Reference ConfigureIIs since nothing will happen without it | ||
| 2425 | this.AddReferenceToConfigureIIs(section, sourceLineNumbers); | ||
| 2426 | |||
| 2427 | if (!this.Messaging.EncounteredError) | ||
| 2428 | { | ||
| 2429 | section.AddSymbol(new IIsHttpHeaderSymbol(sourceLineNumbers, id) | ||
| 2430 | { | ||
| 2431 | HttpHeader = id.Id, | ||
| 2432 | ParentType = (int)parentType, | ||
| 2433 | ParentValue = parent, | ||
| 2434 | Name = headerName, | ||
| 2435 | Value = headerValue, | ||
| 2436 | Attributes = 0, | ||
| 2437 | }); | ||
| 2438 | } | ||
| 2439 | } | ||
| 2440 | |||
| 2441 | /// <summary> | ||
| 2442 | /// Parses a virtual directory element. | ||
| 2443 | /// </summary> | ||
| 2444 | /// <param name="element">Element to parse.</param> | ||
| 2445 | /// <param name="componentId">Identifier of parent component.</param> | ||
| 2446 | /// <param name="parentWeb">Identifier of parent web site.</param> | ||
| 2447 | /// <param name="parentAlias">Alias of the parent web site.</param> | ||
| 2448 | private void ParseWebVirtualDirElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb, string parentAlias) | ||
| 2449 | { | ||
| 2450 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 2451 | Identifier id = null; | ||
| 2452 | string alias = null; | ||
| 2453 | string application = null; | ||
| 2454 | string directory = null; | ||
| 2455 | string dirProperties = null; | ||
| 2456 | |||
| 2457 | foreach (var attrib in element.Attributes()) | ||
| 2458 | { | ||
| 2459 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 2460 | { | ||
| 2461 | switch (attrib.Name.LocalName) | ||
| 2462 | { | ||
| 2463 | case "Id": | ||
| 2464 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 2465 | break; | ||
| 2466 | case "Alias": | ||
| 2467 | alias = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2468 | break; | ||
| 2469 | case "Directory": | ||
| 2470 | directory = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 2471 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, directory); | ||
| 2472 | break; | ||
| 2473 | case "DirProperties": | ||
| 2474 | dirProperties = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2475 | break; | ||
| 2476 | case "WebApplication": | ||
| 2477 | application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2478 | break; | ||
| 2479 | case "WebSite": | ||
| 2480 | if (null != parentWeb) | ||
| 2481 | { | ||
| 2482 | this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName)); | ||
| 2483 | } | ||
| 2484 | |||
| 2485 | parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 2486 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb); | ||
| 2487 | break; | ||
| 2488 | default: | ||
| 2489 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 2490 | break; | ||
| 2491 | } | ||
| 2492 | } | ||
| 2493 | else | ||
| 2494 | { | ||
| 2495 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 2496 | } | ||
| 2497 | } | ||
| 2498 | |||
| 2499 | if (null == id) | ||
| 2500 | { | ||
| 2501 | id = this.ParseHelper.CreateIdentifier("wvd", alias, directory, dirProperties, application, parentWeb); | ||
| 2502 | } | ||
| 2503 | |||
| 2504 | if (null == alias) | ||
| 2505 | { | ||
| 2506 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Alias")); | ||
| 2507 | } | ||
| 2508 | else if (-1 != alias.IndexOf("\\", StringComparison.Ordinal)) | ||
| 2509 | { | ||
| 2510 | this.Messaging.Write(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, element.Name.LocalName, "Alias", alias, '\\')); | ||
| 2511 | } | ||
| 2512 | |||
| 2513 | if (null == directory) | ||
| 2514 | { | ||
| 2515 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Directory")); | ||
| 2516 | } | ||
| 2517 | |||
| 2518 | if (null == parentWeb) | ||
| 2519 | { | ||
| 2520 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "WebSite")); | ||
| 2521 | } | ||
| 2522 | |||
| 2523 | if (null == componentId) | ||
| 2524 | { | ||
| 2525 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(sourceLineNumbers, element.Name.LocalName)); | ||
| 2526 | } | ||
| 2527 | |||
| 2528 | if (null != parentAlias) | ||
| 2529 | { | ||
| 2530 | alias = String.Concat(parentAlias, "/", alias); | ||
| 2531 | } | ||
| 2532 | |||
| 2533 | foreach (var child in element.Elements()) | ||
| 2534 | { | ||
| 2535 | if (this.Namespace == child.Name.Namespace) | ||
| 2536 | { | ||
| 2537 | var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child); | ||
| 2538 | switch (child.Name.LocalName) | ||
| 2539 | { | ||
| 2540 | case "WebApplication": | ||
| 2541 | if (null != application) | ||
| 2542 | { | ||
| 2543 | this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName)); | ||
| 2544 | } | ||
| 2545 | |||
| 2546 | application = this.ParseWebApplicationElement(intermediate, section, child); | ||
| 2547 | break; | ||
| 2548 | case "WebDirProperties": | ||
| 2549 | if (null == componentId) | ||
| 2550 | { | ||
| 2551 | this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 2552 | } | ||
| 2553 | |||
| 2554 | string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId); | ||
| 2555 | if (null == dirProperties) | ||
| 2556 | { | ||
| 2557 | dirProperties = childWebDirProperties; | ||
| 2558 | } | ||
| 2559 | else | ||
| 2560 | { | ||
| 2561 | this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, child.Name.LocalName, "DirProperties", child.Name.LocalName)); | ||
| 2562 | } | ||
| 2563 | break; | ||
| 2564 | |||
| 2565 | case "WebError": | ||
| 2566 | this.ParseWebErrorElement(intermediate, section, child, WebErrorParentType.WebVirtualDir, id?.Id); | ||
| 2567 | break; | ||
| 2568 | case "WebVirtualDir": | ||
| 2569 | this.ParseWebVirtualDirElement(intermediate, section, child, componentId, parentWeb, alias); | ||
| 2570 | break; | ||
| 2571 | case "HttpHeader": | ||
| 2572 | this.ParseHttpHeaderElement(intermediate, section, child, HttpHeaderParentType.WebVirtualDir, id?.Id); | ||
| 2573 | break; | ||
| 2574 | case "MimeMap": | ||
| 2575 | this.ParseMimeMapElement(intermediate, section, child, id?.Id, MimeMapParentType.WebVirtualDir); | ||
| 2576 | break; | ||
| 2577 | default: | ||
| 2578 | this.ParseHelper.UnexpectedElement(element, child); | ||
| 2579 | break; | ||
| 2580 | } | ||
| 2581 | } | ||
| 2582 | else | ||
| 2583 | { | ||
| 2584 | this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); | ||
| 2585 | } | ||
| 2586 | } | ||
| 2587 | |||
| 2588 | if (null != dirProperties) | ||
| 2589 | { | ||
| 2590 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties); | ||
| 2591 | } | ||
| 2592 | |||
| 2593 | if (null != application) | ||
| 2594 | { | ||
| 2595 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application); | ||
| 2596 | } | ||
| 2597 | |||
| 2598 | // Reference ConfigureIIs since nothing will happen without it | ||
| 2599 | this.AddReferenceToConfigureIIs(section, sourceLineNumbers); | ||
| 2600 | |||
| 2601 | if (!this.Messaging.EncounteredError) | ||
| 2602 | { | ||
| 2603 | section.AddSymbol(new IIsWebVirtualDirSymbol(sourceLineNumbers, id) | ||
| 2604 | { | ||
| 2605 | ComponentRef = componentId, | ||
| 2606 | WebRef = parentWeb, | ||
| 2607 | Alias = alias, | ||
| 2608 | DirectoryRef = directory, | ||
| 2609 | DirPropertiesRef = dirProperties, | ||
| 2610 | ApplicationRef = application, | ||
| 2611 | }); | ||
| 2612 | } | ||
| 2613 | } | ||
| 2614 | |||
| 2615 | private void AddReferenceToConfigureIIs(IntermediateSection section, SourceLineNumber sourceLineNumbers) | ||
| 2616 | { | ||
| 2617 | this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureIIs", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); | ||
| 2618 | } | ||
| 2619 | } | ||
| 2620 | } | ||
diff --git a/src/ext/Iis/wixext/IIsDecompiler.cs b/src/ext/Iis/wixext/IIsDecompiler.cs new file mode 100644 index 00000000..17e15348 --- /dev/null +++ b/src/ext/Iis/wixext/IIsDecompiler.cs | |||
| @@ -0,0 +1,1549 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | #if TODO_CONSIDER_DECOMPILER | ||
| 6 | using System; | ||
| 7 | using System.Collections; | ||
| 8 | using System.Globalization; | ||
| 9 | using WixToolset.Data; | ||
| 10 | using WixToolset.Extensibility; | ||
| 11 | using IIs = WixToolset.Extensions.Serialize.IIs; | ||
| 12 | using Wix = WixToolset.Data.Serialize; | ||
| 13 | |||
| 14 | /// <summary> | ||
| 15 | /// The decompiler for the WiX Toolset Internet Information Services Extension. | ||
| 16 | /// </summary> | ||
| 17 | public sealed class IIsDecompiler : DecompilerExtension | ||
| 18 | { | ||
| 19 | /// <summary> | ||
| 20 | /// Creates a decompiler for IIs Extension. | ||
| 21 | /// </summary> | ||
| 22 | public IIsDecompiler() | ||
| 23 | { | ||
| 24 | this.TableDefinitions = IIsExtensionData.GetExtensionTableDefinitions(); | ||
| 25 | } | ||
| 26 | |||
| 27 | /// <summary> | ||
| 28 | /// Get the extensions library to be removed. | ||
| 29 | /// </summary> | ||
| 30 | /// <param name="tableDefinitions">Table definitions for library.</param> | ||
| 31 | /// <returns>Library to remove from decompiled output.</returns> | ||
| 32 | public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions) | ||
| 33 | { | ||
| 34 | return IIsExtensionData.GetExtensionLibrary(tableDefinitions); | ||
| 35 | } | ||
| 36 | |||
| 37 | /// <summary> | ||
| 38 | /// Decompiles an extension table. | ||
| 39 | /// </summary> | ||
| 40 | /// <param name="table">The table to decompile.</param> | ||
| 41 | public override void DecompileTable(Table table) | ||
| 42 | { | ||
| 43 | switch (table.Name) | ||
| 44 | { | ||
| 45 | case "Certificate": | ||
| 46 | this.DecompileCertificateTable(table); | ||
| 47 | break; | ||
| 48 | case "CertificateHash": | ||
| 49 | // There is nothing to do for this table, it contains no authored data | ||
| 50 | // to be decompiled. | ||
| 51 | break; | ||
| 52 | case "IIsAppPool": | ||
| 53 | this.DecompileIIsAppPoolTable(table); | ||
| 54 | break; | ||
| 55 | case "IIsFilter": | ||
| 56 | this.DecompileIIsFilterTable(table); | ||
| 57 | break; | ||
| 58 | case "IIsProperty": | ||
| 59 | this.DecompileIIsPropertyTable(table); | ||
| 60 | break; | ||
| 61 | case "IIsHttpHeader": | ||
| 62 | this.DecompileIIsHttpHeaderTable(table); | ||
| 63 | break; | ||
| 64 | case "IIsMimeMap": | ||
| 65 | this.DecompileIIsMimeMapTable(table); | ||
| 66 | break; | ||
| 67 | case "IIsWebAddress": | ||
| 68 | this.DecompileIIsWebAddressTable(table); | ||
| 69 | break; | ||
| 70 | case "IIsWebApplication": | ||
| 71 | this.DecompileIIsWebApplicationTable(table); | ||
| 72 | break; | ||
| 73 | case "IIsWebDirProperties": | ||
| 74 | this.DecompileIIsWebDirPropertiesTable(table); | ||
| 75 | break; | ||
| 76 | case "IIsWebError": | ||
| 77 | this.DecompileIIsWebErrorTable(table); | ||
| 78 | break; | ||
| 79 | case "IIsWebLog": | ||
| 80 | this.DecompileIIsWebLogTable(table); | ||
| 81 | break; | ||
| 82 | case "IIsWebServiceExtension": | ||
| 83 | this.DecompileIIsWebServiceExtensionTable(table); | ||
| 84 | break; | ||
| 85 | case "IIsWebSite": | ||
| 86 | this.DecompileIIsWebSiteTable(table); | ||
| 87 | break; | ||
| 88 | case "IIsWebVirtualDir": | ||
| 89 | this.DecompileIIsWebVirtualDirTable(table); | ||
| 90 | break; | ||
| 91 | case "IIsWebSiteCertificates": | ||
| 92 | this.DecompileIIsWebSiteCertificatesTable(table); | ||
| 93 | break; | ||
| 94 | default: | ||
| 95 | base.DecompileTable(table); | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | /// <summary> | ||
| 101 | /// Finalize decompilation. | ||
| 102 | /// </summary> | ||
| 103 | /// <param name="tables">The collection of all tables.</param> | ||
| 104 | public override void Finish(TableIndexedCollection tables) | ||
| 105 | { | ||
| 106 | this.FinalizeIIsMimeMapTable(tables); | ||
| 107 | this.FinalizeIIsHttpHeaderTable(tables); | ||
| 108 | this.FinalizeIIsWebApplicationTable(tables); | ||
| 109 | this.FinalizeIIsWebErrorTable(tables); | ||
| 110 | this.FinalizeIIsWebVirtualDirTable(tables); | ||
| 111 | this.FinalizeIIsWebSiteCertificatesTable(tables); | ||
| 112 | this.FinalizeWebAddressTable(tables); | ||
| 113 | } | ||
| 114 | |||
| 115 | /// <summary> | ||
| 116 | /// Decompile the Certificate table. | ||
| 117 | /// </summary> | ||
| 118 | /// <param name="table">The table to decompile.</param> | ||
| 119 | private void DecompileCertificateTable(Table table) | ||
| 120 | { | ||
| 121 | foreach (Row row in table.Rows) | ||
| 122 | { | ||
| 123 | IIs.Certificate certificate = new IIs.Certificate(); | ||
| 124 | |||
| 125 | certificate.Id = (string)row[0]; | ||
| 126 | certificate.Name = (string)row[2]; | ||
| 127 | |||
| 128 | switch ((int)row[3]) | ||
| 129 | { | ||
| 130 | case 1: | ||
| 131 | certificate.StoreLocation = IIs.Certificate.StoreLocationType.currentUser; | ||
| 132 | break; | ||
| 133 | case 2: | ||
| 134 | certificate.StoreLocation = IIs.Certificate.StoreLocationType.localMachine; | ||
| 135 | break; | ||
| 136 | default: | ||
| 137 | // TODO: warn | ||
| 138 | break; | ||
| 139 | } | ||
| 140 | |||
| 141 | switch ((string)row[4]) | ||
| 142 | { | ||
| 143 | case "CA": | ||
| 144 | certificate.StoreName = IIs.Certificate.StoreNameType.ca; | ||
| 145 | break; | ||
| 146 | case "MY": | ||
| 147 | certificate.StoreName = IIs.Certificate.StoreNameType.my; | ||
| 148 | break; | ||
| 149 | case "REQUEST": | ||
| 150 | certificate.StoreName = IIs.Certificate.StoreNameType.request; | ||
| 151 | break; | ||
| 152 | case "Root": | ||
| 153 | certificate.StoreName = IIs.Certificate.StoreNameType.root; | ||
| 154 | break; | ||
| 155 | case "AddressBook": | ||
| 156 | certificate.StoreName = IIs.Certificate.StoreNameType.otherPeople; | ||
| 157 | break; | ||
| 158 | case "TrustedPeople": | ||
| 159 | certificate.StoreName = IIs.Certificate.StoreNameType.trustedPeople; | ||
| 160 | break; | ||
| 161 | case "TrustedPublisher": | ||
| 162 | certificate.StoreName = IIs.Certificate.StoreNameType.trustedPublisher; | ||
| 163 | break; | ||
| 164 | default: | ||
| 165 | // TODO: warn | ||
| 166 | break; | ||
| 167 | } | ||
| 168 | |||
| 169 | int attribute = (int)row[5]; | ||
| 170 | |||
| 171 | if (0x1 == (attribute & 0x1)) | ||
| 172 | { | ||
| 173 | certificate.Request = IIs.YesNoType.yes; | ||
| 174 | } | ||
| 175 | |||
| 176 | if (0x2 == (attribute & 0x2)) | ||
| 177 | { | ||
| 178 | if (null != row[6]) | ||
| 179 | { | ||
| 180 | certificate.BinaryKey = (string)row[6]; | ||
| 181 | } | ||
| 182 | else | ||
| 183 | { | ||
| 184 | // TODO: warn about expected value in row 5 | ||
| 185 | } | ||
| 186 | } | ||
| 187 | else if (null != row[7]) | ||
| 188 | { | ||
| 189 | certificate.CertificatePath = (string)row[7]; | ||
| 190 | } | ||
| 191 | |||
| 192 | if (0x4 == (attribute & 0x4)) | ||
| 193 | { | ||
| 194 | certificate.Overwrite = IIs.YesNoType.yes; | ||
| 195 | } | ||
| 196 | |||
| 197 | if (null != row[8]) | ||
| 198 | { | ||
| 199 | certificate.PFXPassword = (string)row[8]; | ||
| 200 | } | ||
| 201 | |||
| 202 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); | ||
| 203 | if (null != component) | ||
| 204 | { | ||
| 205 | component.AddChild(certificate); | ||
| 206 | } | ||
| 207 | else | ||
| 208 | { | ||
| 209 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | /// <summary> | ||
| 215 | /// Decompile the IIsAppPool table. | ||
| 216 | /// </summary> | ||
| 217 | /// <param name="table">The table to decompile.</param> | ||
| 218 | private void DecompileIIsAppPoolTable(Table table) | ||
| 219 | { | ||
| 220 | foreach (Row row in table.Rows) | ||
| 221 | { | ||
| 222 | IIs.WebAppPool webAppPool = new IIs.WebAppPool(); | ||
| 223 | |||
| 224 | webAppPool.Id = (string)row[0]; | ||
| 225 | |||
| 226 | webAppPool.Name = (string)row[1]; | ||
| 227 | |||
| 228 | switch ((int)row[3] & 0x1F) | ||
| 229 | { | ||
| 230 | case 1: | ||
| 231 | webAppPool.Identity = IIs.WebAppPool.IdentityType.networkService; | ||
| 232 | break; | ||
| 233 | case 2: | ||
| 234 | webAppPool.Identity = IIs.WebAppPool.IdentityType.localService; | ||
| 235 | break; | ||
| 236 | case 4: | ||
| 237 | webAppPool.Identity = IIs.WebAppPool.IdentityType.localSystem; | ||
| 238 | break; | ||
| 239 | case 8: | ||
| 240 | webAppPool.Identity = IIs.WebAppPool.IdentityType.other; | ||
| 241 | break; | ||
| 242 | case 0x10: | ||
| 243 | webAppPool.Identity = IIs.WebAppPool.IdentityType.applicationPoolIdentity; | ||
| 244 | break; | ||
| 245 | default: | ||
| 246 | // TODO: warn | ||
| 247 | break; | ||
| 248 | } | ||
| 249 | |||
| 250 | if (null != row[4]) | ||
| 251 | { | ||
| 252 | webAppPool.User = (string)row[4]; | ||
| 253 | } | ||
| 254 | |||
| 255 | if (null != row[5]) | ||
| 256 | { | ||
| 257 | webAppPool.RecycleMinutes = (int)row[5]; | ||
| 258 | } | ||
| 259 | |||
| 260 | if (null != row[6]) | ||
| 261 | { | ||
| 262 | webAppPool.RecycleRequests = (int)row[6]; | ||
| 263 | } | ||
| 264 | |||
| 265 | if (null != row[7]) | ||
| 266 | { | ||
| 267 | string[] recycleTimeValues = ((string)row[7]).Split(','); | ||
| 268 | |||
| 269 | foreach (string recycleTimeValue in recycleTimeValues) | ||
| 270 | { | ||
| 271 | IIs.RecycleTime recycleTime = new IIs.RecycleTime(); | ||
| 272 | |||
| 273 | recycleTime.Value = recycleTimeValue; | ||
| 274 | |||
| 275 | webAppPool.AddChild(recycleTime); | ||
| 276 | } | ||
| 277 | } | ||
| 278 | |||
| 279 | if (null != row[8]) | ||
| 280 | { | ||
| 281 | webAppPool.IdleTimeout = (int)row[8]; | ||
| 282 | } | ||
| 283 | |||
| 284 | if (null != row[9]) | ||
| 285 | { | ||
| 286 | webAppPool.QueueLimit = (int)row[9]; | ||
| 287 | } | ||
| 288 | |||
| 289 | if (null != row[10]) | ||
| 290 | { | ||
| 291 | string[] cpuMon = ((string)row[10]).Split(','); | ||
| 292 | |||
| 293 | if (0 < cpuMon.Length && "0" != cpuMon[0]) | ||
| 294 | { | ||
| 295 | webAppPool.MaxCpuUsage = Convert.ToInt32(cpuMon[0], CultureInfo.InvariantCulture); | ||
| 296 | } | ||
| 297 | |||
| 298 | if (1 < cpuMon.Length) | ||
| 299 | { | ||
| 300 | webAppPool.RefreshCpu = Convert.ToInt32(cpuMon[1], CultureInfo.InvariantCulture); | ||
| 301 | } | ||
| 302 | |||
| 303 | if (2 < cpuMon.Length) | ||
| 304 | { | ||
| 305 | switch (Convert.ToInt32(cpuMon[2], CultureInfo.InvariantCulture)) | ||
| 306 | { | ||
| 307 | case 0: | ||
| 308 | webAppPool.CpuAction = IIs.WebAppPool.CpuActionType.none; | ||
| 309 | break; | ||
| 310 | case 1: | ||
| 311 | webAppPool.CpuAction = IIs.WebAppPool.CpuActionType.shutdown; | ||
| 312 | break; | ||
| 313 | default: | ||
| 314 | // TODO: warn | ||
| 315 | break; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | if (3 < cpuMon.Length) | ||
| 320 | { | ||
| 321 | // TODO: warn | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | if (null != row[11]) | ||
| 326 | { | ||
| 327 | webAppPool.MaxWorkerProcesses = (int)row[11]; | ||
| 328 | } | ||
| 329 | |||
| 330 | if (null != row[12]) | ||
| 331 | { | ||
| 332 | webAppPool.VirtualMemory = (int)row[12]; | ||
| 333 | } | ||
| 334 | |||
| 335 | if (null != row[13]) | ||
| 336 | { | ||
| 337 | webAppPool.PrivateMemory = (int)row[13]; | ||
| 338 | } | ||
| 339 | |||
| 340 | if (null != row[14]) | ||
| 341 | { | ||
| 342 | webAppPool.ManagedRuntimeVersion = (string)row[14]; | ||
| 343 | } | ||
| 344 | |||
| 345 | if (null != row[15]) | ||
| 346 | { | ||
| 347 | webAppPool.ManagedPipelineMode = (string)row[15]; | ||
| 348 | } | ||
| 349 | |||
| 350 | if (null != row[2]) | ||
| 351 | { | ||
| 352 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 353 | |||
| 354 | if (null != component) | ||
| 355 | { | ||
| 356 | component.AddChild(webAppPool); | ||
| 357 | } | ||
| 358 | else | ||
| 359 | { | ||
| 360 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 361 | } | ||
| 362 | } | ||
| 363 | else | ||
| 364 | { | ||
| 365 | this.Core.RootElement.AddChild(webAppPool); | ||
| 366 | } | ||
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 370 | /// <summary> | ||
| 371 | /// Decompile the IIsProperty table. | ||
| 372 | /// </summary> | ||
| 373 | /// <param name="table">The table to decompile.</param> | ||
| 374 | private void DecompileIIsPropertyTable(Table table) | ||
| 375 | { | ||
| 376 | foreach (Row row in table.Rows) | ||
| 377 | { | ||
| 378 | IIs.WebProperty webProperty = new IIs.WebProperty(); | ||
| 379 | |||
| 380 | switch ((string)row[0]) | ||
| 381 | { | ||
| 382 | case "ETagChangeNumber": | ||
| 383 | webProperty.Id = IIs.WebProperty.IdType.ETagChangeNumber; | ||
| 384 | break; | ||
| 385 | case "IIs5IsolationMode": | ||
| 386 | webProperty.Id = IIs.WebProperty.IdType.IIs5IsolationMode; | ||
| 387 | break; | ||
| 388 | case "LogInUTF8": | ||
| 389 | webProperty.Id = IIs.WebProperty.IdType.LogInUTF8; | ||
| 390 | break; | ||
| 391 | case "MaxGlobalBandwidth": | ||
| 392 | webProperty.Id = IIs.WebProperty.IdType.MaxGlobalBandwidth; | ||
| 393 | break; | ||
| 394 | } | ||
| 395 | |||
| 396 | if (0 != (int)row[2]) | ||
| 397 | { | ||
| 398 | // TODO: warn about value in unused column | ||
| 399 | } | ||
| 400 | |||
| 401 | if (null != row[3]) | ||
| 402 | { | ||
| 403 | webProperty.Value = (string)row[3]; | ||
| 404 | } | ||
| 405 | |||
| 406 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); | ||
| 407 | if (null != component) | ||
| 408 | { | ||
| 409 | component.AddChild(webProperty); | ||
| 410 | } | ||
| 411 | else | ||
| 412 | { | ||
| 413 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); | ||
| 414 | } | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | /// <summary> | ||
| 419 | /// Decompile the IIsHttpHeader table. | ||
| 420 | /// </summary> | ||
| 421 | /// <param name="table">The table to decompile.</param> | ||
| 422 | private void DecompileIIsHttpHeaderTable(Table table) | ||
| 423 | { | ||
| 424 | foreach (Row row in table.Rows) | ||
| 425 | { | ||
| 426 | IIs.HttpHeader httpHeader = new IIs.HttpHeader(); | ||
| 427 | |||
| 428 | httpHeader.Name = (string)row[3]; | ||
| 429 | |||
| 430 | // the ParentType and Parent columns are handled in FinalizeIIsHttpHeaderTable | ||
| 431 | |||
| 432 | httpHeader.Value = (string)row[4]; | ||
| 433 | |||
| 434 | this.Core.IndexElement(row, httpHeader); | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | /// <summary> | ||
| 439 | /// Decompile the IIsMimeMap table. | ||
| 440 | /// </summary> | ||
| 441 | /// <param name="table">The table to decompile.</param> | ||
| 442 | private void DecompileIIsMimeMapTable(Table table) | ||
| 443 | { | ||
| 444 | foreach (Row row in table.Rows) | ||
| 445 | { | ||
| 446 | IIs.MimeMap mimeMap = new IIs.MimeMap(); | ||
| 447 | |||
| 448 | mimeMap.Id = (string)row[0]; | ||
| 449 | |||
| 450 | // the ParentType and ParentValue columns are handled in FinalizeIIsMimeMapTable | ||
| 451 | |||
| 452 | mimeMap.Type = (string)row[3]; | ||
| 453 | |||
| 454 | mimeMap.Extension = (string)row[4]; | ||
| 455 | |||
| 456 | this.Core.IndexElement(row, mimeMap); | ||
| 457 | } | ||
| 458 | } | ||
| 459 | |||
| 460 | /// <summary> | ||
| 461 | /// Decompile the IIsWebAddress table. | ||
| 462 | /// </summary> | ||
| 463 | /// <param name="table">The table to decompile.</param> | ||
| 464 | private void DecompileIIsWebAddressTable(Table table) | ||
| 465 | { | ||
| 466 | foreach (Row row in table.Rows) | ||
| 467 | { | ||
| 468 | IIs.WebAddress webAddress = new IIs.WebAddress(); | ||
| 469 | |||
| 470 | webAddress.Id = (string)row[0]; | ||
| 471 | |||
| 472 | if (null != row[2]) | ||
| 473 | { | ||
| 474 | webAddress.IP = (string)row[2]; | ||
| 475 | } | ||
| 476 | |||
| 477 | webAddress.Port = (string)row[3]; | ||
| 478 | |||
| 479 | if (null != row[4]) | ||
| 480 | { | ||
| 481 | webAddress.Header = (string)row[4]; | ||
| 482 | } | ||
| 483 | |||
| 484 | if (null != row[5] && 1 == (int)row[5]) | ||
| 485 | { | ||
| 486 | webAddress.Secure = IIs.YesNoType.yes; | ||
| 487 | } | ||
| 488 | |||
| 489 | this.Core.IndexElement(row, webAddress); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | /// <summary> | ||
| 494 | /// Decompile the IIsWebApplication table. | ||
| 495 | /// </summary> | ||
| 496 | /// <param name="table">The table to decompile.</param> | ||
| 497 | private void DecompileIIsWebApplicationTable(Table table) | ||
| 498 | { | ||
| 499 | foreach (Row row in table.Rows) | ||
| 500 | { | ||
| 501 | IIs.WebApplication webApplication = new IIs.WebApplication(); | ||
| 502 | |||
| 503 | webApplication.Id = (string)row[0]; | ||
| 504 | |||
| 505 | webApplication.Name = (string)row[1]; | ||
| 506 | |||
| 507 | // these are not listed incorrectly - the order is low, high, medium | ||
| 508 | switch ((int)row[2]) | ||
| 509 | { | ||
| 510 | case 0: | ||
| 511 | webApplication.Isolation = IIs.WebApplication.IsolationType.low; | ||
| 512 | break; | ||
| 513 | case 1: | ||
| 514 | webApplication.Isolation = IIs.WebApplication.IsolationType.high; | ||
| 515 | break; | ||
| 516 | case 2: | ||
| 517 | webApplication.Isolation = IIs.WebApplication.IsolationType.medium; | ||
| 518 | break; | ||
| 519 | default: | ||
| 520 | // TODO: warn | ||
| 521 | break; | ||
| 522 | } | ||
| 523 | |||
| 524 | if (null != row[3]) | ||
| 525 | { | ||
| 526 | switch ((int)row[3]) | ||
| 527 | { | ||
| 528 | case 0: | ||
| 529 | webApplication.AllowSessions = IIs.YesNoDefaultType.no; | ||
| 530 | break; | ||
| 531 | case 1: | ||
| 532 | webApplication.AllowSessions = IIs.YesNoDefaultType.yes; | ||
| 533 | break; | ||
| 534 | default: | ||
| 535 | // TODO: warn | ||
| 536 | break; | ||
| 537 | } | ||
| 538 | } | ||
| 539 | |||
| 540 | if (null != row[4]) | ||
| 541 | { | ||
| 542 | webApplication.SessionTimeout = (int)row[4]; | ||
| 543 | } | ||
| 544 | |||
| 545 | if (null != row[5]) | ||
| 546 | { | ||
| 547 | switch ((int)row[5]) | ||
| 548 | { | ||
| 549 | case 0: | ||
| 550 | webApplication.Buffer = IIs.YesNoDefaultType.no; | ||
| 551 | break; | ||
| 552 | case 1: | ||
| 553 | webApplication.Buffer = IIs.YesNoDefaultType.yes; | ||
| 554 | break; | ||
| 555 | default: | ||
| 556 | // TODO: warn | ||
| 557 | break; | ||
| 558 | } | ||
| 559 | } | ||
| 560 | |||
| 561 | if (null != row[6]) | ||
| 562 | { | ||
| 563 | switch ((int)row[6]) | ||
| 564 | { | ||
| 565 | case 0: | ||
| 566 | webApplication.ParentPaths = IIs.YesNoDefaultType.no; | ||
| 567 | break; | ||
| 568 | case 1: | ||
| 569 | webApplication.ParentPaths = IIs.YesNoDefaultType.yes; | ||
| 570 | break; | ||
| 571 | default: | ||
| 572 | // TODO: warn | ||
| 573 | break; | ||
| 574 | } | ||
| 575 | } | ||
| 576 | |||
| 577 | if (null != row[7]) | ||
| 578 | { | ||
| 579 | switch ((string)row[7]) | ||
| 580 | { | ||
| 581 | case "JScript": | ||
| 582 | webApplication.DefaultScript = IIs.WebApplication.DefaultScriptType.JScript; | ||
| 583 | break; | ||
| 584 | case "VBScript": | ||
| 585 | webApplication.DefaultScript = IIs.WebApplication.DefaultScriptType.VBScript; | ||
| 586 | break; | ||
| 587 | default: | ||
| 588 | // TODO: warn | ||
| 589 | break; | ||
| 590 | } | ||
| 591 | } | ||
| 592 | |||
| 593 | if (null != row[8]) | ||
| 594 | { | ||
| 595 | webApplication.ScriptTimeout = (int)row[8]; | ||
| 596 | } | ||
| 597 | |||
| 598 | if (null != row[9]) | ||
| 599 | { | ||
| 600 | switch ((int)row[9]) | ||
| 601 | { | ||
| 602 | case 0: | ||
| 603 | webApplication.ServerDebugging = IIs.YesNoDefaultType.no; | ||
| 604 | break; | ||
| 605 | case 1: | ||
| 606 | webApplication.ServerDebugging = IIs.YesNoDefaultType.yes; | ||
| 607 | break; | ||
| 608 | default: | ||
| 609 | // TODO: warn | ||
| 610 | break; | ||
| 611 | } | ||
| 612 | } | ||
| 613 | |||
| 614 | if (null != row[10]) | ||
| 615 | { | ||
| 616 | switch ((int)row[10]) | ||
| 617 | { | ||
| 618 | case 0: | ||
| 619 | webApplication.ClientDebugging = IIs.YesNoDefaultType.no; | ||
| 620 | break; | ||
| 621 | case 1: | ||
| 622 | webApplication.ClientDebugging = IIs.YesNoDefaultType.yes; | ||
| 623 | break; | ||
| 624 | default: | ||
| 625 | // TODO: warn | ||
| 626 | break; | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 630 | if (null != row[11]) | ||
| 631 | { | ||
| 632 | webApplication.WebAppPool = (string)row[11]; | ||
| 633 | } | ||
| 634 | |||
| 635 | this.Core.IndexElement(row, webApplication); | ||
| 636 | } | ||
| 637 | } | ||
| 638 | |||
| 639 | /// <summary> | ||
| 640 | /// Decompile the IIsWebDirProperties table. | ||
| 641 | /// </summary> | ||
| 642 | /// <param name="table">The table to decompile.</param> | ||
| 643 | private void DecompileIIsWebDirPropertiesTable(Table table) | ||
| 644 | { | ||
| 645 | foreach (Row row in table.Rows) | ||
| 646 | { | ||
| 647 | IIs.WebDirProperties webDirProperties = new IIs.WebDirProperties(); | ||
| 648 | |||
| 649 | webDirProperties.Id = (string)row[0]; | ||
| 650 | |||
| 651 | if (null != row[1]) | ||
| 652 | { | ||
| 653 | int access = (int)row[1]; | ||
| 654 | |||
| 655 | if (0x1 == (access & 0x1)) | ||
| 656 | { | ||
| 657 | webDirProperties.Read = IIs.YesNoType.yes; | ||
| 658 | } | ||
| 659 | |||
| 660 | if (0x2 == (access & 0x2)) | ||
| 661 | { | ||
| 662 | webDirProperties.Write = IIs.YesNoType.yes; | ||
| 663 | } | ||
| 664 | |||
| 665 | if (0x4 == (access & 0x4)) | ||
| 666 | { | ||
| 667 | webDirProperties.Execute = IIs.YesNoType.yes; | ||
| 668 | } | ||
| 669 | |||
| 670 | if (0x200 == (access & 0x200)) | ||
| 671 | { | ||
| 672 | webDirProperties.Script = IIs.YesNoType.yes; | ||
| 673 | } | ||
| 674 | } | ||
| 675 | |||
| 676 | if (null != row[2]) | ||
| 677 | { | ||
| 678 | int authorization = (int)row[2]; | ||
| 679 | |||
| 680 | if (0x1 == (authorization & 0x1)) | ||
| 681 | { | ||
| 682 | webDirProperties.AnonymousAccess = IIs.YesNoType.yes; | ||
| 683 | } | ||
| 684 | else // set one of the properties to 'no' to force the output value to be '0' if not other attributes are set | ||
| 685 | { | ||
| 686 | webDirProperties.AnonymousAccess = IIs.YesNoType.no; | ||
| 687 | } | ||
| 688 | |||
| 689 | if (0x2 == (authorization & 0x2)) | ||
| 690 | { | ||
| 691 | webDirProperties.BasicAuthentication = IIs.YesNoType.yes; | ||
| 692 | } | ||
| 693 | |||
| 694 | if (0x4 == (authorization & 0x4)) | ||
| 695 | { | ||
| 696 | webDirProperties.WindowsAuthentication = IIs.YesNoType.yes; | ||
| 697 | } | ||
| 698 | |||
| 699 | if (0x10 == (authorization & 0x10)) | ||
| 700 | { | ||
| 701 | webDirProperties.DigestAuthentication = IIs.YesNoType.yes; | ||
| 702 | } | ||
| 703 | |||
| 704 | if (0x40 == (authorization & 0x40)) | ||
| 705 | { | ||
| 706 | webDirProperties.PassportAuthentication = IIs.YesNoType.yes; | ||
| 707 | } | ||
| 708 | } | ||
| 709 | |||
| 710 | if (null != row[3]) | ||
| 711 | { | ||
| 712 | webDirProperties.AnonymousUser = (string)row[3]; | ||
| 713 | } | ||
| 714 | |||
| 715 | if (null != row[4] && 1 == (int)row[4]) | ||
| 716 | { | ||
| 717 | webDirProperties.IIsControlledPassword = IIs.YesNoType.yes; | ||
| 718 | } | ||
| 719 | |||
| 720 | if (null != row[5]) | ||
| 721 | { | ||
| 722 | switch ((int)row[5]) | ||
| 723 | { | ||
| 724 | case 0: | ||
| 725 | webDirProperties.LogVisits = IIs.YesNoType.no; | ||
| 726 | break; | ||
| 727 | case 1: | ||
| 728 | webDirProperties.LogVisits = IIs.YesNoType.yes; | ||
| 729 | break; | ||
| 730 | default: | ||
| 731 | // TODO: warn | ||
| 732 | break; | ||
| 733 | } | ||
| 734 | } | ||
| 735 | |||
| 736 | if (null != row[6]) | ||
| 737 | { | ||
| 738 | switch ((int)row[6]) | ||
| 739 | { | ||
| 740 | case 0: | ||
| 741 | webDirProperties.Index = IIs.YesNoType.no; | ||
| 742 | break; | ||
| 743 | case 1: | ||
| 744 | webDirProperties.Index = IIs.YesNoType.yes; | ||
| 745 | break; | ||
| 746 | default: | ||
| 747 | // TODO: warn | ||
| 748 | break; | ||
| 749 | } | ||
| 750 | } | ||
| 751 | |||
| 752 | if (null != row[7]) | ||
| 753 | { | ||
| 754 | webDirProperties.DefaultDocuments = (string)row[7]; | ||
| 755 | } | ||
| 756 | |||
| 757 | if (null != row[8]) | ||
| 758 | { | ||
| 759 | switch ((int)row[8]) | ||
| 760 | { | ||
| 761 | case 0: | ||
| 762 | webDirProperties.AspDetailedError = IIs.YesNoType.no; | ||
| 763 | break; | ||
| 764 | case 1: | ||
| 765 | webDirProperties.AspDetailedError = IIs.YesNoType.yes; | ||
| 766 | break; | ||
| 767 | default: | ||
| 768 | // TODO: warn | ||
| 769 | break; | ||
| 770 | } | ||
| 771 | } | ||
| 772 | |||
| 773 | if (null != row[9]) | ||
| 774 | { | ||
| 775 | webDirProperties.HttpExpires = (string)row[9]; | ||
| 776 | } | ||
| 777 | |||
| 778 | if (null != row[10]) | ||
| 779 | { | ||
| 780 | // force the value to be a positive number | ||
| 781 | webDirProperties.CacheControlMaxAge = unchecked((uint)(int)row[10]); | ||
| 782 | } | ||
| 783 | |||
| 784 | if (null != row[11]) | ||
| 785 | { | ||
| 786 | webDirProperties.CacheControlCustom = (string)row[11]; | ||
| 787 | } | ||
| 788 | |||
| 789 | if (null != row[12]) | ||
| 790 | { | ||
| 791 | switch ((int)row[8]) | ||
| 792 | { | ||
| 793 | case 0: | ||
| 794 | webDirProperties.ClearCustomError = IIs.YesNoType.no; | ||
| 795 | break; | ||
| 796 | case 1: | ||
| 797 | webDirProperties.ClearCustomError = IIs.YesNoType.yes; | ||
| 798 | break; | ||
| 799 | default: | ||
| 800 | // TODO: warn | ||
| 801 | break; | ||
| 802 | } | ||
| 803 | } | ||
| 804 | |||
| 805 | if (null != row[13]) | ||
| 806 | { | ||
| 807 | int accessSSLFlags = (int)row[13]; | ||
| 808 | |||
| 809 | if (0x8 == (accessSSLFlags & 0x8)) | ||
| 810 | { | ||
| 811 | webDirProperties.AccessSSL = IIs.YesNoType.yes; | ||
| 812 | } | ||
| 813 | |||
| 814 | if (0x20 == (accessSSLFlags & 0x20)) | ||
| 815 | { | ||
| 816 | webDirProperties.AccessSSLNegotiateCert = IIs.YesNoType.yes; | ||
| 817 | } | ||
| 818 | |||
| 819 | if (0x40 == (accessSSLFlags & 0x40)) | ||
| 820 | { | ||
| 821 | webDirProperties.AccessSSLRequireCert = IIs.YesNoType.yes; | ||
| 822 | } | ||
| 823 | |||
| 824 | if (0x80 == (accessSSLFlags & 0x80)) | ||
| 825 | { | ||
| 826 | webDirProperties.AccessSSLMapCert = IIs.YesNoType.yes; | ||
| 827 | } | ||
| 828 | |||
| 829 | if (0x100 == (accessSSLFlags & 0x100)) | ||
| 830 | { | ||
| 831 | webDirProperties.AccessSSL128 = IIs.YesNoType.yes; | ||
| 832 | } | ||
| 833 | } | ||
| 834 | |||
| 835 | if (null != row[14]) | ||
| 836 | { | ||
| 837 | webDirProperties.AuthenticationProviders = (string)row[14]; | ||
| 838 | } | ||
| 839 | |||
| 840 | this.Core.RootElement.AddChild(webDirProperties); | ||
| 841 | } | ||
| 842 | } | ||
| 843 | |||
| 844 | /// <summary> | ||
| 845 | /// Decompile the IIsWebError table. | ||
| 846 | /// </summary> | ||
| 847 | /// <param name="table">The table to decompile.</param> | ||
| 848 | private void DecompileIIsWebErrorTable(Table table) | ||
| 849 | { | ||
| 850 | foreach (Row row in table.Rows) | ||
| 851 | { | ||
| 852 | IIs.WebError webError = new IIs.WebError(); | ||
| 853 | |||
| 854 | webError.ErrorCode = (int)row[0]; | ||
| 855 | |||
| 856 | webError.SubCode = (int)row[1]; | ||
| 857 | |||
| 858 | // the ParentType and ParentValue columns are handled in FinalizeIIsWebErrorTable | ||
| 859 | |||
| 860 | if (null != row[4]) | ||
| 861 | { | ||
| 862 | webError.File = (string)row[4]; | ||
| 863 | } | ||
| 864 | |||
| 865 | if (null != row[5]) | ||
| 866 | { | ||
| 867 | webError.URL = (string)row[5]; | ||
| 868 | } | ||
| 869 | |||
| 870 | this.Core.IndexElement(row, webError); | ||
| 871 | } | ||
| 872 | } | ||
| 873 | |||
| 874 | /// <summary> | ||
| 875 | /// Decompile the IIsFilter table. | ||
| 876 | /// </summary> | ||
| 877 | /// <param name="table">The table to decompile.</param> | ||
| 878 | private void DecompileIIsFilterTable(Table table) | ||
| 879 | { | ||
| 880 | foreach (Row row in table.Rows) | ||
| 881 | { | ||
| 882 | IIs.WebFilter webFilter = new IIs.WebFilter(); | ||
| 883 | |||
| 884 | webFilter.Id = (string)row[0]; | ||
| 885 | |||
| 886 | webFilter.Name = (string)row[1]; | ||
| 887 | |||
| 888 | if (null != row[3]) | ||
| 889 | { | ||
| 890 | webFilter.Path = (string)row[3]; | ||
| 891 | } | ||
| 892 | |||
| 893 | if (null != row[5]) | ||
| 894 | { | ||
| 895 | webFilter.Description = (string)row[5]; | ||
| 896 | } | ||
| 897 | |||
| 898 | webFilter.Flags = (int)row[6]; | ||
| 899 | |||
| 900 | if (null != row[7]) | ||
| 901 | { | ||
| 902 | switch ((int)row[7]) | ||
| 903 | { | ||
| 904 | case (-1): | ||
| 905 | webFilter.LoadOrder = "last"; | ||
| 906 | break; | ||
| 907 | case 0: | ||
| 908 | webFilter.LoadOrder = "first"; | ||
| 909 | break; | ||
| 910 | default: | ||
| 911 | webFilter.LoadOrder = Convert.ToString((int)row[7], CultureInfo.InvariantCulture); | ||
| 912 | break; | ||
| 913 | } | ||
| 914 | } | ||
| 915 | |||
| 916 | if (null != row[4]) | ||
| 917 | { | ||
| 918 | IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[4]); | ||
| 919 | |||
| 920 | if (null != webSite) | ||
| 921 | { | ||
| 922 | webSite.AddChild(webFilter); | ||
| 923 | } | ||
| 924 | else | ||
| 925 | { | ||
| 926 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[4], "IIsWebSite")); | ||
| 927 | } | ||
| 928 | } | ||
| 929 | else // Component parent | ||
| 930 | { | ||
| 931 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 932 | |||
| 933 | if (null != component) | ||
| 934 | { | ||
| 935 | component.AddChild(webFilter); | ||
| 936 | } | ||
| 937 | else | ||
| 938 | { | ||
| 939 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 940 | } | ||
| 941 | } | ||
| 942 | } | ||
| 943 | } | ||
| 944 | |||
| 945 | /// <summary> | ||
| 946 | /// Decompile the IIsWebLog table. | ||
| 947 | /// </summary> | ||
| 948 | /// <param name="table">The table to decompile.</param> | ||
| 949 | private void DecompileIIsWebLogTable(Table table) | ||
| 950 | { | ||
| 951 | foreach (Row row in table.Rows) | ||
| 952 | { | ||
| 953 | IIs.WebLog webLog = new IIs.WebLog(); | ||
| 954 | |||
| 955 | webLog.Id = (string)row[0]; | ||
| 956 | |||
| 957 | switch ((string)row[1]) | ||
| 958 | { | ||
| 959 | case "Microsoft IIS Log File Format": | ||
| 960 | webLog.Type = IIs.WebLog.TypeType.IIS; | ||
| 961 | break; | ||
| 962 | case "NCSA Common Log File Format": | ||
| 963 | webLog.Type = IIs.WebLog.TypeType.NCSA; | ||
| 964 | break; | ||
| 965 | case "none": | ||
| 966 | webLog.Type = IIs.WebLog.TypeType.none; | ||
| 967 | break; | ||
| 968 | case "ODBC Logging": | ||
| 969 | webLog.Type = IIs.WebLog.TypeType.ODBC; | ||
| 970 | break; | ||
| 971 | case "W3C Extended Log File Format": | ||
| 972 | webLog.Type = IIs.WebLog.TypeType.W3C; | ||
| 973 | break; | ||
| 974 | default: | ||
| 975 | // TODO: warn | ||
| 976 | break; | ||
| 977 | } | ||
| 978 | |||
| 979 | this.Core.RootElement.AddChild(webLog); | ||
| 980 | } | ||
| 981 | } | ||
| 982 | |||
| 983 | /// <summary> | ||
| 984 | /// Decompile the IIsWebServiceExtension table. | ||
| 985 | /// </summary> | ||
| 986 | /// <param name="table">The table to decompile.</param> | ||
| 987 | private void DecompileIIsWebServiceExtensionTable(Table table) | ||
| 988 | { | ||
| 989 | foreach (Row row in table.Rows) | ||
| 990 | { | ||
| 991 | IIs.WebServiceExtension webServiceExtension = new IIs.WebServiceExtension(); | ||
| 992 | |||
| 993 | webServiceExtension.Id = (string)row[0]; | ||
| 994 | |||
| 995 | webServiceExtension.File = (string)row[2]; | ||
| 996 | |||
| 997 | if (null != row[3]) | ||
| 998 | { | ||
| 999 | webServiceExtension.Description = (string)row[3]; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | if (null != row[4]) | ||
| 1003 | { | ||
| 1004 | webServiceExtension.Group = (string)row[4]; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | int attributes = (int)row[5]; | ||
| 1008 | |||
| 1009 | if (0x1 == (attributes & 0x1)) | ||
| 1010 | { | ||
| 1011 | webServiceExtension.Allow = IIs.YesNoType.yes; | ||
| 1012 | } | ||
| 1013 | else | ||
| 1014 | { | ||
| 1015 | webServiceExtension.Allow = IIs.YesNoType.no; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | if (0x2 == (attributes & 0x2)) | ||
| 1019 | { | ||
| 1020 | webServiceExtension.UIDeletable = IIs.YesNoType.yes; | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); | ||
| 1024 | if (null != component) | ||
| 1025 | { | ||
| 1026 | component.AddChild(webServiceExtension); | ||
| 1027 | } | ||
| 1028 | else | ||
| 1029 | { | ||
| 1030 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); | ||
| 1031 | } | ||
| 1032 | } | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | /// <summary> | ||
| 1036 | /// Decompile the IIsWebSite table. | ||
| 1037 | /// </summary> | ||
| 1038 | /// <param name="table">The table to decompile.</param> | ||
| 1039 | private void DecompileIIsWebSiteTable(Table table) | ||
| 1040 | { | ||
| 1041 | foreach (Row row in table.Rows) | ||
| 1042 | { | ||
| 1043 | IIs.WebSite webSite = new IIs.WebSite(); | ||
| 1044 | |||
| 1045 | webSite.Id = (string)row[0]; | ||
| 1046 | |||
| 1047 | if (null != row[2]) | ||
| 1048 | { | ||
| 1049 | webSite.Description = (string)row[2]; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | if (null != row[3]) | ||
| 1053 | { | ||
| 1054 | webSite.ConnectionTimeout = (int)row[3]; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | if (null != row[4]) | ||
| 1058 | { | ||
| 1059 | webSite.Directory = (string)row[4]; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | if (null != row[5]) | ||
| 1063 | { | ||
| 1064 | switch ((int)row[5]) | ||
| 1065 | { | ||
| 1066 | case 0: | ||
| 1067 | // this is the default | ||
| 1068 | break; | ||
| 1069 | case 1: | ||
| 1070 | webSite.StartOnInstall = IIs.YesNoType.yes; | ||
| 1071 | break; | ||
| 1072 | case 2: | ||
| 1073 | webSite.AutoStart = IIs.YesNoType.yes; | ||
| 1074 | break; | ||
| 1075 | default: | ||
| 1076 | // TODO: warn | ||
| 1077 | break; | ||
| 1078 | } | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | if (null != row[6]) | ||
| 1082 | { | ||
| 1083 | int attributes = (int)row[6]; | ||
| 1084 | |||
| 1085 | if (0x2 == (attributes & 0x2)) | ||
| 1086 | { | ||
| 1087 | webSite.ConfigureIfExists = IIs.YesNoType.no; | ||
| 1088 | } | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | // the KeyAddress_ column is handled in FinalizeWebAddressTable | ||
| 1092 | |||
| 1093 | if (null != row[8]) | ||
| 1094 | { | ||
| 1095 | webSite.DirProperties = (string)row[8]; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | // the Application_ column is handled in FinalizeIIsWebApplicationTable | ||
| 1099 | |||
| 1100 | if (null != row[10]) | ||
| 1101 | { | ||
| 1102 | if (-1 != (int)row[10]) | ||
| 1103 | { | ||
| 1104 | webSite.Sequence = (int)row[10]; | ||
| 1105 | } | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | if (null != row[11]) | ||
| 1109 | { | ||
| 1110 | webSite.WebLog = (string)row[11]; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | if (null != row[12]) | ||
| 1114 | { | ||
| 1115 | webSite.SiteId = (string)row[12]; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | if (null != row[1]) | ||
| 1119 | { | ||
| 1120 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); | ||
| 1121 | |||
| 1122 | if (null != component) | ||
| 1123 | { | ||
| 1124 | component.AddChild(webSite); | ||
| 1125 | } | ||
| 1126 | else | ||
| 1127 | { | ||
| 1128 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); | ||
| 1129 | } | ||
| 1130 | } | ||
| 1131 | else | ||
| 1132 | { | ||
| 1133 | this.Core.RootElement.AddChild(webSite); | ||
| 1134 | } | ||
| 1135 | this.Core.IndexElement(row, webSite); | ||
| 1136 | } | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | /// <summary> | ||
| 1140 | /// Decompile the IIsWebVirtualDir table. | ||
| 1141 | /// </summary> | ||
| 1142 | /// <param name="table">The table to decompile.</param> | ||
| 1143 | private void DecompileIIsWebVirtualDirTable(Table table) | ||
| 1144 | { | ||
| 1145 | foreach (Row row in table.Rows) | ||
| 1146 | { | ||
| 1147 | IIs.WebVirtualDir webVirtualDir = new IIs.WebVirtualDir(); | ||
| 1148 | |||
| 1149 | webVirtualDir.Id = (string)row[0]; | ||
| 1150 | |||
| 1151 | // the Component_ and Web_ columns are handled in FinalizeIIsWebVirtualDirTable | ||
| 1152 | |||
| 1153 | webVirtualDir.Alias = (string)row[3]; | ||
| 1154 | |||
| 1155 | webVirtualDir.Directory = (string)row[4]; | ||
| 1156 | |||
| 1157 | if (null != row[5]) | ||
| 1158 | { | ||
| 1159 | webVirtualDir.DirProperties = (string)row[5]; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | // the Application_ column is handled in FinalizeIIsWebApplicationTable | ||
| 1163 | |||
| 1164 | this.Core.IndexElement(row, webVirtualDir); | ||
| 1165 | } | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | /// <summary> | ||
| 1169 | /// Decompile the IIsWebSiteCertificates table. | ||
| 1170 | /// </summary> | ||
| 1171 | /// <param name="table">The table to decompile.</param> | ||
| 1172 | private void DecompileIIsWebSiteCertificatesTable(Table table) | ||
| 1173 | { | ||
| 1174 | foreach (Row row in table.Rows) | ||
| 1175 | { | ||
| 1176 | IIs.CertificateRef certificateRef = new IIs.CertificateRef(); | ||
| 1177 | |||
| 1178 | certificateRef.Id = (string)row[1]; | ||
| 1179 | |||
| 1180 | this.Core.IndexElement(row, certificateRef); | ||
| 1181 | } | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | /// <summary> | ||
| 1185 | /// Finalize the IIsHttpHeader table. | ||
| 1186 | /// </summary> | ||
| 1187 | /// <param name="tables">The collection of all tables.</param> | ||
| 1188 | /// <remarks> | ||
| 1189 | /// The IIsHttpHeader table supports multiple parent types so no foreign key | ||
| 1190 | /// is declared and thus nesting must be done late. | ||
| 1191 | /// </remarks> | ||
| 1192 | private void FinalizeIIsHttpHeaderTable(TableIndexedCollection tables) | ||
| 1193 | { | ||
| 1194 | Table iisHttpHeaderTable = tables["IIsHttpHeader"]; | ||
| 1195 | |||
| 1196 | if (null != iisHttpHeaderTable) | ||
| 1197 | { | ||
| 1198 | foreach (Row row in iisHttpHeaderTable.Rows) | ||
| 1199 | { | ||
| 1200 | IIs.HttpHeader httpHeader = (IIs.HttpHeader)this.Core.GetIndexedElement(row); | ||
| 1201 | |||
| 1202 | if (1 == (int)row[1]) | ||
| 1203 | { | ||
| 1204 | IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement("IIsWebVirtualDir", (string)row[2]); | ||
| 1205 | if (null != webVirtualDir) | ||
| 1206 | { | ||
| 1207 | webVirtualDir.AddChild(httpHeader); | ||
| 1208 | } | ||
| 1209 | else | ||
| 1210 | { | ||
| 1211 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisHttpHeaderTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[2], "IIsWebVirtualDir")); | ||
| 1212 | } | ||
| 1213 | } | ||
| 1214 | else if (2 == (int)row[1]) | ||
| 1215 | { | ||
| 1216 | IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[2]); | ||
| 1217 | if (null != webSite) | ||
| 1218 | { | ||
| 1219 | webSite.AddChild(httpHeader); | ||
| 1220 | } | ||
| 1221 | else | ||
| 1222 | { | ||
| 1223 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisHttpHeaderTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[2], "IIsWebSite")); | ||
| 1224 | } | ||
| 1225 | } | ||
| 1226 | } | ||
| 1227 | } | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | /// <summary> | ||
| 1231 | /// Finalize the IIsMimeMap table. | ||
| 1232 | /// </summary> | ||
| 1233 | /// <param name="tables">The collection of all tables.</param> | ||
| 1234 | /// <remarks> | ||
| 1235 | /// The IIsMimeMap table supports multiple parent types so no foreign key | ||
| 1236 | /// is declared and thus nesting must be done late. | ||
| 1237 | /// </remarks> | ||
| 1238 | private void FinalizeIIsMimeMapTable(TableIndexedCollection tables) | ||
| 1239 | { | ||
| 1240 | Table iisMimeMapTable = tables["IIsMimeMap"]; | ||
| 1241 | |||
| 1242 | if (null != iisMimeMapTable) | ||
| 1243 | { | ||
| 1244 | foreach (Row row in iisMimeMapTable.Rows) | ||
| 1245 | { | ||
| 1246 | IIs.MimeMap mimeMap = (IIs.MimeMap)this.Core.GetIndexedElement(row); | ||
| 1247 | |||
| 1248 | if (2 < (int)row[1] || 0 >= (int)row[1]) | ||
| 1249 | { | ||
| 1250 | // TODO: warn about unknown parent type | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement("IIsWebVirtualDir", (string)row[2]); | ||
| 1254 | IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[2]); | ||
| 1255 | if (null != webVirtualDir) | ||
| 1256 | { | ||
| 1257 | webVirtualDir.AddChild(mimeMap); | ||
| 1258 | } | ||
| 1259 | else if (null != webSite) | ||
| 1260 | { | ||
| 1261 | webSite.AddChild(mimeMap); | ||
| 1262 | } | ||
| 1263 | else | ||
| 1264 | { | ||
| 1265 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisMimeMapTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[2], "IIsWebVirtualDir")); | ||
| 1266 | } | ||
| 1267 | } | ||
| 1268 | } | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | /// <summary> | ||
| 1272 | /// Finalize the IIsWebApplication table. | ||
| 1273 | /// </summary> | ||
| 1274 | /// <param name="tables">The collection of all tables.</param> | ||
| 1275 | /// <remarks> | ||
| 1276 | /// Since WebApplication elements may nest under a specific WebSite or | ||
| 1277 | /// WebVirtualDir (or just the root element), the nesting must be done late. | ||
| 1278 | /// </remarks> | ||
| 1279 | private void FinalizeIIsWebApplicationTable(TableIndexedCollection tables) | ||
| 1280 | { | ||
| 1281 | Table iisWebApplicationTable = tables["IIsWebApplication"]; | ||
| 1282 | Table iisWebSiteTable = tables["IIsWebSite"]; | ||
| 1283 | Table iisWebVirtualDirTable = tables["IIsWebVirtualDir"]; | ||
| 1284 | |||
| 1285 | Hashtable addedWebApplications = new Hashtable(); | ||
| 1286 | |||
| 1287 | if (null != iisWebSiteTable) | ||
| 1288 | { | ||
| 1289 | foreach (Row row in iisWebSiteTable.Rows) | ||
| 1290 | { | ||
| 1291 | if (null != row[9]) | ||
| 1292 | { | ||
| 1293 | IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement(row); | ||
| 1294 | |||
| 1295 | IIs.WebApplication webApplication = (IIs.WebApplication)this.Core.GetIndexedElement("IIsWebApplication", (string)row[9]); | ||
| 1296 | if (null != webApplication) | ||
| 1297 | { | ||
| 1298 | webSite.AddChild(webApplication); | ||
| 1299 | addedWebApplications[webApplication] = null; | ||
| 1300 | } | ||
| 1301 | else | ||
| 1302 | { | ||
| 1303 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebSiteTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Application_", (string)row[9], "IIsWebApplication")); | ||
| 1304 | } | ||
| 1305 | } | ||
| 1306 | } | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | if (null != iisWebVirtualDirTable) | ||
| 1310 | { | ||
| 1311 | foreach (Row row in iisWebVirtualDirTable.Rows) | ||
| 1312 | { | ||
| 1313 | if (null != row[6]) | ||
| 1314 | { | ||
| 1315 | IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement(row); | ||
| 1316 | |||
| 1317 | IIs.WebApplication webApplication = (IIs.WebApplication)this.Core.GetIndexedElement("IIsWebApplication", (string)row[6]); | ||
| 1318 | if (null != webApplication) | ||
| 1319 | { | ||
| 1320 | webVirtualDir.AddChild(webApplication); | ||
| 1321 | addedWebApplications[webApplication] = null; | ||
| 1322 | } | ||
| 1323 | else | ||
| 1324 | { | ||
| 1325 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebVirtualDirTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Application_", (string)row[6], "IIsWebApplication")); | ||
| 1326 | } | ||
| 1327 | } | ||
| 1328 | } | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | if (null != iisWebApplicationTable) | ||
| 1332 | { | ||
| 1333 | foreach (Row row in iisWebApplicationTable.Rows) | ||
| 1334 | { | ||
| 1335 | IIs.WebApplication webApplication = (IIs.WebApplication)this.Core.GetIndexedElement(row); | ||
| 1336 | |||
| 1337 | if (!addedWebApplications.Contains(webApplication)) | ||
| 1338 | { | ||
| 1339 | this.Core.RootElement.AddChild(webApplication); | ||
| 1340 | } | ||
| 1341 | } | ||
| 1342 | } | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | /// <summary> | ||
| 1346 | /// Finalize the IIsWebError table. | ||
| 1347 | /// </summary> | ||
| 1348 | /// <param name="tables">The collection of all tables.</param> | ||
| 1349 | /// <remarks> | ||
| 1350 | /// Since there is no foreign key relationship declared for this table | ||
| 1351 | /// (because it takes various parent types), it must be nested late. | ||
| 1352 | /// </remarks> | ||
| 1353 | private void FinalizeIIsWebErrorTable(TableIndexedCollection tables) | ||
| 1354 | { | ||
| 1355 | Table iisWebErrorTable = tables["IIsWebError"]; | ||
| 1356 | |||
| 1357 | if (null != iisWebErrorTable) | ||
| 1358 | { | ||
| 1359 | foreach (Row row in iisWebErrorTable.Rows) | ||
| 1360 | { | ||
| 1361 | IIs.WebError webError = (IIs.WebError)this.Core.GetIndexedElement(row); | ||
| 1362 | |||
| 1363 | if (1 == (int)row[2]) // WebVirtualDir parent | ||
| 1364 | { | ||
| 1365 | IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement("IIsWebVirtualDir", (string)row[3]); | ||
| 1366 | |||
| 1367 | if (null != webVirtualDir) | ||
| 1368 | { | ||
| 1369 | webVirtualDir.AddChild(webError); | ||
| 1370 | } | ||
| 1371 | else | ||
| 1372 | { | ||
| 1373 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebErrorTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[3], "IIsWebVirtualDir")); | ||
| 1374 | } | ||
| 1375 | } | ||
| 1376 | else if (2 == (int)row[2]) // WebSite parent | ||
| 1377 | { | ||
| 1378 | IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[3]); | ||
| 1379 | |||
| 1380 | if (null != webSite) | ||
| 1381 | { | ||
| 1382 | webSite.AddChild(webError); | ||
| 1383 | } | ||
| 1384 | else | ||
| 1385 | { | ||
| 1386 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebErrorTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[3], "IIsWebSite")); | ||
| 1387 | } | ||
| 1388 | } | ||
| 1389 | else | ||
| 1390 | { | ||
| 1391 | // TODO: warn unknown parent type | ||
| 1392 | } | ||
| 1393 | } | ||
| 1394 | } | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | /// <summary> | ||
| 1398 | /// Finalize the IIsWebVirtualDir table. | ||
| 1399 | /// </summary> | ||
| 1400 | /// <param name="tables">The collection of all tables.</param> | ||
| 1401 | /// <remarks> | ||
| 1402 | /// WebVirtualDir elements nest under either a WebSite or component | ||
| 1403 | /// depending upon whether the component in the IIsWebVirtualDir row | ||
| 1404 | /// is the same as the one in the parent IIsWebSite row. | ||
| 1405 | /// </remarks> | ||
| 1406 | private void FinalizeIIsWebVirtualDirTable(TableIndexedCollection tables) | ||
| 1407 | { | ||
| 1408 | Table iisWebSiteTable = tables["IIsWebSite"]; | ||
| 1409 | Table iisWebVirtualDirTable = tables["IIsWebVirtualDir"]; | ||
| 1410 | |||
| 1411 | Hashtable iisWebSiteRows = new Hashtable(); | ||
| 1412 | |||
| 1413 | // index the IIsWebSite rows by their primary keys | ||
| 1414 | if (null != iisWebSiteTable) | ||
| 1415 | { | ||
| 1416 | foreach (Row row in iisWebSiteTable.Rows) | ||
| 1417 | { | ||
| 1418 | iisWebSiteRows.Add(row[0], row); | ||
| 1419 | } | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | if (null != iisWebVirtualDirTable) | ||
| 1423 | { | ||
| 1424 | foreach (Row row in iisWebVirtualDirTable.Rows) | ||
| 1425 | { | ||
| 1426 | IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement(row); | ||
| 1427 | Row iisWebSiteRow = (Row)iisWebSiteRows[row[2]]; | ||
| 1428 | |||
| 1429 | if (null != iisWebSiteRow) | ||
| 1430 | { | ||
| 1431 | if ((string)iisWebSiteRow[1] == (string)row[1]) | ||
| 1432 | { | ||
| 1433 | IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement(iisWebSiteRow); | ||
| 1434 | |||
| 1435 | webSite.AddChild(webVirtualDir); | ||
| 1436 | } | ||
| 1437 | else | ||
| 1438 | { | ||
| 1439 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); | ||
| 1440 | |||
| 1441 | if (null != component) | ||
| 1442 | { | ||
| 1443 | webVirtualDir.WebSite = (string)row[2]; | ||
| 1444 | component.AddChild(webVirtualDir); | ||
| 1445 | } | ||
| 1446 | else | ||
| 1447 | { | ||
| 1448 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebVirtualDirTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); | ||
| 1449 | } | ||
| 1450 | } | ||
| 1451 | } | ||
| 1452 | else | ||
| 1453 | { | ||
| 1454 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebVirtualDirTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[2], "IIsWebSite")); | ||
| 1455 | } | ||
| 1456 | } | ||
| 1457 | } | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | /// <summary> | ||
| 1461 | /// Finalize the IIsWebSiteCertificates table. | ||
| 1462 | /// </summary> | ||
| 1463 | /// <param name="tables">The collection of all tables.</param> | ||
| 1464 | /// <remarks> | ||
| 1465 | /// This table creates CertificateRef elements which nest under WebSite | ||
| 1466 | /// elements. | ||
| 1467 | /// </remarks> | ||
| 1468 | private void FinalizeIIsWebSiteCertificatesTable(TableIndexedCollection tables) | ||
| 1469 | { | ||
| 1470 | Table IIsWebSiteCertificatesTable = tables["IIsWebSiteCertificates"]; | ||
| 1471 | |||
| 1472 | if (null != IIsWebSiteCertificatesTable) | ||
| 1473 | { | ||
| 1474 | foreach (Row row in IIsWebSiteCertificatesTable.Rows) | ||
| 1475 | { | ||
| 1476 | IIs.CertificateRef certificateRef = (IIs.CertificateRef)this.Core.GetIndexedElement(row); | ||
| 1477 | IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[0]); | ||
| 1478 | |||
| 1479 | if (null != webSite) | ||
| 1480 | { | ||
| 1481 | webSite.AddChild(certificateRef); | ||
| 1482 | } | ||
| 1483 | else | ||
| 1484 | { | ||
| 1485 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, IIsWebSiteCertificatesTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[0], "IIsWebSite")); | ||
| 1486 | } | ||
| 1487 | } | ||
| 1488 | } | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | /// <summary> | ||
| 1492 | /// Finalize the WebAddress table. | ||
| 1493 | /// </summary> | ||
| 1494 | /// <param name="tables">The collection of all tables.</param> | ||
| 1495 | /// <remarks> | ||
| 1496 | /// There is a circular dependency between the WebAddress and WebSite | ||
| 1497 | /// tables, so nesting must be handled here. | ||
| 1498 | /// </remarks> | ||
| 1499 | private void FinalizeWebAddressTable(TableIndexedCollection tables) | ||
| 1500 | { | ||
| 1501 | Table iisWebAddressTable = tables["IIsWebAddress"]; | ||
| 1502 | Table iisWebSiteTable = tables["IIsWebSite"]; | ||
| 1503 | |||
| 1504 | Hashtable addedWebAddresses = new Hashtable(); | ||
| 1505 | |||
| 1506 | if (null != iisWebSiteTable) | ||
| 1507 | { | ||
| 1508 | foreach (Row row in iisWebSiteTable.Rows) | ||
| 1509 | { | ||
| 1510 | IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement(row); | ||
| 1511 | |||
| 1512 | IIs.WebAddress webAddress = (IIs.WebAddress)this.Core.GetIndexedElement("IIsWebAddress", (string)row[7]); | ||
| 1513 | if (null != webAddress) | ||
| 1514 | { | ||
| 1515 | webSite.AddChild(webAddress); | ||
| 1516 | addedWebAddresses[webAddress] = null; | ||
| 1517 | } | ||
| 1518 | else | ||
| 1519 | { | ||
| 1520 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebSiteTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyAddress_", (string)row[7], "IIsWebAddress")); | ||
| 1521 | } | ||
| 1522 | } | ||
| 1523 | } | ||
| 1524 | |||
| 1525 | if (null != iisWebAddressTable) | ||
| 1526 | { | ||
| 1527 | foreach (Row row in iisWebAddressTable.Rows) | ||
| 1528 | { | ||
| 1529 | IIs.WebAddress webAddress = (IIs.WebAddress)this.Core.GetIndexedElement(row); | ||
| 1530 | |||
| 1531 | if (!addedWebAddresses.Contains(webAddress)) | ||
| 1532 | { | ||
| 1533 | IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[1]); | ||
| 1534 | |||
| 1535 | if (null != webSite) | ||
| 1536 | { | ||
| 1537 | webSite.AddChild(webAddress); | ||
| 1538 | } | ||
| 1539 | else | ||
| 1540 | { | ||
| 1541 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebAddressTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[1], "IIsWebSite")); | ||
| 1542 | } | ||
| 1543 | } | ||
| 1544 | } | ||
| 1545 | } | ||
| 1546 | } | ||
| 1547 | } | ||
| 1548 | #endif | ||
| 1549 | } | ||
diff --git a/src/ext/Iis/wixext/IIsExtensionData.cs b/src/ext/Iis/wixext/IIsExtensionData.cs new file mode 100644 index 00000000..6a0e1f09 --- /dev/null +++ b/src/ext/Iis/wixext/IIsExtensionData.cs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Extensibility; | ||
| 7 | |||
| 8 | /// <summary> | ||
| 9 | /// The WiX Toolset Internet Information Services Extension. | ||
| 10 | /// </summary> | ||
| 11 | public sealed class IIsExtensionData : BaseExtensionData | ||
| 12 | { | ||
| 13 | /// <summary> | ||
| 14 | /// Gets the default culture. | ||
| 15 | /// </summary> | ||
| 16 | /// <value>The default culture.</value> | ||
| 17 | public override string DefaultCulture => "en-US"; | ||
| 18 | |||
| 19 | public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) | ||
| 20 | { | ||
| 21 | symbolDefinition = IisSymbolDefinitions.ByName(name); | ||
| 22 | return symbolDefinition != null; | ||
| 23 | } | ||
| 24 | |||
| 25 | public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions) | ||
| 26 | { | ||
| 27 | return Intermediate.Load(typeof(IIsExtensionData).Assembly, "WixToolset.Iis.iis.wixlib", symbolDefinitions); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | } | ||
diff --git a/src/ext/Iis/wixext/IisErrors.cs b/src/ext/Iis/wixext/IisErrors.cs new file mode 100644 index 00000000..2f226217 --- /dev/null +++ b/src/ext/Iis/wixext/IisErrors.cs | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Data | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Resources; | ||
| 7 | |||
| 8 | public static class IIsErrors | ||
| 9 | { | ||
| 10 | public static Message DeprecatedBinaryChildElement(SourceLineNumber sourceLineNumbers, string elementName) | ||
| 11 | { | ||
| 12 | return Message(sourceLineNumbers, Ids.DeprecatedBinaryChildElement, "The {0} element contains a deprecated child Binary element. Please move the Binary element under a Fragment, Module, or Product element and set the {0}/@BinaryKey attribute to the value of the Binary/@Id attribute.", elementName); | ||
| 13 | } | ||
| 14 | |||
| 15 | public static Message IllegalAttributeWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName) | ||
| 16 | { | ||
| 17 | return Message(sourceLineNumbers, Ids.IllegalAttributeWithoutComponent, "The {0}/@{1} attribute cannot be specified unless the element has a Component as an ancestor. A {0} that does not have a Component ancestor is not installed.", elementName, attributeName); | ||
| 18 | } | ||
| 19 | |||
| 20 | public static Message IllegalCharacterInAttributeValue(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string value, Char illegalCharacter) | ||
| 21 | { | ||
| 22 | return Message(sourceLineNumbers, Ids.IllegalCharacterInAttributeValue, "The {0}/@{1} attribute's value, '{2}', is invalid. It cannot contain the character '{3}'.", elementName, attributeName, value, illegalCharacter); | ||
| 23 | } | ||
| 24 | |||
| 25 | public static Message IllegalElementWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName) | ||
| 26 | { | ||
| 27 | return Message(sourceLineNumbers, Ids.IllegalElementWithoutComponent, "The {0} element cannot be specified unless the element has a Component as an ancestor. A {0} that does not have a Component ancestor is not installed.", elementName); | ||
| 28 | } | ||
| 29 | |||
| 30 | public static Message MimeMapExtensionMissingPeriod(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string attributeValue) | ||
| 31 | { | ||
| 32 | return Message(sourceLineNumbers, Ids.MimeMapExtensionMissingPeriod, "The {0}/@{1} attribute's value, '{2}', is not a valid mime map extension. It must begin with a period.", elementName, attributeName, attributeValue); | ||
| 33 | } | ||
| 34 | |||
| 35 | public static Message OneOfAttributesRequiredUnderComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName1, string attributeName2, string attributeName3, string attributeName4) | ||
| 36 | { | ||
| 37 | return Message(sourceLineNumbers, Ids.OneOfAttributesRequiredUnderComponent, "When nested under a Component, the {0} element must have one of the following attributes specified: {1}, {2}, {3} or {4}.", elementName, attributeName1, attributeName2, attributeName3, attributeName4); | ||
| 38 | } | ||
| 39 | |||
| 40 | public static Message RequiredAttributeUnderComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName) | ||
| 41 | { | ||
| 42 | return Message(sourceLineNumbers, Ids.RequiredAttributeUnderComponent, "The {0}/@{1} attribute must be specified when the element has a Component as an ancestor.", elementName, attributeName); | ||
| 43 | } | ||
| 44 | |||
| 45 | public static Message WebApplicationAlreadySpecified(SourceLineNumber sourceLineNumbers, string elementName) | ||
| 46 | { | ||
| 47 | return Message(sourceLineNumbers, Ids.WebApplicationAlreadySpecified, "The {0} element can have at most a single WebApplication specified. This can be either through the WebApplication attribute, or through a nested WebApplication element, but not both.", elementName); | ||
| 48 | } | ||
| 49 | |||
| 50 | public static Message WebSiteAttributeUnderWebSite(SourceLineNumber sourceLineNumbers, string elementName) | ||
| 51 | { | ||
| 52 | return Message(sourceLineNumbers, Ids.WebSiteAttributeUnderWebSite, "The {0}/@WebSite attribute cannot be specified when the {0} element is nested under a WebSite element.", elementName); | ||
| 53 | } | ||
| 54 | |||
| 55 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) | ||
| 56 | { | ||
| 57 | return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); | ||
| 58 | } | ||
| 59 | |||
| 60 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args) | ||
| 61 | { | ||
| 62 | return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args); | ||
| 63 | } | ||
| 64 | |||
| 65 | public enum Ids | ||
| 66 | { | ||
| 67 | MimeMapExtensionMissingPeriod = 5150, | ||
| 68 | IllegalAttributeWithoutComponent = 5151, | ||
| 69 | IllegalElementWithoutComponent = 5152, | ||
| 70 | OneOfAttributesRequiredUnderComponent = 5153, | ||
| 71 | WebSiteAttributeUnderWebSite = 5154, | ||
| 72 | WebApplicationAlreadySpecified = 5155, | ||
| 73 | IllegalCharacterInAttributeValue = 5156, | ||
| 74 | DeprecatedBinaryChildElement = 5157, | ||
| 75 | RequiredAttributeUnderComponent = 5161, | ||
| 76 | } | ||
| 77 | } | ||
| 78 | } | ||
diff --git a/src/ext/Iis/wixext/IisExtensionFactory.cs b/src/ext/Iis/wixext/IisExtensionFactory.cs new file mode 100644 index 00000000..2fb7e682 --- /dev/null +++ b/src/ext/Iis/wixext/IisExtensionFactory.cs | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using WixToolset.Extensibility; | ||
| 8 | |||
| 9 | public class IisExtensionFactory : BaseExtensionFactory | ||
| 10 | { | ||
| 11 | protected override IReadOnlyCollection<Type> ExtensionTypes => new[] | ||
| 12 | { | ||
| 13 | typeof(IIsCompiler), | ||
| 14 | typeof(IIsExtensionData), | ||
| 15 | typeof(IisWindowsInstallerBackendBinderExtension), | ||
| 16 | }; | ||
| 17 | } | ||
| 18 | } | ||
diff --git a/src/ext/Iis/wixext/IisTableDefinitions.cs b/src/ext/Iis/wixext/IisTableDefinitions.cs new file mode 100644 index 00000000..f513152e --- /dev/null +++ b/src/ext/Iis/wixext/IisTableDefinitions.cs | |||
| @@ -0,0 +1,324 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data.WindowsInstaller; | ||
| 6 | |||
| 7 | public static class IisTableDefinitions | ||
| 8 | { | ||
| 9 | public static readonly TableDefinition Certificate = new TableDefinition( | ||
| 10 | "Certificate", | ||
| 11 | IisSymbolDefinitions.Certificate, | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new ColumnDefinition("Certificate", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyColumn: 1, description: "Identifier for the certificate in the package.", modularizeType: ColumnModularizeType.Column), | ||
| 15 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), | ||
| 16 | new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name to be used for the Certificate."), | ||
| 17 | new ColumnDefinition("StoreLocation", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 2, description: "Location of the target certificate store (CurrentUser == 1, LocalMachine == 2)"), | ||
| 18 | new ColumnDefinition("StoreName", ColumnType.String, 64, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of the target certificate store"), | ||
| 19 | new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "Attributes of the certificate"), | ||
| 20 | new ColumnDefinition("Binary_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Binary", keyColumn: 1, description: "Identifier to Binary table containing certificate.", modularizeType: ColumnModularizeType.Column), | ||
| 21 | new ColumnDefinition("CertificatePath", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Property to path of certificate.", modularizeType: ColumnModularizeType.Property), | ||
| 22 | new ColumnDefinition("PFXPassword", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Hidden property to a pfx password", modularizeType: ColumnModularizeType.Property), | ||
| 23 | }, | ||
| 24 | symbolIdIsPrimaryKey: true | ||
| 25 | ); | ||
| 26 | |||
| 27 | public static readonly TableDefinition CertificateHash = new TableDefinition( | ||
| 28 | "CertificateHash", | ||
| 29 | IisSymbolDefinitions.CertificateHash, | ||
| 30 | new[] | ||
| 31 | { | ||
| 32 | new ColumnDefinition("Certificate_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyColumn: 1, description: "Foreign key to certificate in Certificate table.", modularizeType: ColumnModularizeType.Column), | ||
| 33 | new ColumnDefinition("Hash", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Base64 encoded SHA1 hash of certificate populated at run-time."), | ||
| 34 | }, | ||
| 35 | symbolIdIsPrimaryKey: false | ||
| 36 | ); | ||
| 37 | |||
| 38 | public static readonly TableDefinition IIsWebSiteCertificates = new TableDefinition( | ||
| 39 | "IIsWebSiteCertificates", | ||
| 40 | IisSymbolDefinitions.IIsWebSiteCertificates, | ||
| 41 | new[] | ||
| 42 | { | ||
| 43 | new ColumnDefinition("Web_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "IIsWebSite", keyColumn: 1, description: "The index into the IIsWebSite table.", modularizeType: ColumnModularizeType.Column), | ||
| 44 | new ColumnDefinition("Certificate_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Text, keyTable: "Certificate", keyColumn: 1, description: "The index into the Certificate table.", modularizeType: ColumnModularizeType.Column), | ||
| 45 | }, | ||
| 46 | symbolIdIsPrimaryKey: false | ||
| 47 | ); | ||
| 48 | |||
| 49 | public static readonly TableDefinition IIsAppPool = new TableDefinition( | ||
| 50 | "IIsAppPool", | ||
| 51 | IisSymbolDefinitions.IIsAppPool, | ||
| 52 | new[] | ||
| 53 | { | ||
| 54 | new ColumnDefinition("AppPool", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for apppool", modularizeType: ColumnModularizeType.Column), | ||
| 55 | new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name to be used for the IIs AppPool.", modularizeType: ColumnModularizeType.Property), | ||
| 56 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key referencing Component that controls the app pool", modularizeType: ColumnModularizeType.Column), | ||
| 57 | new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Attributes of the AppPool"), | ||
| 58 | new ColumnDefinition("User_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "User", keyColumn: 1, description: "User account to run the app pool as", modularizeType: ColumnModularizeType.Column), | ||
| 59 | new ColumnDefinition("RecycleMinutes", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Number of minutes between recycling app pool"), | ||
| 60 | new ColumnDefinition("RecycleRequests", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Number of requests between recycling app pool"), | ||
| 61 | new ColumnDefinition("RecycleTimes", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Times to recycle app pool (comma delimited - i.e. 1:45,13:30)"), | ||
| 62 | new ColumnDefinition("IdleTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Amount of idle time before shutting down"), | ||
| 63 | new ColumnDefinition("QueueLimit", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Reject requests after queue gets how large"), | ||
| 64 | new ColumnDefinition("CPUMon", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "CPUMon is a comma delimeted list of the following format: <percent CPU usage>,<refress minutes>,<Action>. The values for Action are 1 (Shutdown) and 0 (No Action)."), | ||
| 65 | new ColumnDefinition("MaxProc", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Maximum number of processes to use"), | ||
| 66 | new ColumnDefinition("VirtualMemory", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Amount of virtual memory (in KB) that a worker process can use before the worker process recycles. The maximum value supported for this field is 4,294,967 KB."), | ||
| 67 | new ColumnDefinition("PrivateMemory", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Amount of private memory (in KB) that a worker process can use before the worker process recycles. The maximum value supported for this field is 4,294,967 KB."), | ||
| 68 | new ColumnDefinition("ManagedRuntimeVersion", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Specifies the .NET Framework version to be used by the application pool."), | ||
| 69 | new ColumnDefinition("ManagedPipelineMode", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Specifies the request-processing mode that is used to process requests for managed content."), | ||
| 70 | }, | ||
| 71 | symbolIdIsPrimaryKey: true | ||
| 72 | ); | ||
| 73 | |||
| 74 | public static readonly TableDefinition IIsMimeMap = new TableDefinition( | ||
| 75 | "IIsMimeMap", | ||
| 76 | IisSymbolDefinitions.IIsMimeMap, | ||
| 77 | new[] | ||
| 78 | { | ||
| 79 | new ColumnDefinition("MimeMap", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for Mime Map definitions", modularizeType: ColumnModularizeType.Column), | ||
| 80 | new ColumnDefinition("ParentType", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, possibilities: "1;2", description: "Type of parent: 1=vdir 2=website"), | ||
| 81 | new ColumnDefinition("ParentValue", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Name of the parent value.", modularizeType: ColumnModularizeType.Column), | ||
| 82 | new ColumnDefinition("MimeType", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Mime-type covered by the MimeMap."), | ||
| 83 | new ColumnDefinition("Extension", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Extension covered by the MimeMap."), | ||
| 84 | }, | ||
| 85 | symbolIdIsPrimaryKey: true | ||
| 86 | ); | ||
| 87 | |||
| 88 | public static readonly TableDefinition IIsProperty = new TableDefinition( | ||
| 89 | "IIsProperty", | ||
| 90 | IisSymbolDefinitions.IIsProperty, | ||
| 91 | new[] | ||
| 92 | { | ||
| 93 | new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Unique name of the IIsProperty"), | ||
| 94 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component that the property is linked to", modularizeType: ColumnModularizeType.Column), | ||
| 95 | new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Attributes of the IIsProperty (unused)"), | ||
| 96 | new ColumnDefinition("Value", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Value of the IIsProperty"), | ||
| 97 | }, | ||
| 98 | symbolIdIsPrimaryKey: true | ||
| 99 | ); | ||
| 100 | |||
| 101 | public static readonly TableDefinition IIsWebDirProperties = new TableDefinition( | ||
| 102 | "IIsWebDirProperties", | ||
| 103 | IisSymbolDefinitions.IIsWebDirProperties, | ||
| 104 | new[] | ||
| 105 | { | ||
| 106 | new ColumnDefinition("DirProperties", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for Web Properties", modularizeType: ColumnModularizeType.Column), | ||
| 107 | new ColumnDefinition("Access", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Access rights to the web server"), | ||
| 108 | new ColumnDefinition("Authorization", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Authorization policy to web server (anonymous access, NTLM, etc)"), | ||
| 109 | new ColumnDefinition("AnonymousUser_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "User", keyColumn: 1, description: "Foreign key, User used to log into database", modularizeType: ColumnModularizeType.Column), | ||
| 110 | new ColumnDefinition("IIsControlledPassword", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether IIs is allowed to set the AnonymousUser_ password"), | ||
| 111 | new ColumnDefinition("LogVisits", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether IIs tracks all access to the directory"), | ||
| 112 | new ColumnDefinition("Index", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether IIs searches the directory"), | ||
| 113 | new ColumnDefinition("DefaultDoc", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Comma delimited list of file names to act as a default document"), | ||
| 114 | new ColumnDefinition("AspDetailedError", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether detailed ASP errors are sent to browser"), | ||
| 115 | new ColumnDefinition("HttpExpires", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Value to set the HttpExpires attribute to for a Web Dir in the metabase"), | ||
| 116 | new ColumnDefinition("CacheControlMaxAge", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Integer value specifying the cache control maximum age value."), | ||
| 117 | new ColumnDefinition("CacheControlCustom", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Custom HTTP 1.1 cache control directives."), | ||
| 118 | new ColumnDefinition("NoCustomError", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether IIs will return custom errors for this directory."), | ||
| 119 | new ColumnDefinition("AccessSSLFlags", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Specifies AccessSSLFlags IIS metabase property."), | ||
| 120 | new ColumnDefinition("AuthenticationProviders", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Comma delimited list, in order of precedence, of Windows authentication providers that IIS will attempt to use: NTLM, Kerberos, Negotiate, and others."), | ||
| 121 | }, | ||
| 122 | symbolIdIsPrimaryKey: true | ||
| 123 | ); | ||
| 124 | |||
| 125 | public static readonly TableDefinition IIsWebAddress = new TableDefinition( | ||
| 126 | "IIsWebAddress", | ||
| 127 | IisSymbolDefinitions.IIsWebAddress, | ||
| 128 | new[] | ||
| 129 | { | ||
| 130 | new ColumnDefinition("Address", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 131 | new ColumnDefinition("Web_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "IIsWebSite", keyColumn: 1, description: "Foreign key referencing Web that uses the address.", modularizeType: ColumnModularizeType.Column), | ||
| 132 | new ColumnDefinition("IP", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "String representing IP address (#.#.#.#) or NT machine name (fooserver)", modularizeType: ColumnModularizeType.Property), | ||
| 133 | new ColumnDefinition("Port", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Port web site listens on", modularizeType: ColumnModularizeType.Property), | ||
| 134 | new ColumnDefinition("Header", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Special header information for the web site"), | ||
| 135 | new ColumnDefinition("Secure", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether SSL is used to communicate with web site"), | ||
| 136 | }, | ||
| 137 | symbolIdIsPrimaryKey: true | ||
| 138 | ); | ||
| 139 | |||
| 140 | public static readonly TableDefinition IIsWebSite = new TableDefinition( | ||
| 141 | "IIsWebSite", | ||
| 142 | IisSymbolDefinitions.IIsWebSite, | ||
| 143 | new[] | ||
| 144 | { | ||
| 145 | new ColumnDefinition("Web", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 146 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key referencing Component that controls the web site", modularizeType: ColumnModularizeType.Column), | ||
| 147 | new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in IIS MMC applet"), | ||
| 148 | new ColumnDefinition("ConnectionTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Time connection is maintained without activity (in seconds)"), | ||
| 149 | new ColumnDefinition("Directory_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Directory", keyColumn: 1, description: "Foreign key referencing directory that the web site points at", modularizeType: ColumnModularizeType.Column), | ||
| 150 | new ColumnDefinition("State", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1;2", description: "Sets intial state of web site"), | ||
| 151 | new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "2", description: "Control the install behavior of web site"), | ||
| 152 | new ColumnDefinition("KeyAddress_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "IIsWebAddress", keyColumn: 1, description: "Foreign key referencing primary address for the web site", modularizeType: ColumnModularizeType.Column), | ||
| 153 | new ColumnDefinition("DirProperties_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "IIsWebDirProperties", keyColumn: 1, description: "Foreign key referencing possible security information for the web site", modularizeType: ColumnModularizeType.Column), | ||
| 154 | new ColumnDefinition("Application_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "IIsWebApplication", keyColumn: 1, description: "Foreign key referencing possible ASP application for the web site.", modularizeType: ColumnModularizeType.Column), | ||
| 155 | new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Allows ordering of web site install"), | ||
| 156 | new ColumnDefinition("Log_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Unknown, keyTable: "IIsWebLog", keyColumn: 1, description: "Foreign key reference to IIsWebLog data", modularizeType: ColumnModularizeType.Column), | ||
| 157 | new ColumnDefinition("Id", ColumnType.String, 74, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Optional number or formatted value that resolves to number that acts as the WebSite Id."), | ||
| 158 | }, | ||
| 159 | symbolIdIsPrimaryKey: true | ||
| 160 | ); | ||
| 161 | |||
| 162 | public static readonly TableDefinition IIsWebApplication = new TableDefinition( | ||
| 163 | "IIsWebApplication", | ||
| 164 | IisSymbolDefinitions.IIsWebApplication, | ||
| 165 | new[] | ||
| 166 | { | ||
| 167 | new ColumnDefinition("Application", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for ASP Application", modularizeType: ColumnModularizeType.Column), | ||
| 168 | new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of application in IIS MMC applet", modularizeType: ColumnModularizeType.Property), | ||
| 169 | new ColumnDefinition("Isolation", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, possibilities: "0;1;2", description: "Isolation level for ASP Application: 0 == Low, 2 == Medium, 1 == High"), | ||
| 170 | new ColumnDefinition("AllowSessions", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether application may maintain session state"), | ||
| 171 | new ColumnDefinition("SessionTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Time session state is maintained without user interaction"), | ||
| 172 | new ColumnDefinition("Buffer", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether application buffers its output"), | ||
| 173 | new ColumnDefinition("ParentPaths", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "What is this for anyway?"), | ||
| 174 | new ColumnDefinition("DefaultScript", ColumnType.String, 26, primaryKey: false, nullable: true, ColumnCategory.Text, possibilities: "VBScript;JScript", description: "Default scripting language for ASP applications"), | ||
| 175 | new ColumnDefinition("ScriptTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Time ASP application page is permitted to process"), | ||
| 176 | new ColumnDefinition("ServerDebugging", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether to allow ASP server-side script debugging"), | ||
| 177 | new ColumnDefinition("ClientDebugging", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether to allow ASP client-side script debugging"), | ||
| 178 | new ColumnDefinition("AppPool_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "IIsAppPool", keyColumn: 1, description: "App Pool this application should run under", modularizeType: ColumnModularizeType.Column), | ||
| 179 | }, | ||
| 180 | symbolIdIsPrimaryKey: true | ||
| 181 | ); | ||
| 182 | |||
| 183 | public static readonly TableDefinition IIsWebApplicationExtension = new TableDefinition( | ||
| 184 | "IIsWebApplicationExtension", | ||
| 185 | IisSymbolDefinitions.IIsWebApplicationExtension, | ||
| 186 | new[] | ||
| 187 | { | ||
| 188 | new ColumnDefinition("Application_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "IIsWebApplication", keyColumn: 1, description: "Foreign key referencing possible ASP application for the web site", modularizeType: ColumnModularizeType.Column), | ||
| 189 | new ColumnDefinition("Extension", ColumnType.String, 255, primaryKey: true, nullable: true, ColumnCategory.Text, description: "Primary key, Extension that should be registered for this ASP application"), | ||
| 190 | new ColumnDefinition("Verbs", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Comma delimited list of HTTP verbs the extension should be registered with"), | ||
| 191 | new ColumnDefinition("Executable", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Path to extension (usually file property: [#file])", modularizeType: ColumnModularizeType.Property), | ||
| 192 | new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "1;4;5", description: "Attributes for extension: 1 == Script, 4 == Check Path Info"), | ||
| 193 | }, | ||
| 194 | symbolIdIsPrimaryKey: false | ||
| 195 | ); | ||
| 196 | |||
| 197 | public static readonly TableDefinition IIsFilter = new TableDefinition( | ||
| 198 | "IIsFilter", | ||
| 199 | IisSymbolDefinitions.IIsFilter, | ||
| 200 | new[] | ||
| 201 | { | ||
| 202 | new ColumnDefinition("Filter", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 203 | new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Name of the ISAPI Filter in IIS"), | ||
| 204 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key referencing Component that controls the filter", modularizeType: ColumnModularizeType.Column), | ||
| 205 | new ColumnDefinition("Path", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Path to filter (usually file property: [#file])", modularizeType: ColumnModularizeType.Property), | ||
| 206 | new ColumnDefinition("Web_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "IIsWebSite", keyColumn: 1, description: "Foreign key referencing web site that loads the filter (NULL == global filter", modularizeType: ColumnModularizeType.Column), | ||
| 207 | new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in IIS MMC applet"), | ||
| 208 | new ColumnDefinition("Flags", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "What do all these numbers mean?"), | ||
| 209 | new ColumnDefinition("LoadOrder", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "-1 == last in order, 0 == first in order, # == place in order"), | ||
| 210 | }, | ||
| 211 | symbolIdIsPrimaryKey: true | ||
| 212 | ); | ||
| 213 | |||
| 214 | public static readonly TableDefinition IIsWebDir = new TableDefinition( | ||
| 215 | "IIsWebDir", | ||
| 216 | IisSymbolDefinitions.IIsWebDir, | ||
| 217 | new[] | ||
| 218 | { | ||
| 219 | new ColumnDefinition("WebDir", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 220 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key referencing Component that controls the virtual directory", modularizeType: ColumnModularizeType.Column), | ||
| 221 | new ColumnDefinition("Web_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "IIsWebSite", keyColumn: 1, description: "Foreign key referencing web site that controls the virtual directory", modularizeType: ColumnModularizeType.Column), | ||
| 222 | new ColumnDefinition("Path", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of web directory displayed in IIS MMC applet", modularizeType: ColumnModularizeType.Property), | ||
| 223 | new ColumnDefinition("DirProperties_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "IIsWebDirProperties", keyColumn: 1, description: "Foreign key referencing possible security information for the virtual directory", modularizeType: ColumnModularizeType.Column), | ||
| 224 | new ColumnDefinition("Application_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "IIsWebApplication", keyColumn: 1, description: "Foreign key referencing possible ASP application for the virtual directory. This column is currently unused, but maintained for compatibility reasons.", modularizeType: ColumnModularizeType.Column), | ||
| 225 | }, | ||
| 226 | symbolIdIsPrimaryKey: true | ||
| 227 | ); | ||
| 228 | |||
| 229 | public static readonly TableDefinition IIsWebError = new TableDefinition( | ||
| 230 | "IIsWebError", | ||
| 231 | IisSymbolDefinitions.IIsWebError, | ||
| 232 | new[] | ||
| 233 | { | ||
| 234 | new ColumnDefinition("ErrorCode", ColumnType.Number, 2, primaryKey: true, nullable: false, ColumnCategory.Unknown, minValue: 400, maxValue: 599, description: "HTTP status code indicating error."), | ||
| 235 | new ColumnDefinition("SubCode", ColumnType.Number, 4, primaryKey: true, nullable: false, ColumnCategory.Unknown, description: "HTTP sub-status code indicating error."), | ||
| 236 | new ColumnDefinition("ParentType", ColumnType.Number, 2, primaryKey: true, nullable: false, ColumnCategory.Unknown, possibilities: "1;2", description: "Type of parent: 1=vdir, 2=web"), | ||
| 237 | new ColumnDefinition("ParentValue", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Name of the parent value.", modularizeType: ColumnModularizeType.Column), | ||
| 238 | new ColumnDefinition("File", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Path to file for this custom error (usually file property: [#file]). Must be null if URL is not null."), | ||
| 239 | new ColumnDefinition("URL", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "URL for this custom error. Must be null if File is not null."), | ||
| 240 | }, | ||
| 241 | symbolIdIsPrimaryKey: false | ||
| 242 | ); | ||
| 243 | |||
| 244 | public static readonly TableDefinition IIsHttpHeader = new TableDefinition( | ||
| 245 | "IIsHttpHeader", | ||
| 246 | IisSymbolDefinitions.IIsHttpHeader, | ||
| 247 | new[] | ||
| 248 | { | ||
| 249 | new ColumnDefinition("HttpHeader", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 250 | new ColumnDefinition("ParentType", ColumnType.Number, 2, primaryKey: true, nullable: false, ColumnCategory.Unknown, possibilities: "1;2", description: "Type of parent: 1=vdir, 2=web"), | ||
| 251 | new ColumnDefinition("ParentValue", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Name of the parent value.", modularizeType: ColumnModularizeType.Column), | ||
| 252 | new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Name of the HTTP Header"), | ||
| 253 | new ColumnDefinition("Value", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "URL for this custom error. Must be null if File is not null."), | ||
| 254 | new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 0, description: "Attributes for HTTP Header: none"), | ||
| 255 | new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to add the HTTP Headers."), | ||
| 256 | }, | ||
| 257 | symbolIdIsPrimaryKey: false | ||
| 258 | ); | ||
| 259 | |||
| 260 | public static readonly TableDefinition IIsWebServiceExtension = new TableDefinition( | ||
| 261 | "IIsWebServiceExtension", | ||
| 262 | IisSymbolDefinitions.IIsWebServiceExtension, | ||
| 263 | new[] | ||
| 264 | { | ||
| 265 | new ColumnDefinition("WebServiceExtension", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 266 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key referencing Component that controls the WebServiceExtension handler", modularizeType: ColumnModularizeType.Column), | ||
| 267 | new ColumnDefinition("File", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Path to handler (usually file property: [#file])", modularizeType: ColumnModularizeType.Property), | ||
| 268 | new ColumnDefinition("Description", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in WebServiceExtension Wizard", modularizeType: ColumnModularizeType.Property), | ||
| 269 | new ColumnDefinition("Group", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "String used to identify groups of extensions.", modularizeType: ColumnModularizeType.Property), | ||
| 270 | new ColumnDefinition("Attributes", ColumnType.Number, 1, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 3, description: "Attributes for WebServiceExtension: 1 = Allow, 2 = UIDeletable"), | ||
| 271 | }, | ||
| 272 | symbolIdIsPrimaryKey: true | ||
| 273 | ); | ||
| 274 | |||
| 275 | public static readonly TableDefinition IIsWebVirtualDir = new TableDefinition( | ||
| 276 | "IIsWebVirtualDir", | ||
| 277 | IisSymbolDefinitions.IIsWebVirtualDir, | ||
| 278 | new[] | ||
| 279 | { | ||
| 280 | new ColumnDefinition("VirtualDir", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 281 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key referencing Component that controls the virtual directory", modularizeType: ColumnModularizeType.Column), | ||
| 282 | new ColumnDefinition("Web_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "IIsWebSite", keyColumn: 1, description: "Foreign key referencing web site that controls the virtual directory", modularizeType: ColumnModularizeType.Column), | ||
| 283 | new ColumnDefinition("Alias", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of virtual directory displayed in IIS MMC applet", modularizeType: ColumnModularizeType.Property), | ||
| 284 | new ColumnDefinition("Directory_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Directory", keyColumn: 1, description: "Foreign key referencing directory that the virtual directory points at", modularizeType: ColumnModularizeType.Column), | ||
| 285 | new ColumnDefinition("DirProperties_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "IIsWebDirProperties", keyColumn: 1, description: "Foreign key referencing possible security information for the virtual directory", modularizeType: ColumnModularizeType.Column), | ||
| 286 | new ColumnDefinition("Application_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "IIsWebApplication", keyColumn: 1, description: "Foreign key referencing possible ASP application for the virtual directory", modularizeType: ColumnModularizeType.Column), | ||
| 287 | }, | ||
| 288 | symbolIdIsPrimaryKey: true | ||
| 289 | ); | ||
| 290 | |||
| 291 | public static readonly TableDefinition IIsWebLog = new TableDefinition( | ||
| 292 | "IIsWebLog", | ||
| 293 | IisSymbolDefinitions.IIsWebLog, | ||
| 294 | new[] | ||
| 295 | { | ||
| 296 | new ColumnDefinition("Log", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 297 | new ColumnDefinition("Format", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Type of log format"), | ||
| 298 | }, | ||
| 299 | symbolIdIsPrimaryKey: true | ||
| 300 | ); | ||
| 301 | |||
| 302 | public static readonly TableDefinition[] All = new[] | ||
| 303 | { | ||
| 304 | Certificate, | ||
| 305 | CertificateHash, | ||
| 306 | IIsWebSiteCertificates, | ||
| 307 | IIsAppPool, | ||
| 308 | IIsMimeMap, | ||
| 309 | IIsProperty, | ||
| 310 | IIsWebDirProperties, | ||
| 311 | IIsWebAddress, | ||
| 312 | IIsWebSite, | ||
| 313 | IIsWebApplication, | ||
| 314 | IIsWebApplicationExtension, | ||
| 315 | IIsFilter, | ||
| 316 | IIsWebDir, | ||
| 317 | IIsWebError, | ||
| 318 | IIsHttpHeader, | ||
| 319 | IIsWebServiceExtension, | ||
| 320 | IIsWebVirtualDir, | ||
| 321 | IIsWebLog, | ||
| 322 | }; | ||
| 323 | } | ||
| 324 | } | ||
diff --git a/src/ext/Iis/wixext/IisWindowsInstallerBackendBinderExtension.cs b/src/ext/Iis/wixext/IisWindowsInstallerBackendBinderExtension.cs new file mode 100644 index 00000000..a61cbad6 --- /dev/null +++ b/src/ext/Iis/wixext/IisWindowsInstallerBackendBinderExtension.cs | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using System.Collections.Generic; | ||
| 6 | using WixToolset.Data.WindowsInstaller; | ||
| 7 | using WixToolset.Extensibility; | ||
| 8 | |||
| 9 | public class IisWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension | ||
| 10 | { | ||
| 11 | public override IReadOnlyCollection<TableDefinition> TableDefinitions => IisTableDefinitions.All; | ||
| 12 | } | ||
| 13 | } | ||
diff --git a/src/ext/Iis/wixext/Symbols/CertificateHashSymbol.cs b/src/ext/Iis/wixext/Symbols/CertificateHashSymbol.cs new file mode 100644 index 00000000..866d474c --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/CertificateHashSymbol.cs | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition CertificateHash = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.CertificateHash.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(CertificateHashSymbolFields.CertificateRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(CertificateHashSymbolFields.Hash), IntermediateFieldType.String), | ||
| 16 | }, | ||
| 17 | typeof(CertificateHashSymbol)); | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace WixToolset.Iis.Symbols | ||
| 22 | { | ||
| 23 | using WixToolset.Data; | ||
| 24 | |||
| 25 | public enum CertificateHashSymbolFields | ||
| 26 | { | ||
| 27 | CertificateRef, | ||
| 28 | Hash, | ||
| 29 | } | ||
| 30 | |||
| 31 | public class CertificateHashSymbol : IntermediateSymbol | ||
| 32 | { | ||
| 33 | public CertificateHashSymbol() : base(IisSymbolDefinitions.CertificateHash, null, null) | ||
| 34 | { | ||
| 35 | } | ||
| 36 | |||
| 37 | public CertificateHashSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.CertificateHash, sourceLineNumber, id) | ||
| 38 | { | ||
| 39 | } | ||
| 40 | |||
| 41 | public IntermediateField this[CertificateHashSymbolFields index] => this.Fields[(int)index]; | ||
| 42 | |||
| 43 | public string CertificateRef | ||
| 44 | { | ||
| 45 | get => this.Fields[(int)CertificateHashSymbolFields.CertificateRef].AsString(); | ||
| 46 | set => this.Set((int)CertificateHashSymbolFields.CertificateRef, value); | ||
| 47 | } | ||
| 48 | |||
| 49 | public string Hash | ||
| 50 | { | ||
| 51 | get => this.Fields[(int)CertificateHashSymbolFields.Hash].AsString(); | ||
| 52 | set => this.Set((int)CertificateHashSymbolFields.Hash, value); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/CertificateSymbol.cs b/src/ext/Iis/wixext/Symbols/CertificateSymbol.cs new file mode 100644 index 00000000..b80b6ba4 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/CertificateSymbol.cs | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition Certificate = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.Certificate.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(CertificateSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(CertificateSymbolFields.Name), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(CertificateSymbolFields.StoreLocation), IntermediateFieldType.Number), | ||
| 17 | new IntermediateFieldDefinition(nameof(CertificateSymbolFields.StoreName), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(CertificateSymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 19 | new IntermediateFieldDefinition(nameof(CertificateSymbolFields.BinaryRef), IntermediateFieldType.String), | ||
| 20 | new IntermediateFieldDefinition(nameof(CertificateSymbolFields.CertificatePath), IntermediateFieldType.String), | ||
| 21 | new IntermediateFieldDefinition(nameof(CertificateSymbolFields.PFXPassword), IntermediateFieldType.String), | ||
| 22 | }, | ||
| 23 | typeof(CertificateSymbol)); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | namespace WixToolset.Iis.Symbols | ||
| 28 | { | ||
| 29 | using WixToolset.Data; | ||
| 30 | |||
| 31 | public enum CertificateSymbolFields | ||
| 32 | { | ||
| 33 | ComponentRef, | ||
| 34 | Name, | ||
| 35 | StoreLocation, | ||
| 36 | StoreName, | ||
| 37 | Attributes, | ||
| 38 | BinaryRef, | ||
| 39 | CertificatePath, | ||
| 40 | PFXPassword, | ||
| 41 | } | ||
| 42 | |||
| 43 | public class CertificateSymbol : IntermediateSymbol | ||
| 44 | { | ||
| 45 | public CertificateSymbol() : base(IisSymbolDefinitions.Certificate, null, null) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | public CertificateSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.Certificate, sourceLineNumber, id) | ||
| 50 | { | ||
| 51 | } | ||
| 52 | |||
| 53 | public IntermediateField this[CertificateSymbolFields index] => this.Fields[(int)index]; | ||
| 54 | |||
| 55 | public string ComponentRef | ||
| 56 | { | ||
| 57 | get => this.Fields[(int)CertificateSymbolFields.ComponentRef].AsString(); | ||
| 58 | set => this.Set((int)CertificateSymbolFields.ComponentRef, value); | ||
| 59 | } | ||
| 60 | |||
| 61 | public string Name | ||
| 62 | { | ||
| 63 | get => this.Fields[(int)CertificateSymbolFields.Name].AsString(); | ||
| 64 | set => this.Set((int)CertificateSymbolFields.Name, value); | ||
| 65 | } | ||
| 66 | |||
| 67 | public int StoreLocation | ||
| 68 | { | ||
| 69 | get => this.Fields[(int)CertificateSymbolFields.StoreLocation].AsNumber(); | ||
| 70 | set => this.Set((int)CertificateSymbolFields.StoreLocation, value); | ||
| 71 | } | ||
| 72 | |||
| 73 | public string StoreName | ||
| 74 | { | ||
| 75 | get => this.Fields[(int)CertificateSymbolFields.StoreName].AsString(); | ||
| 76 | set => this.Set((int)CertificateSymbolFields.StoreName, value); | ||
| 77 | } | ||
| 78 | |||
| 79 | public int Attributes | ||
| 80 | { | ||
| 81 | get => this.Fields[(int)CertificateSymbolFields.Attributes].AsNumber(); | ||
| 82 | set => this.Set((int)CertificateSymbolFields.Attributes, value); | ||
| 83 | } | ||
| 84 | |||
| 85 | public string BinaryRef | ||
| 86 | { | ||
| 87 | get => this.Fields[(int)CertificateSymbolFields.BinaryRef].AsString(); | ||
| 88 | set => this.Set((int)CertificateSymbolFields.BinaryRef, value); | ||
| 89 | } | ||
| 90 | |||
| 91 | public string CertificatePath | ||
| 92 | { | ||
| 93 | get => this.Fields[(int)CertificateSymbolFields.CertificatePath].AsString(); | ||
| 94 | set => this.Set((int)CertificateSymbolFields.CertificatePath, value); | ||
| 95 | } | ||
| 96 | |||
| 97 | public string PFXPassword | ||
| 98 | { | ||
| 99 | get => this.Fields[(int)CertificateSymbolFields.PFXPassword].AsString(); | ||
| 100 | set => this.Set((int)CertificateSymbolFields.PFXPassword, value); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsAppPoolSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsAppPoolSymbol.cs new file mode 100644 index 00000000..a6fab136 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsAppPoolSymbol.cs | |||
| @@ -0,0 +1,159 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsAppPool = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsAppPool.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.Name), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.UserRef), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.RecycleMinutes), IntermediateFieldType.Number), | ||
| 19 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.RecycleRequests), IntermediateFieldType.Number), | ||
| 20 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.RecycleTimes), IntermediateFieldType.String), | ||
| 21 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.IdleTimeout), IntermediateFieldType.Number), | ||
| 22 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.QueueLimit), IntermediateFieldType.Number), | ||
| 23 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.CPUMon), IntermediateFieldType.String), | ||
| 24 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.MaxProc), IntermediateFieldType.Number), | ||
| 25 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.VirtualMemory), IntermediateFieldType.Number), | ||
| 26 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.PrivateMemory), IntermediateFieldType.Number), | ||
| 27 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.ManagedRuntimeVersion), IntermediateFieldType.String), | ||
| 28 | new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.ManagedPipelineMode), IntermediateFieldType.String), | ||
| 29 | }, | ||
| 30 | typeof(IIsAppPoolSymbol)); | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | namespace WixToolset.Iis.Symbols | ||
| 35 | { | ||
| 36 | using WixToolset.Data; | ||
| 37 | |||
| 38 | public enum IIsAppPoolSymbolFields | ||
| 39 | { | ||
| 40 | Name, | ||
| 41 | ComponentRef, | ||
| 42 | Attributes, | ||
| 43 | UserRef, | ||
| 44 | RecycleMinutes, | ||
| 45 | RecycleRequests, | ||
| 46 | RecycleTimes, | ||
| 47 | IdleTimeout, | ||
| 48 | QueueLimit, | ||
| 49 | CPUMon, | ||
| 50 | MaxProc, | ||
| 51 | VirtualMemory, | ||
| 52 | PrivateMemory, | ||
| 53 | ManagedRuntimeVersion, | ||
| 54 | ManagedPipelineMode, | ||
| 55 | } | ||
| 56 | |||
| 57 | public class IIsAppPoolSymbol : IntermediateSymbol | ||
| 58 | { | ||
| 59 | public IIsAppPoolSymbol() : base(IisSymbolDefinitions.IIsAppPool, null, null) | ||
| 60 | { | ||
| 61 | } | ||
| 62 | |||
| 63 | public IIsAppPoolSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsAppPool, sourceLineNumber, id) | ||
| 64 | { | ||
| 65 | } | ||
| 66 | |||
| 67 | public IntermediateField this[IIsAppPoolSymbolFields index] => this.Fields[(int)index]; | ||
| 68 | |||
| 69 | public string Name | ||
| 70 | { | ||
| 71 | get => this.Fields[(int)IIsAppPoolSymbolFields.Name].AsString(); | ||
| 72 | set => this.Set((int)IIsAppPoolSymbolFields.Name, value); | ||
| 73 | } | ||
| 74 | |||
| 75 | public string ComponentRef | ||
| 76 | { | ||
| 77 | get => this.Fields[(int)IIsAppPoolSymbolFields.ComponentRef].AsString(); | ||
| 78 | set => this.Set((int)IIsAppPoolSymbolFields.ComponentRef, value); | ||
| 79 | } | ||
| 80 | |||
| 81 | public int Attributes | ||
| 82 | { | ||
| 83 | get => this.Fields[(int)IIsAppPoolSymbolFields.Attributes].AsNumber(); | ||
| 84 | set => this.Set((int)IIsAppPoolSymbolFields.Attributes, value); | ||
| 85 | } | ||
| 86 | |||
| 87 | public string UserRef | ||
| 88 | { | ||
| 89 | get => this.Fields[(int)IIsAppPoolSymbolFields.UserRef].AsString(); | ||
| 90 | set => this.Set((int)IIsAppPoolSymbolFields.UserRef, value); | ||
| 91 | } | ||
| 92 | |||
| 93 | public int? RecycleMinutes | ||
| 94 | { | ||
| 95 | get => this.Fields[(int)IIsAppPoolSymbolFields.RecycleMinutes].AsNullableNumber(); | ||
| 96 | set => this.Set((int)IIsAppPoolSymbolFields.RecycleMinutes, value); | ||
| 97 | } | ||
| 98 | |||
| 99 | public int? RecycleRequests | ||
| 100 | { | ||
| 101 | get => this.Fields[(int)IIsAppPoolSymbolFields.RecycleRequests].AsNullableNumber(); | ||
| 102 | set => this.Set((int)IIsAppPoolSymbolFields.RecycleRequests, value); | ||
| 103 | } | ||
| 104 | |||
| 105 | public string RecycleTimes | ||
| 106 | { | ||
| 107 | get => this.Fields[(int)IIsAppPoolSymbolFields.RecycleTimes].AsString(); | ||
| 108 | set => this.Set((int)IIsAppPoolSymbolFields.RecycleTimes, value); | ||
| 109 | } | ||
| 110 | |||
| 111 | public int? IdleTimeout | ||
| 112 | { | ||
| 113 | get => this.Fields[(int)IIsAppPoolSymbolFields.IdleTimeout].AsNullableNumber(); | ||
| 114 | set => this.Set((int)IIsAppPoolSymbolFields.IdleTimeout, value); | ||
| 115 | } | ||
| 116 | |||
| 117 | public int? QueueLimit | ||
| 118 | { | ||
| 119 | get => this.Fields[(int)IIsAppPoolSymbolFields.QueueLimit].AsNullableNumber(); | ||
| 120 | set => this.Set((int)IIsAppPoolSymbolFields.QueueLimit, value); | ||
| 121 | } | ||
| 122 | |||
| 123 | public string CPUMon | ||
| 124 | { | ||
| 125 | get => this.Fields[(int)IIsAppPoolSymbolFields.CPUMon].AsString(); | ||
| 126 | set => this.Set((int)IIsAppPoolSymbolFields.CPUMon, value); | ||
| 127 | } | ||
| 128 | |||
| 129 | public int? MaxProc | ||
| 130 | { | ||
| 131 | get => this.Fields[(int)IIsAppPoolSymbolFields.MaxProc].AsNullableNumber(); | ||
| 132 | set => this.Set((int)IIsAppPoolSymbolFields.MaxProc, value); | ||
| 133 | } | ||
| 134 | |||
| 135 | public int? VirtualMemory | ||
| 136 | { | ||
| 137 | get => this.Fields[(int)IIsAppPoolSymbolFields.VirtualMemory].AsNullableNumber(); | ||
| 138 | set => this.Set((int)IIsAppPoolSymbolFields.VirtualMemory, value); | ||
| 139 | } | ||
| 140 | |||
| 141 | public int? PrivateMemory | ||
| 142 | { | ||
| 143 | get => this.Fields[(int)IIsAppPoolSymbolFields.PrivateMemory].AsNullableNumber(); | ||
| 144 | set => this.Set((int)IIsAppPoolSymbolFields.PrivateMemory, value); | ||
| 145 | } | ||
| 146 | |||
| 147 | public string ManagedRuntimeVersion | ||
| 148 | { | ||
| 149 | get => this.Fields[(int)IIsAppPoolSymbolFields.ManagedRuntimeVersion].AsString(); | ||
| 150 | set => this.Set((int)IIsAppPoolSymbolFields.ManagedRuntimeVersion, value); | ||
| 151 | } | ||
| 152 | |||
| 153 | public string ManagedPipelineMode | ||
| 154 | { | ||
| 155 | get => this.Fields[(int)IIsAppPoolSymbolFields.ManagedPipelineMode].AsString(); | ||
| 156 | set => this.Set((int)IIsAppPoolSymbolFields.ManagedPipelineMode, value); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsFilterSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsFilterSymbol.cs new file mode 100644 index 00000000..618730bf --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsFilterSymbol.cs | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsFilter = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsFilter.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Name), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Path), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.WebRef), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Description), IntermediateFieldType.String), | ||
| 19 | new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Flags), IntermediateFieldType.Number), | ||
| 20 | new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.LoadOrder), IntermediateFieldType.Number), | ||
| 21 | }, | ||
| 22 | typeof(IIsFilterSymbol)); | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | namespace WixToolset.Iis.Symbols | ||
| 27 | { | ||
| 28 | using WixToolset.Data; | ||
| 29 | |||
| 30 | public enum IIsFilterSymbolFields | ||
| 31 | { | ||
| 32 | Name, | ||
| 33 | ComponentRef, | ||
| 34 | Path, | ||
| 35 | WebRef, | ||
| 36 | Description, | ||
| 37 | Flags, | ||
| 38 | LoadOrder, | ||
| 39 | } | ||
| 40 | |||
| 41 | public class IIsFilterSymbol : IntermediateSymbol | ||
| 42 | { | ||
| 43 | public IIsFilterSymbol() : base(IisSymbolDefinitions.IIsFilter, null, null) | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | public IIsFilterSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsFilter, sourceLineNumber, id) | ||
| 48 | { | ||
| 49 | } | ||
| 50 | |||
| 51 | public IntermediateField this[IIsFilterSymbolFields index] => this.Fields[(int)index]; | ||
| 52 | |||
| 53 | public string Name | ||
| 54 | { | ||
| 55 | get => this.Fields[(int)IIsFilterSymbolFields.Name].AsString(); | ||
| 56 | set => this.Set((int)IIsFilterSymbolFields.Name, value); | ||
| 57 | } | ||
| 58 | |||
| 59 | public string ComponentRef | ||
| 60 | { | ||
| 61 | get => this.Fields[(int)IIsFilterSymbolFields.ComponentRef].AsString(); | ||
| 62 | set => this.Set((int)IIsFilterSymbolFields.ComponentRef, value); | ||
| 63 | } | ||
| 64 | |||
| 65 | public string Path | ||
| 66 | { | ||
| 67 | get => this.Fields[(int)IIsFilterSymbolFields.Path].AsString(); | ||
| 68 | set => this.Set((int)IIsFilterSymbolFields.Path, value); | ||
| 69 | } | ||
| 70 | |||
| 71 | public string WebRef | ||
| 72 | { | ||
| 73 | get => this.Fields[(int)IIsFilterSymbolFields.WebRef].AsString(); | ||
| 74 | set => this.Set((int)IIsFilterSymbolFields.WebRef, value); | ||
| 75 | } | ||
| 76 | |||
| 77 | public string Description | ||
| 78 | { | ||
| 79 | get => this.Fields[(int)IIsFilterSymbolFields.Description].AsString(); | ||
| 80 | set => this.Set((int)IIsFilterSymbolFields.Description, value); | ||
| 81 | } | ||
| 82 | |||
| 83 | public int Flags | ||
| 84 | { | ||
| 85 | get => this.Fields[(int)IIsFilterSymbolFields.Flags].AsNumber(); | ||
| 86 | set => this.Set((int)IIsFilterSymbolFields.Flags, value); | ||
| 87 | } | ||
| 88 | |||
| 89 | public int? LoadOrder | ||
| 90 | { | ||
| 91 | get => this.Fields[(int)IIsFilterSymbolFields.LoadOrder].AsNullableNumber(); | ||
| 92 | set => this.Set((int)IIsFilterSymbolFields.LoadOrder, value); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsHttpHeaderSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsHttpHeaderSymbol.cs new file mode 100644 index 00000000..3ab2bf59 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsHttpHeaderSymbol.cs | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsHttpHeader = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsHttpHeader.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.HttpHeader), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.ParentType), IntermediateFieldType.Number), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.ParentValue), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Name), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Value), IntermediateFieldType.String), | ||
| 19 | new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 20 | new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Sequence), IntermediateFieldType.Number), | ||
| 21 | }, | ||
| 22 | typeof(IIsHttpHeaderSymbol)); | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | namespace WixToolset.Iis.Symbols | ||
| 27 | { | ||
| 28 | using WixToolset.Data; | ||
| 29 | |||
| 30 | public enum IIsHttpHeaderSymbolFields | ||
| 31 | { | ||
| 32 | HttpHeader, | ||
| 33 | ParentType, | ||
| 34 | ParentValue, | ||
| 35 | Name, | ||
| 36 | Value, | ||
| 37 | Attributes, | ||
| 38 | Sequence, | ||
| 39 | } | ||
| 40 | |||
| 41 | public class IIsHttpHeaderSymbol : IntermediateSymbol | ||
| 42 | { | ||
| 43 | public IIsHttpHeaderSymbol() : base(IisSymbolDefinitions.IIsHttpHeader, null, null) | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | public IIsHttpHeaderSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsHttpHeader, sourceLineNumber, id) | ||
| 48 | { | ||
| 49 | } | ||
| 50 | |||
| 51 | public IntermediateField this[IIsHttpHeaderSymbolFields index] => this.Fields[(int)index]; | ||
| 52 | |||
| 53 | public string HttpHeader | ||
| 54 | { | ||
| 55 | get => this.Fields[(int)IIsHttpHeaderSymbolFields.HttpHeader].AsString(); | ||
| 56 | set => this.Set((int)IIsHttpHeaderSymbolFields.HttpHeader, value); | ||
| 57 | } | ||
| 58 | |||
| 59 | public int ParentType | ||
| 60 | { | ||
| 61 | get => this.Fields[(int)IIsHttpHeaderSymbolFields.ParentType].AsNumber(); | ||
| 62 | set => this.Set((int)IIsHttpHeaderSymbolFields.ParentType, value); | ||
| 63 | } | ||
| 64 | |||
| 65 | public string ParentValue | ||
| 66 | { | ||
| 67 | get => this.Fields[(int)IIsHttpHeaderSymbolFields.ParentValue].AsString(); | ||
| 68 | set => this.Set((int)IIsHttpHeaderSymbolFields.ParentValue, value); | ||
| 69 | } | ||
| 70 | |||
| 71 | public string Name | ||
| 72 | { | ||
| 73 | get => this.Fields[(int)IIsHttpHeaderSymbolFields.Name].AsString(); | ||
| 74 | set => this.Set((int)IIsHttpHeaderSymbolFields.Name, value); | ||
| 75 | } | ||
| 76 | |||
| 77 | public string Value | ||
| 78 | { | ||
| 79 | get => this.Fields[(int)IIsHttpHeaderSymbolFields.Value].AsString(); | ||
| 80 | set => this.Set((int)IIsHttpHeaderSymbolFields.Value, value); | ||
| 81 | } | ||
| 82 | |||
| 83 | public int Attributes | ||
| 84 | { | ||
| 85 | get => this.Fields[(int)IIsHttpHeaderSymbolFields.Attributes].AsNumber(); | ||
| 86 | set => this.Set((int)IIsHttpHeaderSymbolFields.Attributes, value); | ||
| 87 | } | ||
| 88 | |||
| 89 | public int? Sequence | ||
| 90 | { | ||
| 91 | get => this.Fields[(int)IIsHttpHeaderSymbolFields.Sequence].AsNullableNumber(); | ||
| 92 | set => this.Set((int)IIsHttpHeaderSymbolFields.Sequence, value); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsMimeMapSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsMimeMapSymbol.cs new file mode 100644 index 00000000..4af6f81c --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsMimeMapSymbol.cs | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsMimeMap = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsMimeMap.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.ParentType), IntermediateFieldType.Number), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.ParentValue), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.MimeType), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.Extension), IntermediateFieldType.String), | ||
| 18 | }, | ||
| 19 | typeof(IIsMimeMapSymbol)); | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | namespace WixToolset.Iis.Symbols | ||
| 24 | { | ||
| 25 | using WixToolset.Data; | ||
| 26 | |||
| 27 | public enum IIsMimeMapSymbolFields | ||
| 28 | { | ||
| 29 | ParentType, | ||
| 30 | ParentValue, | ||
| 31 | MimeType, | ||
| 32 | Extension, | ||
| 33 | } | ||
| 34 | |||
| 35 | public class IIsMimeMapSymbol : IntermediateSymbol | ||
| 36 | { | ||
| 37 | public IIsMimeMapSymbol() : base(IisSymbolDefinitions.IIsMimeMap, null, null) | ||
| 38 | { | ||
| 39 | } | ||
| 40 | |||
| 41 | public IIsMimeMapSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsMimeMap, sourceLineNumber, id) | ||
| 42 | { | ||
| 43 | } | ||
| 44 | |||
| 45 | public IntermediateField this[IIsMimeMapSymbolFields index] => this.Fields[(int)index]; | ||
| 46 | |||
| 47 | public int ParentType | ||
| 48 | { | ||
| 49 | get => this.Fields[(int)IIsMimeMapSymbolFields.ParentType].AsNumber(); | ||
| 50 | set => this.Set((int)IIsMimeMapSymbolFields.ParentType, value); | ||
| 51 | } | ||
| 52 | |||
| 53 | public string ParentValue | ||
| 54 | { | ||
| 55 | get => this.Fields[(int)IIsMimeMapSymbolFields.ParentValue].AsString(); | ||
| 56 | set => this.Set((int)IIsMimeMapSymbolFields.ParentValue, value); | ||
| 57 | } | ||
| 58 | |||
| 59 | public string MimeType | ||
| 60 | { | ||
| 61 | get => this.Fields[(int)IIsMimeMapSymbolFields.MimeType].AsString(); | ||
| 62 | set => this.Set((int)IIsMimeMapSymbolFields.MimeType, value); | ||
| 63 | } | ||
| 64 | |||
| 65 | public string Extension | ||
| 66 | { | ||
| 67 | get => this.Fields[(int)IIsMimeMapSymbolFields.Extension].AsString(); | ||
| 68 | set => this.Set((int)IIsMimeMapSymbolFields.Extension, value); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsPropertySymbol.cs b/src/ext/Iis/wixext/Symbols/IIsPropertySymbol.cs new file mode 100644 index 00000000..9cf67014 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsPropertySymbol.cs | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsProperty = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsProperty.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsPropertySymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsPropertySymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsPropertySymbolFields.Value), IntermediateFieldType.String), | ||
| 17 | }, | ||
| 18 | typeof(IIsPropertySymbol)); | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | namespace WixToolset.Iis.Symbols | ||
| 23 | { | ||
| 24 | using WixToolset.Data; | ||
| 25 | |||
| 26 | public enum IIsPropertySymbolFields | ||
| 27 | { | ||
| 28 | ComponentRef, | ||
| 29 | Attributes, | ||
| 30 | Value, | ||
| 31 | } | ||
| 32 | |||
| 33 | public class IIsPropertySymbol : IntermediateSymbol | ||
| 34 | { | ||
| 35 | public IIsPropertySymbol() : base(IisSymbolDefinitions.IIsProperty, null, null) | ||
| 36 | { | ||
| 37 | } | ||
| 38 | |||
| 39 | public IIsPropertySymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsProperty, sourceLineNumber, id) | ||
| 40 | { | ||
| 41 | } | ||
| 42 | |||
| 43 | public IntermediateField this[IIsPropertySymbolFields index] => this.Fields[(int)index]; | ||
| 44 | |||
| 45 | public string ComponentRef | ||
| 46 | { | ||
| 47 | get => this.Fields[(int)IIsPropertySymbolFields.ComponentRef].AsString(); | ||
| 48 | set => this.Set((int)IIsPropertySymbolFields.ComponentRef, value); | ||
| 49 | } | ||
| 50 | |||
| 51 | public int Attributes | ||
| 52 | { | ||
| 53 | get => this.Fields[(int)IIsPropertySymbolFields.Attributes].AsNumber(); | ||
| 54 | set => this.Set((int)IIsPropertySymbolFields.Attributes, value); | ||
| 55 | } | ||
| 56 | |||
| 57 | public string Value | ||
| 58 | { | ||
| 59 | get => this.Fields[(int)IIsPropertySymbolFields.Value].AsString(); | ||
| 60 | set => this.Set((int)IIsPropertySymbolFields.Value, value); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebAddressSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebAddressSymbol.cs new file mode 100644 index 00000000..7111718a --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebAddressSymbol.cs | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebAddress = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebAddress.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.WebRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.IP), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.Port), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.Header), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.Secure), IntermediateFieldType.Number), | ||
| 19 | }, | ||
| 20 | typeof(IIsWebAddressSymbol)); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace WixToolset.Iis.Symbols | ||
| 25 | { | ||
| 26 | using WixToolset.Data; | ||
| 27 | |||
| 28 | public enum IIsWebAddressSymbolFields | ||
| 29 | { | ||
| 30 | WebRef, | ||
| 31 | IP, | ||
| 32 | Port, | ||
| 33 | Header, | ||
| 34 | Secure, | ||
| 35 | } | ||
| 36 | |||
| 37 | public class IIsWebAddressSymbol : IntermediateSymbol | ||
| 38 | { | ||
| 39 | public IIsWebAddressSymbol() : base(IisSymbolDefinitions.IIsWebAddress, null, null) | ||
| 40 | { | ||
| 41 | } | ||
| 42 | |||
| 43 | public IIsWebAddressSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebAddress, sourceLineNumber, id) | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | public IntermediateField this[IIsWebAddressSymbolFields index] => this.Fields[(int)index]; | ||
| 48 | |||
| 49 | public string WebRef | ||
| 50 | { | ||
| 51 | get => this.Fields[(int)IIsWebAddressSymbolFields.WebRef].AsString(); | ||
| 52 | set => this.Set((int)IIsWebAddressSymbolFields.WebRef, value); | ||
| 53 | } | ||
| 54 | |||
| 55 | public string IP | ||
| 56 | { | ||
| 57 | get => this.Fields[(int)IIsWebAddressSymbolFields.IP].AsString(); | ||
| 58 | set => this.Set((int)IIsWebAddressSymbolFields.IP, value); | ||
| 59 | } | ||
| 60 | |||
| 61 | public string Port | ||
| 62 | { | ||
| 63 | get => this.Fields[(int)IIsWebAddressSymbolFields.Port].AsString(); | ||
| 64 | set => this.Set((int)IIsWebAddressSymbolFields.Port, value); | ||
| 65 | } | ||
| 66 | |||
| 67 | public string Header | ||
| 68 | { | ||
| 69 | get => this.Fields[(int)IIsWebAddressSymbolFields.Header].AsString(); | ||
| 70 | set => this.Set((int)IIsWebAddressSymbolFields.Header, value); | ||
| 71 | } | ||
| 72 | |||
| 73 | public int? Secure | ||
| 74 | { | ||
| 75 | get => this.Fields[(int)IIsWebAddressSymbolFields.Secure].AsNullableNumber(); | ||
| 76 | set => this.Set((int)IIsWebAddressSymbolFields.Secure, value); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebApplicationExtensionSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebApplicationExtensionSymbol.cs new file mode 100644 index 00000000..4283d702 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebApplicationExtensionSymbol.cs | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebApplicationExtension = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebApplicationExtension.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.ApplicationRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Extension), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Verbs), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Executable), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 19 | }, | ||
| 20 | typeof(IIsWebApplicationExtensionSymbol)); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace WixToolset.Iis.Symbols | ||
| 25 | { | ||
| 26 | using WixToolset.Data; | ||
| 27 | |||
| 28 | public enum IIsWebApplicationExtensionSymbolFields | ||
| 29 | { | ||
| 30 | ApplicationRef, | ||
| 31 | Extension, | ||
| 32 | Verbs, | ||
| 33 | Executable, | ||
| 34 | Attributes, | ||
| 35 | } | ||
| 36 | |||
| 37 | public class IIsWebApplicationExtensionSymbol : IntermediateSymbol | ||
| 38 | { | ||
| 39 | public IIsWebApplicationExtensionSymbol() : base(IisSymbolDefinitions.IIsWebApplicationExtension, null, null) | ||
| 40 | { | ||
| 41 | } | ||
| 42 | |||
| 43 | public IIsWebApplicationExtensionSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebApplicationExtension, sourceLineNumber, id) | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | public IntermediateField this[IIsWebApplicationExtensionSymbolFields index] => this.Fields[(int)index]; | ||
| 48 | |||
| 49 | public string ApplicationRef | ||
| 50 | { | ||
| 51 | get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.ApplicationRef].AsString(); | ||
| 52 | set => this.Set((int)IIsWebApplicationExtensionSymbolFields.ApplicationRef, value); | ||
| 53 | } | ||
| 54 | |||
| 55 | public string Extension | ||
| 56 | { | ||
| 57 | get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Extension].AsString(); | ||
| 58 | set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Extension, value); | ||
| 59 | } | ||
| 60 | |||
| 61 | public string Verbs | ||
| 62 | { | ||
| 63 | get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Verbs].AsString(); | ||
| 64 | set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Verbs, value); | ||
| 65 | } | ||
| 66 | |||
| 67 | public string Executable | ||
| 68 | { | ||
| 69 | get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Executable].AsString(); | ||
| 70 | set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Executable, value); | ||
| 71 | } | ||
| 72 | |||
| 73 | public int Attributes | ||
| 74 | { | ||
| 75 | get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Attributes].AsNumber(); | ||
| 76 | set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Attributes, value); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebApplicationSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebApplicationSymbol.cs new file mode 100644 index 00000000..2f6f87de --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebApplicationSymbol.cs | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebApplication = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebApplication.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.Name), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.Isolation), IntermediateFieldType.Number), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.AllowSessions), IntermediateFieldType.Number), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.SessionTimeout), IntermediateFieldType.Number), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.Buffer), IntermediateFieldType.Number), | ||
| 19 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ParentPaths), IntermediateFieldType.Number), | ||
| 20 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.DefaultScript), IntermediateFieldType.String), | ||
| 21 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ScriptTimeout), IntermediateFieldType.Number), | ||
| 22 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ServerDebugging), IntermediateFieldType.Number), | ||
| 23 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ClientDebugging), IntermediateFieldType.Number), | ||
| 24 | new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.AppPoolRef), IntermediateFieldType.String), | ||
| 25 | }, | ||
| 26 | typeof(IIsWebApplicationSymbol)); | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | namespace WixToolset.Iis.Symbols | ||
| 31 | { | ||
| 32 | using WixToolset.Data; | ||
| 33 | |||
| 34 | public enum IIsWebApplicationSymbolFields | ||
| 35 | { | ||
| 36 | Name, | ||
| 37 | Isolation, | ||
| 38 | AllowSessions, | ||
| 39 | SessionTimeout, | ||
| 40 | Buffer, | ||
| 41 | ParentPaths, | ||
| 42 | DefaultScript, | ||
| 43 | ScriptTimeout, | ||
| 44 | ServerDebugging, | ||
| 45 | ClientDebugging, | ||
| 46 | AppPoolRef, | ||
| 47 | } | ||
| 48 | |||
| 49 | public class IIsWebApplicationSymbol : IntermediateSymbol | ||
| 50 | { | ||
| 51 | public IIsWebApplicationSymbol() : base(IisSymbolDefinitions.IIsWebApplication, null, null) | ||
| 52 | { | ||
| 53 | } | ||
| 54 | |||
| 55 | public IIsWebApplicationSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebApplication, sourceLineNumber, id) | ||
| 56 | { | ||
| 57 | } | ||
| 58 | |||
| 59 | public IntermediateField this[IIsWebApplicationSymbolFields index] => this.Fields[(int)index]; | ||
| 60 | |||
| 61 | public string Name | ||
| 62 | { | ||
| 63 | get => this.Fields[(int)IIsWebApplicationSymbolFields.Name].AsString(); | ||
| 64 | set => this.Set((int)IIsWebApplicationSymbolFields.Name, value); | ||
| 65 | } | ||
| 66 | |||
| 67 | public int Isolation | ||
| 68 | { | ||
| 69 | get => this.Fields[(int)IIsWebApplicationSymbolFields.Isolation].AsNumber(); | ||
| 70 | set => this.Set((int)IIsWebApplicationSymbolFields.Isolation, value); | ||
| 71 | } | ||
| 72 | |||
| 73 | public int? AllowSessions | ||
| 74 | { | ||
| 75 | get => this.Fields[(int)IIsWebApplicationSymbolFields.AllowSessions].AsNullableNumber(); | ||
| 76 | set => this.Set((int)IIsWebApplicationSymbolFields.AllowSessions, value); | ||
| 77 | } | ||
| 78 | |||
| 79 | public int? SessionTimeout | ||
| 80 | { | ||
| 81 | get => this.Fields[(int)IIsWebApplicationSymbolFields.SessionTimeout].AsNullableNumber(); | ||
| 82 | set => this.Set((int)IIsWebApplicationSymbolFields.SessionTimeout, value); | ||
| 83 | } | ||
| 84 | |||
| 85 | public int? Buffer | ||
| 86 | { | ||
| 87 | get => this.Fields[(int)IIsWebApplicationSymbolFields.Buffer].AsNullableNumber(); | ||
| 88 | set => this.Set((int)IIsWebApplicationSymbolFields.Buffer, value); | ||
| 89 | } | ||
| 90 | |||
| 91 | public int? ParentPaths | ||
| 92 | { | ||
| 93 | get => this.Fields[(int)IIsWebApplicationSymbolFields.ParentPaths].AsNullableNumber(); | ||
| 94 | set => this.Set((int)IIsWebApplicationSymbolFields.ParentPaths, value); | ||
| 95 | } | ||
| 96 | |||
| 97 | public string DefaultScript | ||
| 98 | { | ||
| 99 | get => this.Fields[(int)IIsWebApplicationSymbolFields.DefaultScript].AsString(); | ||
| 100 | set => this.Set((int)IIsWebApplicationSymbolFields.DefaultScript, value); | ||
| 101 | } | ||
| 102 | |||
| 103 | public int? ScriptTimeout | ||
| 104 | { | ||
| 105 | get => this.Fields[(int)IIsWebApplicationSymbolFields.ScriptTimeout].AsNullableNumber(); | ||
| 106 | set => this.Set((int)IIsWebApplicationSymbolFields.ScriptTimeout, value); | ||
| 107 | } | ||
| 108 | |||
| 109 | public int? ServerDebugging | ||
| 110 | { | ||
| 111 | get => this.Fields[(int)IIsWebApplicationSymbolFields.ServerDebugging].AsNullableNumber(); | ||
| 112 | set => this.Set((int)IIsWebApplicationSymbolFields.ServerDebugging, value); | ||
| 113 | } | ||
| 114 | |||
| 115 | public int? ClientDebugging | ||
| 116 | { | ||
| 117 | get => this.Fields[(int)IIsWebApplicationSymbolFields.ClientDebugging].AsNullableNumber(); | ||
| 118 | set => this.Set((int)IIsWebApplicationSymbolFields.ClientDebugging, value); | ||
| 119 | } | ||
| 120 | |||
| 121 | public string AppPoolRef | ||
| 122 | { | ||
| 123 | get => this.Fields[(int)IIsWebApplicationSymbolFields.AppPoolRef].AsString(); | ||
| 124 | set => this.Set((int)IIsWebApplicationSymbolFields.AppPoolRef, value); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebDirPropertiesSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebDirPropertiesSymbol.cs new file mode 100644 index 00000000..42d2dead --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebDirPropertiesSymbol.cs | |||
| @@ -0,0 +1,151 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebDirProperties = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebDirProperties.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.Access), IntermediateFieldType.Number), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.Authorization), IntermediateFieldType.Number), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AnonymousUserRef), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.IIsControlledPassword), IntermediateFieldType.Number), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.LogVisits), IntermediateFieldType.Number), | ||
| 19 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.Index), IntermediateFieldType.Number), | ||
| 20 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.DefaultDoc), IntermediateFieldType.String), | ||
| 21 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AspDetailedError), IntermediateFieldType.Number), | ||
| 22 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.HttpExpires), IntermediateFieldType.String), | ||
| 23 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.CacheControlMaxAge), IntermediateFieldType.Number), | ||
| 24 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.CacheControlCustom), IntermediateFieldType.String), | ||
| 25 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.NoCustomError), IntermediateFieldType.Number), | ||
| 26 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AccessSSLFlags), IntermediateFieldType.Number), | ||
| 27 | new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AuthenticationProviders), IntermediateFieldType.String), | ||
| 28 | }, | ||
| 29 | typeof(IIsWebDirPropertiesSymbol)); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | namespace WixToolset.Iis.Symbols | ||
| 34 | { | ||
| 35 | using WixToolset.Data; | ||
| 36 | |||
| 37 | public enum IIsWebDirPropertiesSymbolFields | ||
| 38 | { | ||
| 39 | Access, | ||
| 40 | Authorization, | ||
| 41 | AnonymousUserRef, | ||
| 42 | IIsControlledPassword, | ||
| 43 | LogVisits, | ||
| 44 | Index, | ||
| 45 | DefaultDoc, | ||
| 46 | AspDetailedError, | ||
| 47 | HttpExpires, | ||
| 48 | CacheControlMaxAge, | ||
| 49 | CacheControlCustom, | ||
| 50 | NoCustomError, | ||
| 51 | AccessSSLFlags, | ||
| 52 | AuthenticationProviders, | ||
| 53 | } | ||
| 54 | |||
| 55 | public class IIsWebDirPropertiesSymbol : IntermediateSymbol | ||
| 56 | { | ||
| 57 | public IIsWebDirPropertiesSymbol() : base(IisSymbolDefinitions.IIsWebDirProperties, null, null) | ||
| 58 | { | ||
| 59 | } | ||
| 60 | |||
| 61 | public IIsWebDirPropertiesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebDirProperties, sourceLineNumber, id) | ||
| 62 | { | ||
| 63 | } | ||
| 64 | |||
| 65 | public IntermediateField this[IIsWebDirPropertiesSymbolFields index] => this.Fields[(int)index]; | ||
| 66 | |||
| 67 | public int? Access | ||
| 68 | { | ||
| 69 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.Access].AsNullableNumber(); | ||
| 70 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.Access, value); | ||
| 71 | } | ||
| 72 | |||
| 73 | public int? Authorization | ||
| 74 | { | ||
| 75 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.Authorization].AsNullableNumber(); | ||
| 76 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.Authorization, value); | ||
| 77 | } | ||
| 78 | |||
| 79 | public string AnonymousUserRef | ||
| 80 | { | ||
| 81 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AnonymousUserRef].AsString(); | ||
| 82 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.AnonymousUserRef, value); | ||
| 83 | } | ||
| 84 | |||
| 85 | public int? IIsControlledPassword | ||
| 86 | { | ||
| 87 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.IIsControlledPassword].AsNullableNumber(); | ||
| 88 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.IIsControlledPassword, value); | ||
| 89 | } | ||
| 90 | |||
| 91 | public int? LogVisits | ||
| 92 | { | ||
| 93 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.LogVisits].AsNullableNumber(); | ||
| 94 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.LogVisits, value); | ||
| 95 | } | ||
| 96 | |||
| 97 | public int? Index | ||
| 98 | { | ||
| 99 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.Index].AsNullableNumber(); | ||
| 100 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.Index, value); | ||
| 101 | } | ||
| 102 | |||
| 103 | public string DefaultDoc | ||
| 104 | { | ||
| 105 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.DefaultDoc].AsString(); | ||
| 106 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.DefaultDoc, value); | ||
| 107 | } | ||
| 108 | |||
| 109 | public int? AspDetailedError | ||
| 110 | { | ||
| 111 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AspDetailedError].AsNullableNumber(); | ||
| 112 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.AspDetailedError, value); | ||
| 113 | } | ||
| 114 | |||
| 115 | public string HttpExpires | ||
| 116 | { | ||
| 117 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.HttpExpires].AsString(); | ||
| 118 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.HttpExpires, value); | ||
| 119 | } | ||
| 120 | |||
| 121 | public int? CacheControlMaxAge | ||
| 122 | { | ||
| 123 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.CacheControlMaxAge].AsNullableNumber(); | ||
| 124 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.CacheControlMaxAge, value); | ||
| 125 | } | ||
| 126 | |||
| 127 | public string CacheControlCustom | ||
| 128 | { | ||
| 129 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.CacheControlCustom].AsString(); | ||
| 130 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.CacheControlCustom, value); | ||
| 131 | } | ||
| 132 | |||
| 133 | public int? NoCustomError | ||
| 134 | { | ||
| 135 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.NoCustomError].AsNullableNumber(); | ||
| 136 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.NoCustomError, value); | ||
| 137 | } | ||
| 138 | |||
| 139 | public int? AccessSSLFlags | ||
| 140 | { | ||
| 141 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AccessSSLFlags].AsNullableNumber(); | ||
| 142 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.AccessSSLFlags, value); | ||
| 143 | } | ||
| 144 | |||
| 145 | public string AuthenticationProviders | ||
| 146 | { | ||
| 147 | get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AuthenticationProviders].AsString(); | ||
| 148 | set => this.Set((int)IIsWebDirPropertiesSymbolFields.AuthenticationProviders, value); | ||
| 149 | } | ||
| 150 | } | ||
| 151 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebDirSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebDirSymbol.cs new file mode 100644 index 00000000..7f257f14 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebDirSymbol.cs | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebDir = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebDir.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.WebRef), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.Path), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.DirPropertiesRef), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.ApplicationRef), IntermediateFieldType.String), | ||
| 19 | }, | ||
| 20 | typeof(IIsWebDirSymbol)); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace WixToolset.Iis.Symbols | ||
| 25 | { | ||
| 26 | using WixToolset.Data; | ||
| 27 | |||
| 28 | public enum IIsWebDirSymbolFields | ||
| 29 | { | ||
| 30 | ComponentRef, | ||
| 31 | WebRef, | ||
| 32 | Path, | ||
| 33 | DirPropertiesRef, | ||
| 34 | ApplicationRef, | ||
| 35 | } | ||
| 36 | |||
| 37 | public class IIsWebDirSymbol : IntermediateSymbol | ||
| 38 | { | ||
| 39 | public IIsWebDirSymbol() : base(IisSymbolDefinitions.IIsWebDir, null, null) | ||
| 40 | { | ||
| 41 | } | ||
| 42 | |||
| 43 | public IIsWebDirSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebDir, sourceLineNumber, id) | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | public IntermediateField this[IIsWebDirSymbolFields index] => this.Fields[(int)index]; | ||
| 48 | |||
| 49 | public string ComponentRef | ||
| 50 | { | ||
| 51 | get => this.Fields[(int)IIsWebDirSymbolFields.ComponentRef].AsString(); | ||
| 52 | set => this.Set((int)IIsWebDirSymbolFields.ComponentRef, value); | ||
| 53 | } | ||
| 54 | |||
| 55 | public string WebRef | ||
| 56 | { | ||
| 57 | get => this.Fields[(int)IIsWebDirSymbolFields.WebRef].AsString(); | ||
| 58 | set => this.Set((int)IIsWebDirSymbolFields.WebRef, value); | ||
| 59 | } | ||
| 60 | |||
| 61 | public string Path | ||
| 62 | { | ||
| 63 | get => this.Fields[(int)IIsWebDirSymbolFields.Path].AsString(); | ||
| 64 | set => this.Set((int)IIsWebDirSymbolFields.Path, value); | ||
| 65 | } | ||
| 66 | |||
| 67 | public string DirPropertiesRef | ||
| 68 | { | ||
| 69 | get => this.Fields[(int)IIsWebDirSymbolFields.DirPropertiesRef].AsString(); | ||
| 70 | set => this.Set((int)IIsWebDirSymbolFields.DirPropertiesRef, value); | ||
| 71 | } | ||
| 72 | |||
| 73 | public string ApplicationRef | ||
| 74 | { | ||
| 75 | get => this.Fields[(int)IIsWebDirSymbolFields.ApplicationRef].AsString(); | ||
| 76 | set => this.Set((int)IIsWebDirSymbolFields.ApplicationRef, value); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebErrorSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebErrorSymbol.cs new file mode 100644 index 00000000..f8488fed --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebErrorSymbol.cs | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebError = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebError.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.ErrorCode), IntermediateFieldType.Number), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.SubCode), IntermediateFieldType.Number), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.ParentType), IntermediateFieldType.Number), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.ParentValue), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.File), IntermediateFieldType.String), | ||
| 19 | new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.URL), IntermediateFieldType.String), | ||
| 20 | }, | ||
| 21 | typeof(IIsWebErrorSymbol)); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | namespace WixToolset.Iis.Symbols | ||
| 26 | { | ||
| 27 | using WixToolset.Data; | ||
| 28 | |||
| 29 | public enum IIsWebErrorSymbolFields | ||
| 30 | { | ||
| 31 | ErrorCode, | ||
| 32 | SubCode, | ||
| 33 | ParentType, | ||
| 34 | ParentValue, | ||
| 35 | File, | ||
| 36 | URL, | ||
| 37 | } | ||
| 38 | |||
| 39 | public class IIsWebErrorSymbol : IntermediateSymbol | ||
| 40 | { | ||
| 41 | public IIsWebErrorSymbol() : base(IisSymbolDefinitions.IIsWebError, null, null) | ||
| 42 | { | ||
| 43 | } | ||
| 44 | |||
| 45 | public IIsWebErrorSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebError, sourceLineNumber, id) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | public IntermediateField this[IIsWebErrorSymbolFields index] => this.Fields[(int)index]; | ||
| 50 | |||
| 51 | public int ErrorCode | ||
| 52 | { | ||
| 53 | get => this.Fields[(int)IIsWebErrorSymbolFields.ErrorCode].AsNumber(); | ||
| 54 | set => this.Set((int)IIsWebErrorSymbolFields.ErrorCode, value); | ||
| 55 | } | ||
| 56 | |||
| 57 | public int SubCode | ||
| 58 | { | ||
| 59 | get => this.Fields[(int)IIsWebErrorSymbolFields.SubCode].AsNumber(); | ||
| 60 | set => this.Set((int)IIsWebErrorSymbolFields.SubCode, value); | ||
| 61 | } | ||
| 62 | |||
| 63 | public int ParentType | ||
| 64 | { | ||
| 65 | get => this.Fields[(int)IIsWebErrorSymbolFields.ParentType].AsNumber(); | ||
| 66 | set => this.Set((int)IIsWebErrorSymbolFields.ParentType, value); | ||
| 67 | } | ||
| 68 | |||
| 69 | public string ParentValue | ||
| 70 | { | ||
| 71 | get => this.Fields[(int)IIsWebErrorSymbolFields.ParentValue].AsString(); | ||
| 72 | set => this.Set((int)IIsWebErrorSymbolFields.ParentValue, value); | ||
| 73 | } | ||
| 74 | |||
| 75 | public string File | ||
| 76 | { | ||
| 77 | get => this.Fields[(int)IIsWebErrorSymbolFields.File].AsString(); | ||
| 78 | set => this.Set((int)IIsWebErrorSymbolFields.File, value); | ||
| 79 | } | ||
| 80 | |||
| 81 | public string URL | ||
| 82 | { | ||
| 83 | get => this.Fields[(int)IIsWebErrorSymbolFields.URL].AsString(); | ||
| 84 | set => this.Set((int)IIsWebErrorSymbolFields.URL, value); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebLogSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebLogSymbol.cs new file mode 100644 index 00000000..409dc673 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebLogSymbol.cs | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebLog = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebLog.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebLogSymbolFields.Format), IntermediateFieldType.String), | ||
| 15 | }, | ||
| 16 | typeof(IIsWebLogSymbol)); | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace WixToolset.Iis.Symbols | ||
| 21 | { | ||
| 22 | using WixToolset.Data; | ||
| 23 | |||
| 24 | public enum IIsWebLogSymbolFields | ||
| 25 | { | ||
| 26 | Format, | ||
| 27 | } | ||
| 28 | |||
| 29 | public class IIsWebLogSymbol : IntermediateSymbol | ||
| 30 | { | ||
| 31 | public IIsWebLogSymbol() : base(IisSymbolDefinitions.IIsWebLog, null, null) | ||
| 32 | { | ||
| 33 | } | ||
| 34 | |||
| 35 | public IIsWebLogSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebLog, sourceLineNumber, id) | ||
| 36 | { | ||
| 37 | } | ||
| 38 | |||
| 39 | public IntermediateField this[IIsWebLogSymbolFields index] => this.Fields[(int)index]; | ||
| 40 | |||
| 41 | public string Format | ||
| 42 | { | ||
| 43 | get => this.Fields[(int)IIsWebLogSymbolFields.Format].AsString(); | ||
| 44 | set => this.Set((int)IIsWebLogSymbolFields.Format, value); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebServiceExtensionSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebServiceExtensionSymbol.cs new file mode 100644 index 00000000..44922357 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebServiceExtensionSymbol.cs | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebServiceExtension = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebServiceExtension.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.File), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.Description), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.Group), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 19 | }, | ||
| 20 | typeof(IIsWebServiceExtensionSymbol)); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace WixToolset.Iis.Symbols | ||
| 25 | { | ||
| 26 | using WixToolset.Data; | ||
| 27 | |||
| 28 | public enum IIsWebServiceExtensionSymbolFields | ||
| 29 | { | ||
| 30 | ComponentRef, | ||
| 31 | File, | ||
| 32 | Description, | ||
| 33 | Group, | ||
| 34 | Attributes, | ||
| 35 | } | ||
| 36 | |||
| 37 | public class IIsWebServiceExtensionSymbol : IntermediateSymbol | ||
| 38 | { | ||
| 39 | public IIsWebServiceExtensionSymbol() : base(IisSymbolDefinitions.IIsWebServiceExtension, null, null) | ||
| 40 | { | ||
| 41 | } | ||
| 42 | |||
| 43 | public IIsWebServiceExtensionSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebServiceExtension, sourceLineNumber, id) | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | public IntermediateField this[IIsWebServiceExtensionSymbolFields index] => this.Fields[(int)index]; | ||
| 48 | |||
| 49 | public string ComponentRef | ||
| 50 | { | ||
| 51 | get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.ComponentRef].AsString(); | ||
| 52 | set => this.Set((int)IIsWebServiceExtensionSymbolFields.ComponentRef, value); | ||
| 53 | } | ||
| 54 | |||
| 55 | public string File | ||
| 56 | { | ||
| 57 | get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.File].AsString(); | ||
| 58 | set => this.Set((int)IIsWebServiceExtensionSymbolFields.File, value); | ||
| 59 | } | ||
| 60 | |||
| 61 | public string Description | ||
| 62 | { | ||
| 63 | get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.Description].AsString(); | ||
| 64 | set => this.Set((int)IIsWebServiceExtensionSymbolFields.Description, value); | ||
| 65 | } | ||
| 66 | |||
| 67 | public string Group | ||
| 68 | { | ||
| 69 | get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.Group].AsString(); | ||
| 70 | set => this.Set((int)IIsWebServiceExtensionSymbolFields.Group, value); | ||
| 71 | } | ||
| 72 | |||
| 73 | public int Attributes | ||
| 74 | { | ||
| 75 | get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.Attributes].AsNumber(); | ||
| 76 | set => this.Set((int)IIsWebServiceExtensionSymbolFields.Attributes, value); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebSiteCertificatesSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebSiteCertificatesSymbol.cs new file mode 100644 index 00000000..851ce556 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebSiteCertificatesSymbol.cs | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebSiteCertificates = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebSiteCertificates.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebSiteCertificatesSymbolFields.WebRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebSiteCertificatesSymbolFields.CertificateRef), IntermediateFieldType.String), | ||
| 16 | }, | ||
| 17 | typeof(IIsWebSiteCertificatesSymbol)); | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace WixToolset.Iis.Symbols | ||
| 22 | { | ||
| 23 | using WixToolset.Data; | ||
| 24 | |||
| 25 | public enum IIsWebSiteCertificatesSymbolFields | ||
| 26 | { | ||
| 27 | WebRef, | ||
| 28 | CertificateRef, | ||
| 29 | } | ||
| 30 | |||
| 31 | public class IIsWebSiteCertificatesSymbol : IntermediateSymbol | ||
| 32 | { | ||
| 33 | public IIsWebSiteCertificatesSymbol() : base(IisSymbolDefinitions.IIsWebSiteCertificates, null, null) | ||
| 34 | { | ||
| 35 | } | ||
| 36 | |||
| 37 | public IIsWebSiteCertificatesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebSiteCertificates, sourceLineNumber, id) | ||
| 38 | { | ||
| 39 | } | ||
| 40 | |||
| 41 | public IntermediateField this[IIsWebSiteCertificatesSymbolFields index] => this.Fields[(int)index]; | ||
| 42 | |||
| 43 | public string WebRef | ||
| 44 | { | ||
| 45 | get => this.Fields[(int)IIsWebSiteCertificatesSymbolFields.WebRef].AsString(); | ||
| 46 | set => this.Set((int)IIsWebSiteCertificatesSymbolFields.WebRef, value); | ||
| 47 | } | ||
| 48 | |||
| 49 | public string CertificateRef | ||
| 50 | { | ||
| 51 | get => this.Fields[(int)IIsWebSiteCertificatesSymbolFields.CertificateRef].AsString(); | ||
| 52 | set => this.Set((int)IIsWebSiteCertificatesSymbolFields.CertificateRef, value); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebSiteSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebSiteSymbol.cs new file mode 100644 index 00000000..ceba2ea0 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebSiteSymbol.cs | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebSite = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebSite.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.Description), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.ConnectionTimeout), IntermediateFieldType.Number), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.DirectoryRef), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.State), IntermediateFieldType.Number), | ||
| 19 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 20 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.KeyAddressRef), IntermediateFieldType.String), | ||
| 21 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.DirPropertiesRef), IntermediateFieldType.String), | ||
| 22 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.ApplicationRef), IntermediateFieldType.String), | ||
| 23 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.Sequence), IntermediateFieldType.Number), | ||
| 24 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.LogRef), IntermediateFieldType.String), | ||
| 25 | new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.WebsiteId), IntermediateFieldType.String), | ||
| 26 | }, | ||
| 27 | typeof(IIsWebSiteSymbol)); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | namespace WixToolset.Iis.Symbols | ||
| 32 | { | ||
| 33 | using WixToolset.Data; | ||
| 34 | |||
| 35 | public enum IIsWebSiteSymbolFields | ||
| 36 | { | ||
| 37 | ComponentRef, | ||
| 38 | Description, | ||
| 39 | ConnectionTimeout, | ||
| 40 | DirectoryRef, | ||
| 41 | State, | ||
| 42 | Attributes, | ||
| 43 | KeyAddressRef, | ||
| 44 | DirPropertiesRef, | ||
| 45 | ApplicationRef, | ||
| 46 | Sequence, | ||
| 47 | LogRef, | ||
| 48 | WebsiteId, | ||
| 49 | } | ||
| 50 | |||
| 51 | public class IIsWebSiteSymbol : IntermediateSymbol | ||
| 52 | { | ||
| 53 | public IIsWebSiteSymbol() : base(IisSymbolDefinitions.IIsWebSite, null, null) | ||
| 54 | { | ||
| 55 | } | ||
| 56 | |||
| 57 | public IIsWebSiteSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebSite, sourceLineNumber, id) | ||
| 58 | { | ||
| 59 | } | ||
| 60 | |||
| 61 | public IntermediateField this[IIsWebSiteSymbolFields index] => this.Fields[(int)index]; | ||
| 62 | |||
| 63 | public string ComponentRef | ||
| 64 | { | ||
| 65 | get => this.Fields[(int)IIsWebSiteSymbolFields.ComponentRef].AsString(); | ||
| 66 | set => this.Set((int)IIsWebSiteSymbolFields.ComponentRef, value); | ||
| 67 | } | ||
| 68 | |||
| 69 | public string Description | ||
| 70 | { | ||
| 71 | get => this.Fields[(int)IIsWebSiteSymbolFields.Description].AsString(); | ||
| 72 | set => this.Set((int)IIsWebSiteSymbolFields.Description, value); | ||
| 73 | } | ||
| 74 | |||
| 75 | public int? ConnectionTimeout | ||
| 76 | { | ||
| 77 | get => this.Fields[(int)IIsWebSiteSymbolFields.ConnectionTimeout].AsNullableNumber(); | ||
| 78 | set => this.Set((int)IIsWebSiteSymbolFields.ConnectionTimeout, value); | ||
| 79 | } | ||
| 80 | |||
| 81 | public string DirectoryRef | ||
| 82 | { | ||
| 83 | get => this.Fields[(int)IIsWebSiteSymbolFields.DirectoryRef].AsString(); | ||
| 84 | set => this.Set((int)IIsWebSiteSymbolFields.DirectoryRef, value); | ||
| 85 | } | ||
| 86 | |||
| 87 | public int? State | ||
| 88 | { | ||
| 89 | get => this.Fields[(int)IIsWebSiteSymbolFields.State].AsNullableNumber(); | ||
| 90 | set => this.Set((int)IIsWebSiteSymbolFields.State, value); | ||
| 91 | } | ||
| 92 | |||
| 93 | public int Attributes | ||
| 94 | { | ||
| 95 | get => this.Fields[(int)IIsWebSiteSymbolFields.Attributes].AsNumber(); | ||
| 96 | set => this.Set((int)IIsWebSiteSymbolFields.Attributes, value); | ||
| 97 | } | ||
| 98 | |||
| 99 | public string KeyAddressRef | ||
| 100 | { | ||
| 101 | get => this.Fields[(int)IIsWebSiteSymbolFields.KeyAddressRef].AsString(); | ||
| 102 | set => this.Set((int)IIsWebSiteSymbolFields.KeyAddressRef, value); | ||
| 103 | } | ||
| 104 | |||
| 105 | public string DirPropertiesRef | ||
| 106 | { | ||
| 107 | get => this.Fields[(int)IIsWebSiteSymbolFields.DirPropertiesRef].AsString(); | ||
| 108 | set => this.Set((int)IIsWebSiteSymbolFields.DirPropertiesRef, value); | ||
| 109 | } | ||
| 110 | |||
| 111 | public string ApplicationRef | ||
| 112 | { | ||
| 113 | get => this.Fields[(int)IIsWebSiteSymbolFields.ApplicationRef].AsString(); | ||
| 114 | set => this.Set((int)IIsWebSiteSymbolFields.ApplicationRef, value); | ||
| 115 | } | ||
| 116 | |||
| 117 | public int? Sequence | ||
| 118 | { | ||
| 119 | get => this.Fields[(int)IIsWebSiteSymbolFields.Sequence].AsNullableNumber(); | ||
| 120 | set => this.Set((int)IIsWebSiteSymbolFields.Sequence, value); | ||
| 121 | } | ||
| 122 | |||
| 123 | public string LogRef | ||
| 124 | { | ||
| 125 | get => this.Fields[(int)IIsWebSiteSymbolFields.LogRef].AsString(); | ||
| 126 | set => this.Set((int)IIsWebSiteSymbolFields.LogRef, value); | ||
| 127 | } | ||
| 128 | |||
| 129 | public string WebsiteId | ||
| 130 | { | ||
| 131 | get => this.Fields[(int)IIsWebSiteSymbolFields.WebsiteId].AsString(); | ||
| 132 | set => this.Set((int)IIsWebSiteSymbolFields.WebsiteId, value); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IIsWebVirtualDirSymbol.cs b/src/ext/Iis/wixext/Symbols/IIsWebVirtualDirSymbol.cs new file mode 100644 index 00000000..bfc29e84 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IIsWebVirtualDirSymbol.cs | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Iis.Symbols; | ||
| 7 | |||
| 8 | public static partial class IisSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition IIsWebVirtualDir = new IntermediateSymbolDefinition( | ||
| 11 | IisSymbolDefinitionType.IIsWebVirtualDir.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.WebRef), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.Alias), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.DirectoryRef), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.DirPropertiesRef), IntermediateFieldType.String), | ||
| 19 | new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.ApplicationRef), IntermediateFieldType.String), | ||
| 20 | }, | ||
| 21 | typeof(IIsWebVirtualDirSymbol)); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | namespace WixToolset.Iis.Symbols | ||
| 26 | { | ||
| 27 | using WixToolset.Data; | ||
| 28 | |||
| 29 | public enum IIsWebVirtualDirSymbolFields | ||
| 30 | { | ||
| 31 | ComponentRef, | ||
| 32 | WebRef, | ||
| 33 | Alias, | ||
| 34 | DirectoryRef, | ||
| 35 | DirPropertiesRef, | ||
| 36 | ApplicationRef, | ||
| 37 | } | ||
| 38 | |||
| 39 | public class IIsWebVirtualDirSymbol : IntermediateSymbol | ||
| 40 | { | ||
| 41 | public IIsWebVirtualDirSymbol() : base(IisSymbolDefinitions.IIsWebVirtualDir, null, null) | ||
| 42 | { | ||
| 43 | } | ||
| 44 | |||
| 45 | public IIsWebVirtualDirSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebVirtualDir, sourceLineNumber, id) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | public IntermediateField this[IIsWebVirtualDirSymbolFields index] => this.Fields[(int)index]; | ||
| 50 | |||
| 51 | public string ComponentRef | ||
| 52 | { | ||
| 53 | get => this.Fields[(int)IIsWebVirtualDirSymbolFields.ComponentRef].AsString(); | ||
| 54 | set => this.Set((int)IIsWebVirtualDirSymbolFields.ComponentRef, value); | ||
| 55 | } | ||
| 56 | |||
| 57 | public string WebRef | ||
| 58 | { | ||
| 59 | get => this.Fields[(int)IIsWebVirtualDirSymbolFields.WebRef].AsString(); | ||
| 60 | set => this.Set((int)IIsWebVirtualDirSymbolFields.WebRef, value); | ||
| 61 | } | ||
| 62 | |||
| 63 | public string Alias | ||
| 64 | { | ||
| 65 | get => this.Fields[(int)IIsWebVirtualDirSymbolFields.Alias].AsString(); | ||
| 66 | set => this.Set((int)IIsWebVirtualDirSymbolFields.Alias, value); | ||
| 67 | } | ||
| 68 | |||
| 69 | public string DirectoryRef | ||
| 70 | { | ||
| 71 | get => this.Fields[(int)IIsWebVirtualDirSymbolFields.DirectoryRef].AsString(); | ||
| 72 | set => this.Set((int)IIsWebVirtualDirSymbolFields.DirectoryRef, value); | ||
| 73 | } | ||
| 74 | |||
| 75 | public string DirPropertiesRef | ||
| 76 | { | ||
| 77 | get => this.Fields[(int)IIsWebVirtualDirSymbolFields.DirPropertiesRef].AsString(); | ||
| 78 | set => this.Set((int)IIsWebVirtualDirSymbolFields.DirPropertiesRef, value); | ||
| 79 | } | ||
| 80 | |||
| 81 | public string ApplicationRef | ||
| 82 | { | ||
| 83 | get => this.Fields[(int)IIsWebVirtualDirSymbolFields.ApplicationRef].AsString(); | ||
| 84 | set => this.Set((int)IIsWebVirtualDirSymbolFields.ApplicationRef, value); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | } \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixext/Symbols/IisSymbolDefinitions.cs b/src/ext/Iis/wixext/Symbols/IisSymbolDefinitions.cs new file mode 100644 index 00000000..d6ed80a2 --- /dev/null +++ b/src/ext/Iis/wixext/Symbols/IisSymbolDefinitions.cs | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Iis | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using WixToolset.Data; | ||
| 7 | |||
| 8 | public enum IisSymbolDefinitionType | ||
| 9 | { | ||
| 10 | Certificate, | ||
| 11 | CertificateHash, | ||
| 12 | IIsAppPool, | ||
| 13 | IIsFilter, | ||
| 14 | IIsHttpHeader, | ||
| 15 | IIsMimeMap, | ||
| 16 | IIsProperty, | ||
| 17 | IIsWebAddress, | ||
| 18 | IIsWebApplication, | ||
| 19 | IIsWebApplicationExtension, | ||
| 20 | IIsWebDir, | ||
| 21 | IIsWebDirProperties, | ||
| 22 | IIsWebError, | ||
| 23 | IIsWebLog, | ||
| 24 | IIsWebServiceExtension, | ||
| 25 | IIsWebSite, | ||
| 26 | IIsWebSiteCertificates, | ||
| 27 | IIsWebVirtualDir, | ||
| 28 | } | ||
| 29 | |||
| 30 | public static partial class IisSymbolDefinitions | ||
| 31 | { | ||
| 32 | public static readonly Version Version = new Version("4.0.0"); | ||
| 33 | |||
| 34 | public static IntermediateSymbolDefinition ByName(string name) | ||
| 35 | { | ||
| 36 | if (!Enum.TryParse(name, out IisSymbolDefinitionType type)) | ||
| 37 | { | ||
| 38 | return null; | ||
| 39 | } | ||
| 40 | |||
| 41 | return ByType(type); | ||
| 42 | } | ||
| 43 | |||
| 44 | public static IntermediateSymbolDefinition ByType(IisSymbolDefinitionType type) | ||
| 45 | { | ||
| 46 | switch (type) | ||
| 47 | { | ||
| 48 | case IisSymbolDefinitionType.Certificate: | ||
| 49 | return IisSymbolDefinitions.Certificate; | ||
| 50 | |||
| 51 | case IisSymbolDefinitionType.CertificateHash: | ||
| 52 | return IisSymbolDefinitions.CertificateHash; | ||
| 53 | |||
| 54 | case IisSymbolDefinitionType.IIsAppPool: | ||
| 55 | return IisSymbolDefinitions.IIsAppPool; | ||
| 56 | |||
| 57 | case IisSymbolDefinitionType.IIsFilter: | ||
| 58 | return IisSymbolDefinitions.IIsFilter; | ||
| 59 | |||
| 60 | case IisSymbolDefinitionType.IIsHttpHeader: | ||
| 61 | return IisSymbolDefinitions.IIsHttpHeader; | ||
| 62 | |||
| 63 | case IisSymbolDefinitionType.IIsMimeMap: | ||
| 64 | return IisSymbolDefinitions.IIsMimeMap; | ||
| 65 | |||
| 66 | case IisSymbolDefinitionType.IIsProperty: | ||
| 67 | return IisSymbolDefinitions.IIsProperty; | ||
| 68 | |||
| 69 | case IisSymbolDefinitionType.IIsWebAddress: | ||
| 70 | return IisSymbolDefinitions.IIsWebAddress; | ||
| 71 | |||
| 72 | case IisSymbolDefinitionType.IIsWebApplication: | ||
| 73 | return IisSymbolDefinitions.IIsWebApplication; | ||
| 74 | |||
| 75 | case IisSymbolDefinitionType.IIsWebApplicationExtension: | ||
| 76 | return IisSymbolDefinitions.IIsWebApplicationExtension; | ||
| 77 | |||
| 78 | case IisSymbolDefinitionType.IIsWebDir: | ||
| 79 | return IisSymbolDefinitions.IIsWebDir; | ||
| 80 | |||
| 81 | case IisSymbolDefinitionType.IIsWebDirProperties: | ||
| 82 | return IisSymbolDefinitions.IIsWebDirProperties; | ||
| 83 | |||
| 84 | case IisSymbolDefinitionType.IIsWebError: | ||
| 85 | return IisSymbolDefinitions.IIsWebError; | ||
| 86 | |||
| 87 | case IisSymbolDefinitionType.IIsWebLog: | ||
| 88 | return IisSymbolDefinitions.IIsWebLog; | ||
| 89 | |||
| 90 | case IisSymbolDefinitionType.IIsWebServiceExtension: | ||
| 91 | return IisSymbolDefinitions.IIsWebServiceExtension; | ||
| 92 | |||
| 93 | case IisSymbolDefinitionType.IIsWebSite: | ||
| 94 | return IisSymbolDefinitions.IIsWebSite; | ||
| 95 | |||
| 96 | case IisSymbolDefinitionType.IIsWebSiteCertificates: | ||
| 97 | return IisSymbolDefinitions.IIsWebSiteCertificates; | ||
| 98 | |||
| 99 | case IisSymbolDefinitionType.IIsWebVirtualDir: | ||
| 100 | return IisSymbolDefinitions.IIsWebVirtualDir; | ||
| 101 | |||
| 102 | default: | ||
| 103 | throw new ArgumentOutOfRangeException(nameof(type)); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | } | ||
| 107 | } | ||
diff --git a/src/ext/Iis/wixext/WixToolset.Iis.wixext.csproj b/src/ext/Iis/wixext/WixToolset.Iis.wixext.csproj new file mode 100644 index 00000000..81d41e77 --- /dev/null +++ b/src/ext/Iis/wixext/WixToolset.Iis.wixext.csproj | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | <Project Sdk="Microsoft.NET.Sdk"> | ||
| 5 | <PropertyGroup> | ||
| 6 | <TargetFramework>netstandard2.0</TargetFramework> | ||
| 7 | <RootNamespace>WixToolset.Iis</RootNamespace> | ||
| 8 | <Description>WiX Toolset Iis Extension</Description> | ||
| 9 | <Title>WiX Toolset Iis Extension</Title> | ||
| 10 | <IsTool>true</IsTool> | ||
| 11 | <ContentTargetFolders>build</ContentTargetFolders> | ||
| 12 | </PropertyGroup> | ||
| 13 | |||
| 14 | <ItemGroup> | ||
| 15 | <Content Include="$(MSBuildThisFileName).targets" /> | ||
| 16 | <EmbeddedResource Include="$(OutputPath)..\iis.wixlib" /> | ||
| 17 | </ItemGroup> | ||
| 18 | |||
| 19 | <ItemGroup> | ||
| 20 | <PackageReference Include="WixToolset.Data" Version="4.0.*" PrivateAssets="all" /> | ||
| 21 | <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" PrivateAssets="all" /> | ||
| 22 | </ItemGroup> | ||
| 23 | |||
| 24 | <ItemGroup> | ||
| 25 | <ProjectReference Include="..\wixlib\iis.wixproj" ReferenceOutputAssembly="false" Condition=" '$(NCrunch)'=='' " /> | ||
| 26 | </ItemGroup> | ||
| 27 | |||
| 28 | <ItemGroup> | ||
| 29 | <PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="all" /> | ||
| 30 | </ItemGroup> | ||
| 31 | </Project> | ||
diff --git a/src/ext/Iis/wixext/WixToolset.Iis.wixext.targets b/src/ext/Iis/wixext/WixToolset.Iis.wixext.targets new file mode 100644 index 00000000..6398fce1 --- /dev/null +++ b/src/ext/Iis/wixext/WixToolset.Iis.wixext.targets | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | ||
| 5 | <PropertyGroup> | ||
| 6 | <WixToolsetIisWixextPath Condition=" '$(WixToolsetIisWixextPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\WixToolset.Iis.wixext.dll</WixToolsetIisWixextPath> | ||
| 7 | </PropertyGroup> | ||
| 8 | <ItemGroup> | ||
| 9 | <WixExtension Include="$(WixToolsetIisWixextPath)" /> | ||
| 10 | </ItemGroup> | ||
| 11 | </Project> | ||
diff --git a/src/ext/Iis/wixlib/IIsExtension.wxs b/src/ext/Iis/wixlib/IIsExtension.wxs new file mode 100644 index 00000000..18fc34ff --- /dev/null +++ b/src/ext/Iis/wixlib/IIsExtension.wxs | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?include caerr.wxi ?> | ||
| 6 | |||
| 7 | <Fragment> | ||
| 8 | <Property Id="IISMAJORVERSION"> | ||
| 9 | <RegistrySearch Id="IIsMajorVersionSearch" Root="HKLM" Key="SOFTWARE\Microsoft\InetStp" Name="MajorVersion" Type="raw" /> | ||
| 10 | </Property> | ||
| 11 | |||
| 12 | <Property Id="IISMINORVERSION"> | ||
| 13 | <RegistrySearch Id="IIsMinorVersionSearch" Root="HKLM" Key="SOFTWARE\Microsoft\InetStp" Name="MinorVersion" Type="raw" /> | ||
| 14 | </Property> | ||
| 15 | </Fragment> | ||
| 16 | |||
| 17 | <Fragment> | ||
| 18 | <UI Id="WixIIsErrors"> | ||
| 19 | <Error Id="$(var.msierrIISCannotConnect)" Message="!(loc.msierrIISCannotConnect)" /> | ||
| 20 | <Error Id="$(var.msierrIISFailedReadWebSite)" Message="!(loc.msierrIISFailedReadWebSite)" /> | ||
| 21 | <Error Id="$(var.msierrIISFailedReadWebDirs)" Message="!(loc.msierrIISFailedReadWebDirs)" /> | ||
| 22 | <Error Id="$(var.msierrIISFailedReadVDirs)" Message="!(loc.msierrIISFailedReadVDirs)" /> | ||
| 23 | <Error Id="$(var.msierrIISFailedReadFilters)" Message="!(loc.msierrIISFailedReadFilters)" /> | ||
| 24 | <Error Id="$(var.msierrIISFailedReadMimeMap)" Message="!(loc.msierrIISFailedReadMimeMap)" /> | ||
| 25 | <Error Id="$(var.msierrIISFailedReadAppPool)" Message="!(loc.msierrIISFailedReadAppPool)" /> | ||
| 26 | <Error Id="$(var.msierrIISFailedReadProp)" Message="!(loc.msierrIISFailedReadProp)" /> | ||
| 27 | <Error Id="$(var.msierrIISFailedReadWebSvcExt)" Message="!(loc.msierrIISFailedReadWebSvcExt)" /> | ||
| 28 | <Error Id="$(var.msierrIISFailedReadWebError)" Message="!(loc.msierrIISFailedReadWebError)" /> | ||
| 29 | <Error Id="$(var.msierrIISFailedReadHttpHeader)" Message="!(loc.msierrIISFailedReadHttpHeader)" /> | ||
| 30 | |||
| 31 | <Error Id="$(var.msierrIISFailedSchedTransaction)" Message="!(loc.msierrIISFailedSchedTransaction)" /> | ||
| 32 | <Error Id="$(var.msierrIISFailedSchedInstallWebs)" Message="!(loc.msierrIISFailedSchedInstallWebs)" /> | ||
| 33 | <Error Id="$(var.msierrIISFailedSchedInstallWebDirs)" Message="!(loc.msierrIISFailedSchedInstallWebDirs)" /> | ||
| 34 | <Error Id="$(var.msierrIISFailedSchedInstallVDirs)" Message="!(loc.msierrIISFailedSchedInstallVDirs)" /> | ||
| 35 | <Error Id="$(var.msierrIISFailedSchedInstallFilters)" Message="!(loc.msierrIISFailedSchedInstallFilters)" /> | ||
| 36 | <Error Id="$(var.msierrIISFailedSchedInstallAppPool)" Message="!(loc.msierrIISFailedSchedInstallAppPool)" /> | ||
| 37 | <Error Id="$(var.msierrIISFailedSchedInstallProp)" Message="!(loc.msierrIISFailedSchedInstallProp)" /> | ||
| 38 | <Error Id="$(var.msierrIISFailedSchedInstallWebSvcExt)" Message="!(loc.msierrIISFailedSchedInstallWebSvcExt)" /> | ||
| 39 | |||
| 40 | <Error Id="$(var.msierrIISFailedSchedUninstallWebs)" Message="!(loc.msierrIISFailedSchedUninstallWebs)" /> | ||
| 41 | <Error Id="$(var.msierrIISFailedSchedUninstallWebDirs)" Message="!(loc.msierrIISFailedSchedUninstallWebDirs)" /> | ||
| 42 | <Error Id="$(var.msierrIISFailedSchedUninstallVDirs)" Message="!(loc.msierrIISFailedSchedUninstallVDirs)" /> | ||
| 43 | <Error Id="$(var.msierrIISFailedSchedUninstallFilters)" Message="!(loc.msierrIISFailedSchedUninstallFilters)" /> | ||
| 44 | <Error Id="$(var.msierrIISFailedSchedUninstallAppPool)" Message="!(loc.msierrIISFailedSchedUninstallAppPool)" /> | ||
| 45 | <Error Id="$(var.msierrIISFailedSchedUninstallProp)" Message="!(loc.msierrIISFailedSchedUninstallProp)" /> | ||
| 46 | <Error Id="$(var.msierrIISFailedSchedUninstallWebSvcExt)" Message="!(loc.msierrIISFailedSchedUninstallWebSvcExt)" /> | ||
| 47 | |||
| 48 | <Error Id="$(var.msierrIISFailedStartTransaction)" Message="!(loc.msierrIISFailedStartTransaction)" /> | ||
| 49 | <Error Id="$(var.msierrIISFailedOpenKey)" Message="!(loc.msierrIISFailedOpenKey)" /> | ||
| 50 | <Error Id="$(var.msierrIISFailedCreateKey)" Message="!(loc.msierrIISFailedCreateKey)" /> | ||
| 51 | <Error Id="$(var.msierrIISFailedWriteData)" Message="!(loc.msierrIISFailedWriteData)" /> | ||
| 52 | <Error Id="$(var.msierrIISFailedCreateApp)" Message="!(loc.msierrIISFailedCreateApp)" /> | ||
| 53 | <Error Id="$(var.msierrIISFailedDeleteKey)" Message="!(loc.msierrIISFailedDeleteKey)" /> | ||
| 54 | <Error Id="$(var.msierrIISFailedDeleteValue)" Message="!(loc.msierrIISFailedDeleteValue)" /> | ||
| 55 | <Error Id="$(var.msierrIISFailedCommitInUse)" Message="!(loc.msierrIISFailedCommitInUse)" /> | ||
| 56 | </UI> | ||
| 57 | </Fragment> | ||
| 58 | </Wix> | ||
diff --git a/src/ext/Iis/wixlib/IIsExtension_Platform.wxi b/src/ext/Iis/wixlib/IIsExtension_Platform.wxi new file mode 100644 index 00000000..09562a69 --- /dev/null +++ b/src/ext/Iis/wixlib/IIsExtension_Platform.wxi | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Include xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?include caDecor.wxi ?> | ||
| 6 | |||
| 7 | <Fragment> | ||
| 8 | <UIRef Id="WixIIsErrors" /> | ||
| 9 | <UI> | ||
| 10 | <ProgressText Action="$(var.Prefix)ConfigureIIs$(var.Suffix)" Message="!(loc.ConfigureIIs)" /> | ||
| 11 | <ProgressText Action="$(var.Prefix)ConfigureIIsExec$(var.Suffix)" Message="!(loc.ConfigureIIsExec)" /> | ||
| 12 | <ProgressText Action="$(var.Prefix)StartMetabaseTransaction$(var.Suffix)" Message="!(loc.StartMetabaseTransaction)" /> | ||
| 13 | <ProgressText Action="$(var.Prefix)RollbackMetabaseTransaction$(var.Suffix)" Message="!(loc.RollbackMetabaseTransaction)" /> | ||
| 14 | <ProgressText Action="$(var.Prefix)CommitMetabaseTransaction$(var.Suffix)" Message="!(loc.CommitMetabaseTransaction)" /> | ||
| 15 | <ProgressText Action="$(var.Prefix)WriteMetabaseChanges$(var.Suffix)" Message="!(loc.WriteMetabaseChanges)" /> | ||
| 16 | |||
| 17 | <ProgressText Action="$(var.Prefix)ConfigureIIs7Exec$(var.Suffix)" Message="!(loc.ConfigureIIs7Exec)" /> | ||
| 18 | <ProgressText Action="$(var.Prefix)StartIIS7ConfigTransaction$(var.Suffix)" Message="!(loc.StartIIS7ConfigTransaction)" /> | ||
| 19 | <ProgressText Action="$(var.Prefix)RollbackIIS7ConfigTransaction$(var.Suffix)" Message="!(loc.RollbackIIS7ConfigTransaction)" /> | ||
| 20 | <ProgressText Action="$(var.Prefix)CommitIIS7ConfigTransaction$(var.Suffix)" Message="!(loc.CommitIIS7ConfigTransaction)" /> | ||
| 21 | <ProgressText Action="$(var.Prefix)WriteIIS7ConfigChanges$(var.Suffix)" Message="!(loc.WriteIIS7ConfigChanges)" /> | ||
| 22 | </UI> | ||
| 23 | |||
| 24 | <CustomAction Id="$(var.Prefix)ConfigureIIs$(var.Suffix)" DllEntry="ConfigureIIs" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 25 | <CustomAction Id="$(var.Prefix)ConfigureIIsExec$(var.Suffix)" DllEntry="ConfigureIIsExec" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 26 | <CustomAction Id="$(var.Prefix)StartMetabaseTransaction$(var.Suffix)" DllEntry="StartMetabaseTransaction" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 27 | <CustomAction Id="$(var.Prefix)RollbackMetabaseTransaction$(var.Suffix)" DllEntry="RollbackMetabaseTransaction" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 28 | <CustomAction Id="$(var.Prefix)CommitMetabaseTransaction$(var.Suffix)" DllEntry="CommitMetabaseTransaction" Impersonate="no" Execute="commit" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 29 | <CustomAction Id="$(var.Prefix)WriteMetabaseChanges$(var.Suffix)" DllEntry="WriteMetabaseChanges" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 30 | |||
| 31 | <CustomAction Id="$(var.Prefix)ConfigureIIs7Exec$(var.Suffix)" DllEntry="ConfigureIIs7Exec" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 32 | <CustomAction Id="$(var.Prefix)StartIIS7ConfigTransaction$(var.Suffix)" DllEntry="StartIIS7ConfigTransaction" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 33 | <CustomAction Id="$(var.Prefix)RollbackIIS7ConfigTransaction$(var.Suffix)" DllEntry="RollbackIIS7ConfigTransaction" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 34 | <CustomAction Id="$(var.Prefix)CommitIIS7ConfigTransaction$(var.Suffix)" DllEntry="CommitIIS7ConfigTransaction" Impersonate="no" Execute="commit" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 35 | <CustomAction Id="$(var.Prefix)WriteIIS7ConfigChanges$(var.Suffix)" DllEntry="WriteIIS7ConfigChanges" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 36 | |||
| 37 | <InstallExecuteSequence> | ||
| 38 | <Custom Action="$(var.Prefix)ConfigureIIs$(var.Suffix)" Before="RegisterUser" Overridable="yes" Condition="NOT SKIPCONFIGUREIIS AND VersionNT > 400" /> | ||
| 39 | </InstallExecuteSequence> | ||
| 40 | </Fragment> | ||
| 41 | |||
| 42 | <Fragment> | ||
| 43 | <Binary Id="IisCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))iisca.dll" /> | ||
| 44 | </Fragment> | ||
| 45 | |||
| 46 | <Fragment> | ||
| 47 | <CustomAction Id="$(var.Prefix)InstallCertificates$(var.Suffix)" DllEntry="InstallCertificates" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 48 | <CustomAction Id="$(var.Prefix)UninstallCertificates$(var.Suffix)" DllEntry="UninstallCertificates" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 49 | |||
| 50 | <CustomAction Id="$(var.Prefix)AddUserCertificate$(var.Suffix)" DllEntry="AddUserCertificate" Impersonate="yes" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" TerminalServerAware="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 51 | <CustomAction Id="$(var.Prefix)AddMachineCertificate$(var.Suffix)" DllEntry="AddMachineCertificate" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 52 | <CustomAction Id="$(var.Prefix)DeleteUserCertificate$(var.Suffix)" DllEntry="DeleteUserCertificate" Impersonate="yes" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" TerminalServerAware="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 53 | <CustomAction Id="$(var.Prefix)DeleteMachineCertificate$(var.Suffix)" DllEntry="DeleteMachineCertificate" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 54 | |||
| 55 | <CustomAction Id="$(var.Prefix)RollbackAddUserCertificate$(var.Suffix)" DllEntry="DeleteUserCertificate" Impersonate="yes" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" TerminalServerAware="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 56 | <CustomAction Id="$(var.Prefix)RollbackAddMachineCertificate$(var.Suffix)" DllEntry="DeleteMachineCertificate" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 57 | <CustomAction Id="$(var.Prefix)RollbackDeleteUserCertificate$(var.Suffix)" DllEntry="AddUserCertificate" Impersonate="yes" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" TerminalServerAware="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 58 | <CustomAction Id="$(var.Prefix)RollbackDeleteMachineCertificate$(var.Suffix)" DllEntry="AddMachineCertificate" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" /> | ||
| 59 | |||
| 60 | <InstallExecuteSequence> | ||
| 61 | <Custom Action="UninstallCertificates$(var.Suffix)" Before="RemoveFiles" Overridable="yes" Condition="VersionNT > 400" /> | ||
| 62 | <Custom Action="InstallCertificates$(var.Suffix)" After="InstallFiles" Overridable="yes" Condition="VersionNT > 400" /> | ||
| 63 | </InstallExecuteSequence> | ||
| 64 | </Fragment> | ||
| 65 | |||
| 66 | </Include> | ||
diff --git a/src/ext/Iis/wixlib/IIsExtension_arm64.wxs b/src/ext/Iis/wixlib/IIsExtension_arm64.wxs new file mode 100644 index 00000000..39ac048f --- /dev/null +++ b/src/ext/Iis/wixlib/IIsExtension_arm64.wxs | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?define platform=arm64 ?> | ||
| 6 | <?include IIsExtension_Platform.wxi ?> | ||
| 7 | </Wix> | ||
diff --git a/src/ext/Iis/wixlib/IIsExtension_x64.wxs b/src/ext/Iis/wixlib/IIsExtension_x64.wxs new file mode 100644 index 00000000..553953b3 --- /dev/null +++ b/src/ext/Iis/wixlib/IIsExtension_x64.wxs | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?define platform=x64 ?> | ||
| 6 | <?include IIsExtension_Platform.wxi ?> | ||
| 7 | </Wix> | ||
diff --git a/src/ext/Iis/wixlib/IIsExtension_x86.wxs b/src/ext/Iis/wixlib/IIsExtension_x86.wxs new file mode 100644 index 00000000..c99a243b --- /dev/null +++ b/src/ext/Iis/wixlib/IIsExtension_x86.wxs | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?define platform=x86 ?> | ||
| 6 | <?include IIsExtension_Platform.wxi ?> | ||
| 7 | </Wix> | ||
diff --git a/src/ext/Iis/wixlib/caDecor.wxi b/src/ext/Iis/wixlib/caDecor.wxi new file mode 100644 index 00000000..b1711518 --- /dev/null +++ b/src/ext/Iis/wixlib/caDecor.wxi | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Include xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?ifdef Prefix ?> | ||
| 6 | <?undef Prefix ?> | ||
| 7 | <?endif?> | ||
| 8 | |||
| 9 | <?define Prefix="Wix4" ?> | ||
| 10 | |||
| 11 | <?ifndef platform ?> | ||
| 12 | <?define platform="x86" ?> | ||
| 13 | <?endif?> | ||
| 14 | |||
| 15 | <?if $(var.platform)="" ?> | ||
| 16 | <?undef platform ?> | ||
| 17 | <?define platform="x86" ?> | ||
| 18 | <?endif?> | ||
| 19 | |||
| 20 | <?ifdef Suffix ?> | ||
| 21 | <?undef Suffix ?> | ||
| 22 | <?endif?> | ||
| 23 | |||
| 24 | <?if $(var.platform)~="x86" ?> | ||
| 25 | <?define Suffix="_X86" ?> | ||
| 26 | <?endif?> | ||
| 27 | |||
| 28 | <?if $(var.platform)~="x64" ?> | ||
| 29 | <?define Suffix="_X64" ?> | ||
| 30 | <?endif?> | ||
| 31 | |||
| 32 | <?if $(var.platform)~="arm" ?> | ||
| 33 | <?define Suffix="_A32" ?> | ||
| 34 | <?endif?> | ||
| 35 | |||
| 36 | <?if $(var.platform)~="arm64" ?> | ||
| 37 | <?define Suffix="_A64" ?> | ||
| 38 | <?endif?> | ||
| 39 | </Include> | ||
diff --git a/src/ext/Iis/wixlib/caerr.wxi b/src/ext/Iis/wixlib/caerr.wxi new file mode 100644 index 00000000..ff7ec121 --- /dev/null +++ b/src/ext/Iis/wixlib/caerr.wxi | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | <Include xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 2 | <?define msierrSecureObjectsFailedCreateSD = 25520?> | ||
| 3 | <?define msierrSecureObjectsFailedSet = 25521?> | ||
| 4 | <?define msierrSecureObjectsUnknownType = 25522?> | ||
| 5 | <?define msierrXmlFileFailedRead = 25530?> | ||
| 6 | <?define msierrXmlFileFailedOpen = 25531?> | ||
| 7 | <?define msierrXmlFileFailedSelect = 25532?> | ||
| 8 | <?define msierrXmlFileFailedSave = 25533?> | ||
| 9 | <?define msierrXmlConfigFailedRead = 25540?> | ||
| 10 | <?define msierrXmlConfigFailedOpen = 25541?> | ||
| 11 | <?define msierrXmlConfigFailedSelect = 25542?> | ||
| 12 | <?define msierrXmlConfigFailedSave = 25543?> | ||
| 13 | <?define msierrFirewallCannotConnect = 25580?> | ||
| 14 | <?define msierrIISCannotConnect = 26001?> | ||
| 15 | <?define msierrIISFailedReadWebSite = 26002?> | ||
| 16 | <?define msierrIISFailedReadWebDirs = 26003?> | ||
| 17 | <?define msierrIISFailedReadVDirs = 26004?> | ||
| 18 | <?define msierrIISFailedReadFilters = 26005?> | ||
| 19 | <?define msierrIISFailedReadAppPool = 26006?> | ||
| 20 | <?define msierrIISFailedReadMimeMap = 26007?> | ||
| 21 | <?define msierrIISFailedReadProp = 26008?> | ||
| 22 | <?define msierrIISFailedReadWebSvcExt = 26009?> | ||
| 23 | <?define msierrIISFailedReadWebError = 26010?> | ||
| 24 | <?define msierrIISFailedReadHttpHeader = 26011?> | ||
| 25 | <?define msierrIISFailedSchedTransaction = 26031?> | ||
| 26 | <?define msierrIISFailedSchedInstallWebs = 26032?> | ||
| 27 | <?define msierrIISFailedSchedInstallWebDirs = 26033?> | ||
| 28 | <?define msierrIISFailedSchedInstallVDirs = 26034?> | ||
| 29 | <?define msierrIISFailedSchedInstallFilters = 26035?> | ||
| 30 | <?define msierrIISFailedSchedInstallAppPool = 26036?> | ||
| 31 | <?define msierrIISFailedSchedInstallProp = 26037?> | ||
| 32 | <?define msierrIISFailedSchedInstallWebSvcExt = 26038?> | ||
| 33 | <?define msierrIISFailedSchedUninstallWebs = 26051?> | ||
| 34 | <?define msierrIISFailedSchedUninstallWebDirs = 26052?> | ||
| 35 | <?define msierrIISFailedSchedUninstallVDirs = 26053?> | ||
| 36 | <?define msierrIISFailedSchedUninstallFilters = 26054?> | ||
| 37 | <?define msierrIISFailedSchedUninstallAppPool = 26055?> | ||
| 38 | <?define msierrIISFailedSchedUninstallProp = 26056?> | ||
| 39 | <?define msierrIISFailedSchedUninstallWebSvcExt = 26057?> | ||
| 40 | <?define msierrIISFailedStartTransaction = 26101?> | ||
| 41 | <?define msierrIISFailedOpenKey = 26102?> | ||
| 42 | <?define msierrIISFailedCreateKey = 26103?> | ||
| 43 | <?define msierrIISFailedWriteData = 26104?> | ||
| 44 | <?define msierrIISFailedCreateApp = 26105?> | ||
| 45 | <?define msierrIISFailedDeleteKey = 26106?> | ||
| 46 | <?define msierrIISFailedDeleteApp = 26107?> | ||
| 47 | <?define msierrIISFailedDeleteValue = 26108?> | ||
| 48 | <?define msierrIISFailedCommitInUse = 26109?> | ||
| 49 | <?define msierrSQLFailedCreateDatabase = 26201?> | ||
| 50 | <?define msierrSQLFailedDropDatabase = 26202?> | ||
| 51 | <?define msierrSQLFailedConnectDatabase = 26203?> | ||
| 52 | <?define msierrSQLFailedExecString = 26204?> | ||
| 53 | <?define msierrSQLDatabaseAlreadyExists = 26205?> | ||
| 54 | <?define msierrPERFMONFailedRegisterDLL = 26251?> | ||
| 55 | <?define msierrPERFMONFailedUnregisterDLL = 26252?> | ||
| 56 | <?define msierrInstallPerfCounterData = 26253?> | ||
| 57 | <?define msierrUninstallPerfCounterData = 26254?> | ||
| 58 | <?define msierrSMBFailedCreate = 26301?> | ||
| 59 | <?define msierrSMBFailedDrop = 26302?> | ||
| 60 | <?define msierrCERTFailedOpen = 26351?> | ||
| 61 | <?define msierrCERTFailedAdd = 26352?> | ||
| 62 | <?define msierrUSRFailedUserCreate = 26401?> | ||
| 63 | <?define msierrUSRFailedUserCreatePswd = 26402?> | ||
| 64 | <?define msierrUSRFailedUserGroupAdd = 26403?> | ||
| 65 | <?define msierrUSRFailedUserCreateExists = 26404?> | ||
| 66 | <?define msierrUSRFailedGrantLogonAsService = 26405?> | ||
| 67 | <?define msierrDependencyMissingDependencies = 26451?> | ||
| 68 | <?define msierrDependencyHasDependents = 26452?> | ||
| 69 | <?define msierrDotNetRuntimeRequired = 27000?> | ||
| 70 | <?define msierrComPlusCannotConnect = 28001?> | ||
| 71 | <?define msierrComPlusPartitionReadFailed = 28002?> | ||
| 72 | <?define msierrComPlusPartitionRoleReadFailed = 28003?> | ||
| 73 | <?define msierrComPlusUserInPartitionRoleReadFailed = 28004?> | ||
| 74 | <?define msierrComPlusPartitionUserReadFailed = 28005?> | ||
| 75 | <?define msierrComPlusApplicationReadFailed = 28006?> | ||
| 76 | <?define msierrComPlusApplicationRoleReadFailed = 28007?> | ||
| 77 | <?define msierrComPlusUserInApplicationRoleReadFailed = 28008?> | ||
| 78 | <?define msierrComPlusAssembliesReadFailed = 28009?> | ||
| 79 | <?define msierrComPlusSubscriptionReadFailed = 28010?> | ||
| 80 | <?define msierrComPlusPartitionDependency = 28011?> | ||
| 81 | <?define msierrComPlusPartitionNotFound = 28012?> | ||
| 82 | <?define msierrComPlusPartitionIdConflict = 28013?> | ||
| 83 | <?define msierrComPlusPartitionNameConflict = 28014?> | ||
| 84 | <?define msierrComPlusApplicationDependency = 28015?> | ||
| 85 | <?define msierrComPlusApplicationNotFound = 28016?> | ||
| 86 | <?define msierrComPlusApplicationIdConflict = 28017?> | ||
| 87 | <?define msierrComPlusApplicationNameConflict = 28018?> | ||
| 88 | <?define msierrComPlusApplicationRoleDependency = 28019?> | ||
| 89 | <?define msierrComPlusApplicationRoleNotFound = 28020?> | ||
| 90 | <?define msierrComPlusApplicationRoleConflict = 28021?> | ||
| 91 | <?define msierrComPlusAssemblyDependency = 28022?> | ||
| 92 | <?define msierrComPlusSubscriptionIdConflict = 28023?> | ||
| 93 | <?define msierrComPlusSubscriptionNameConflict = 28024?> | ||
| 94 | <?define msierrComPlusFailedLookupNames = 28025?> | ||
| 95 | <?define msierrMsmqCannotConnect = 28101?> | ||
| 96 | </Include> \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixlib/de-de.wxl b/src/ext/Iis/wixlib/de-de.wxl new file mode 100644 index 00000000..5929f258 --- /dev/null +++ b/src/ext/Iis/wixlib/de-de.wxl | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="de-de" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrIISCannotConnect" Overridable="yes">Konnte keine Verbindung mit dem Internet Information Server herstellen. ([2] [3] [4] [5])</String> | ||
| 6 | <String Id="msierrIISFailedReadWebSite" Overridable="yes">Fehler bei der Verarbeitung der WebSites. ([2] [3] [4] [5])</String> | ||
| 7 | <String Id="msierrIISFailedReadWebDirs" Overridable="yes">Fehler bei der Verarbeitung der WebDirs. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrIISFailedReadVDirs" Overridable="yes">Fehler bei der Verarbeitung der WebVirtualDirs. ([2] [3] [4] [5])</String> | ||
| 9 | <String Id="msierrIISFailedReadFilters" Overridable="yes">Fehler bei der Verarbeitung der WebFilters. ([2] [3] [4] [5])</String> | ||
| 10 | <String Id="msierrIISFailedReadMimeMap" Overridable="yes">Fehler bei der Verarbeitung der MimeMaps. ([2] [3] [4] [5])</String> | ||
| 11 | <String Id="msierrIISFailedReadAppPool" Overridable="yes">Fehler bei der Verarbeitung der WebAppPools. ([2] [3] [4] [5])</String> | ||
| 12 | <String Id="msierrIISFailedReadProp" Overridable="yes">Fehler bei der Verarbeitung der WebProperties. ([2] [3] [4] [5])</String> | ||
| 13 | <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">Fehler bei der Verarbeitung der WebServiceExtensions. ([2] [3] [4] [5])</String> | ||
| 14 | <String Id="msierrIISFailedReadWebError" Overridable="yes">Fehler bei der Verarbeitung der WebErrors. ([2] [3] [4] [5])</String> | ||
| 15 | <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">Fehler bei der Verarbeitung der HttpHeader. ([2] [3] [4] [5])</String> | ||
| 16 | |||
| 17 | <String Id="msierrIISFailedSchedTransaction" Overridable="yes">Die Transaktion für Änderungen am IIS konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 18 | <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">Die Installation von IIS-Websites konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 19 | <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">Die Installation von IIS Web Directories konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 20 | <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">Die Installation von IIS Virtual Directories konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 21 | <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">Die Installation von IIS Filters konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 22 | <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">Die Installation von IIS AppPools konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 23 | <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">Die Installation von IIS Properties konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 24 | <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">Die Installation von IIS Web Service Extensions konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 25 | |||
| 26 | <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">Die Deinstallation von IIS Web Sites konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 27 | <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">Die Deinstallation von IIS Web Directories konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 28 | <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">Die Deinstallation von IIS Virtual Directories konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 29 | <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">Die Deinstallation von IIS Filters konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 30 | <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">Die Deinstallation von IIS AppPools konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 31 | <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">Die Deinstallation der IIS Properties konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 32 | <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">Die Deinstallation von IIS Web Service Extensions konnte nicht geschedulded werden. ([2] [3] [4] [5])</String> | ||
| 33 | |||
| 34 | <String Id="msierrIISFailedStartTransaction" Overridable="yes">Die IIS-Transaktion konnte nicht gestartet werden. ([2] [3] [4] [5])</String> | ||
| 35 | <String Id="msierrIISFailedOpenKey" Overridable="yes">Der Metabase Key konnte nicht geöffnet werden. ([2] [3] [4] [5])</String> | ||
| 36 | <String Id="msierrIISFailedCreateKey" Overridable="yes">Der Metabase Key konnte nicht erstellt werden. ([2] [3] [4] [5])</String> | ||
| 37 | <String Id="msierrIISFailedWriteData" Overridable="yes">Daten konnten nicht in den Metabase Key geschrieben werden. ([2] [3] [4] [5])</String> | ||
| 38 | <String Id="msierrIISFailedCreateApp" Overridable="yes">Webanwendung konnte nicht erstellt werden. ([2] [3] [4] [5])</String> | ||
| 39 | <String Id="msierrIISFailedDeleteKey" Overridable="yes">Der Metabase Key konnte nicht gelöscht werden. ([2] [3] [4] [5])</String> | ||
| 40 | <String Id="msierrIISFailedDeleteValue" Overridable="yes">Der Metabase Value konnte nicht gelöscht werden. ([2] [3] [4] [5])</String> | ||
| 41 | <String Id="msierrIISFailedCommitInUse" Overridable="yes">Die IIS Transaktion konnte aufgrund einer Freigabeverletzung nicht committed werden. Möglicherweise konfiguriert eine andere Anwendung derzeit IIS.</String> | ||
| 42 | |||
| 43 | <String Id="ConfigureIIs" Overridable="yes">Konfiguriere IIS</String> | ||
| 44 | <String Id="ConfigureIIsExec" Overridable="yes">Führe IIS Konfiguration aus</String> | ||
| 45 | <String Id="StartMetabaseTransaction" Overridable="yes">Starte IIS Metabase Transaktion</String> | ||
| 46 | <String Id="RollbackMetabaseTransaction" Overridable="yes">Mache IIS Metabase Transaktion rückgängig</String> | ||
| 47 | <String Id="CommitMetabaseTransaction" Overridable="yes">Committe IIS Metabase Transaktion</String> | ||
| 48 | <String Id="WriteMetabaseChanges" Overridable="yes">Installiere Metabase Keys und Values</String> | ||
| 49 | |||
| 50 | <String Id="ConfigureIIs7Exec" Overridable="yes">Konfiguriere IIS</String> | ||
| 51 | <String Id="StartIIS7ConfigTransaction" Overridable="yes">Starte IIS Konfigurationstransaktion</String> | ||
| 52 | <String Id="RollbackIIS7ConfigTransaction" Overridable="yes">Mache IIS Konfigurationstransaktion rückgängig</String> | ||
| 53 | <String Id="CommitIIS7ConfigTransaction" Overridable="yes">Committe IIS Konfigurationstransaktion</String> | ||
| 54 | <String Id="WriteIIS7ConfigChanges" Overridable="yes">Installiere Konfigurationskeys and -values</String> | ||
| 55 | </WixLocalization> | ||
diff --git a/src/ext/Iis/wixlib/en-us.wxl b/src/ext/Iis/wixlib/en-us.wxl new file mode 100644 index 00000000..44949095 --- /dev/null +++ b/src/ext/Iis/wixlib/en-us.wxl | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrIISCannotConnect" Overridable="yes">Cannot connect to Internet Information Server. ([2] [3] [4] [5])</String> | ||
| 6 | <String Id="msierrIISFailedReadWebSite" Overridable="yes">Failed while processing WebSites. ([2] [3] [4] [5])</String> | ||
| 7 | <String Id="msierrIISFailedReadWebDirs" Overridable="yes">Failed while processing WebDirs. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrIISFailedReadVDirs" Overridable="yes">Failed while processing WebVirtualDirs. ([2] [3] [4] [5])</String> | ||
| 9 | <String Id="msierrIISFailedReadFilters" Overridable="yes">Failed while processing WebFilters. ([2] [3] [4] [5])</String> | ||
| 10 | <String Id="msierrIISFailedReadMimeMap" Overridable="yes">Failed while processing MimeMaps. ([2] [3] [4] [5])</String> | ||
| 11 | <String Id="msierrIISFailedReadAppPool" Overridable="yes">Failed while processing WebAppPools. ([2] [3] [4] [5])</String> | ||
| 12 | <String Id="msierrIISFailedReadProp" Overridable="yes">Failed while processing WebProperties. ([2] [3] [4] [5])</String> | ||
| 13 | <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">Failed while processing WebServiceExtensions. ([2] [3] [4] [5])</String> | ||
| 14 | <String Id="msierrIISFailedReadWebError" Overridable="yes">Failed while processing WebErrors. ([2] [3] [4] [5])</String> | ||
| 15 | <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">Failed while processing HttpHeaders. ([2] [3] [4] [5])</String> | ||
| 16 | |||
| 17 | <String Id="msierrIISFailedSchedTransaction" Overridable="yes">Failed to schedule transaction for changes to IIS. ([2] [3] [4] [5])</String> | ||
| 18 | <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">Failed to schedule install of IIS Web Sites. ([2] [3] [4] [5])</String> | ||
| 19 | <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">Failed to schedule install of IIS Web Directories. ([2] [3] [4] [5])</String> | ||
| 20 | <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">Failed to schedule install of IIS Virtual Directories. ([2] [3] [4] [5])</String> | ||
| 21 | <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">Failed to schedule install of IIS Filters. ([2] [3] [4] [5])</String> | ||
| 22 | <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">Failed to schedule install of IIS AppPools. ([2] [3] [4] [5])</String> | ||
| 23 | <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">Failed to schedule install of IIS Properties. ([2] [3] [4] [5])</String> | ||
| 24 | <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">Failed to schedule install of IIS Web Service Extensions. ([2] [3] [4] [5])</String> | ||
| 25 | |||
| 26 | <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">Failed to schedule uninstall of IIS Web Sites. ([2] [3] [4] [5])</String> | ||
| 27 | <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">Failed to schedule uninstall of IIS Web Directories. ([2] [3] [4] [5])</String> | ||
| 28 | <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">Failed to schedule uninstall of IIS Virtual Directories. ([2] [3] [4] [5])</String> | ||
| 29 | <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">Failed to schedule uninstall of IIS Filters. ([2] [3] [4] [5])</String> | ||
| 30 | <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">Failed to schedule uninstall of IIS AppPools. ([2] [3] [4] [5])</String> | ||
| 31 | <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">Failed to schedule uninstall of IIS Properties. ([2] [3] [4] [5])</String> | ||
| 32 | <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">Failed to schedule uninstall of IIS Web Service Extensions. ([2] [3] [4] [5])</String> | ||
| 33 | |||
| 34 | <String Id="msierrIISFailedStartTransaction" Overridable="yes">Failed to start IIS transaction. ([2] [3] [4] [5])</String> | ||
| 35 | <String Id="msierrIISFailedOpenKey" Overridable="yes">Failed to open metabase key. ([2] [3] [4] [5])</String> | ||
| 36 | <String Id="msierrIISFailedCreateKey" Overridable="yes">Failed to create metabase key. ([2] [3] [4] [5])</String> | ||
| 37 | <String Id="msierrIISFailedWriteData" Overridable="yes">Failed to write data to metabase key. ([2] [3] [4] [5])</String> | ||
| 38 | <String Id="msierrIISFailedCreateApp" Overridable="yes">Failed to create web application. ([2] [3] [4] [5])</String> | ||
| 39 | <String Id="msierrIISFailedDeleteKey" Overridable="yes">Failed to delete metabase key. ([2] [3] [4] [5])</String> | ||
| 40 | <String Id="msierrIISFailedDeleteValue" Overridable="yes">Failed to delete metabase value. ([2] [3] [4] [5])</String> | ||
| 41 | <String Id="msierrIISFailedCommitInUse" Overridable="yes">Failed to commit IIS transaction due to a sharing violation. Some other application may be configuring IIS.</String> | ||
| 42 | |||
| 43 | <String Id="ConfigureIIs" Overridable="yes">Configuring IIS</String> | ||
| 44 | <String Id="ConfigureIIsExec" Overridable="yes">Executing IIS Configuration</String> | ||
| 45 | <String Id="StartMetabaseTransaction" Overridable="yes">Starting IIS Metabase Transaction</String> | ||
| 46 | <String Id="RollbackMetabaseTransaction" Overridable="yes">Rolling back IIS Metabase Transaction</String> | ||
| 47 | <String Id="CommitMetabaseTransaction" Overridable="yes">Committing IIS Metabase Transaction</String> | ||
| 48 | <String Id="WriteMetabaseChanges" Overridable="yes">Installing Metabase Keys and Values</String> | ||
| 49 | |||
| 50 | <String Id="ConfigureIIs7Exec" Overridable="yes">Configuring IIS</String> | ||
| 51 | <String Id="StartIIS7ConfigTransaction" Overridable="yes">Starting IIS Config Transaction</String> | ||
| 52 | <String Id="RollbackIIS7ConfigTransaction" Overridable="yes">Rolling back IIS Config Transaction</String> | ||
| 53 | <String Id="CommitIIS7ConfigTransaction" Overridable="yes">Committing IIS Config Transaction</String> | ||
| 54 | <String Id="WriteIIS7ConfigChanges" Overridable="yes">Installing Config Keys and Values</String> | ||
| 55 | </WixLocalization> | ||
diff --git a/src/ext/Iis/wixlib/iis.v3.ncrunchproject b/src/ext/Iis/wixlib/iis.v3.ncrunchproject new file mode 100644 index 00000000..319cd523 --- /dev/null +++ b/src/ext/Iis/wixlib/iis.v3.ncrunchproject | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | <ProjectConfiguration> | ||
| 2 | <Settings> | ||
| 3 | <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely> | ||
| 4 | </Settings> | ||
| 5 | </ProjectConfiguration> \ No newline at end of file | ||
diff --git a/src/ext/Iis/wixlib/iis.wixproj b/src/ext/Iis/wixlib/iis.wixproj new file mode 100644 index 00000000..89f9608f --- /dev/null +++ b/src/ext/Iis/wixlib/iis.wixproj | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | <Project Sdk="WixToolset.Sdk"> | ||
| 3 | |||
| 4 | <PropertyGroup> | ||
| 5 | <OutputType>Library</OutputType> | ||
| 6 | <BindFiles>true</BindFiles> | ||
| 7 | <Cultures>en-us</Cultures> | ||
| 8 | </PropertyGroup> | ||
| 9 | |||
| 10 | <ItemGroup> | ||
| 11 | <BindInputPaths Include="$(OutputPath)x86" BindName='x86' /> | ||
| 12 | <BindInputPaths Include="$(OutputPath)x64" BindName='x64' /> | ||
| 13 | <BindInputPaths Include="$(OutputPath)arm64" BindName='arm64' /> | ||
| 14 | </ItemGroup> | ||
| 15 | |||
| 16 | <ItemGroup> | ||
| 17 | <ProjectReference Include="..\ca\iisca.vcxproj" Properties="Platform=ARM64" /> | ||
| 18 | <ProjectReference Include="..\ca\iisca.vcxproj" Properties="Platform=x86" /> | ||
| 19 | <ProjectReference Include="..\ca\iisca.vcxproj" Properties="Platform=x64" /> | ||
| 20 | </ItemGroup> | ||
| 21 | |||
| 22 | <ItemGroup> | ||
| 23 | <PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="All" /> | ||
| 24 | </ItemGroup> | ||
| 25 | |||
| 26 | </Project> | ||
diff --git a/src/ext/Iis/wixlib/ja-jp.wxl b/src/ext/Iis/wixlib/ja-jp.wxl new file mode 100644 index 00000000..7fd6978a --- /dev/null +++ b/src/ext/Iis/wixlib/ja-jp.wxl | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="ja-jp" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrIISCannotConnect" Overridable="yes">IISへ接続できません。 ([2] [3] [4] [5])</String> | ||
| 6 | <String Id="msierrIISFailedReadWebSite" Overridable="yes">ウェブ サイト処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 7 | <String Id="msierrIISFailedReadWebDirs" Overridable="yes">ウェブ ディレクトリ処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrIISFailedReadVDirs" Overridable="yes">ウェブ仮想ディレクトリ処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 9 | <String Id="msierrIISFailedReadFilters" Overridable="yes">ウェブ フィルタ処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 10 | <String Id="msierrIISFailedReadMimeMap" Overridable="yes">MIME マップ処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 11 | <String Id="msierrIISFailedReadAppPool" Overridable="yes">ウェブ アプリケーション プール処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 12 | <String Id="msierrIISFailedReadProp" Overridable="yes">ウェブ プロパティ処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 13 | <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">ウェブ サービス拡張処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 14 | <String Id="msierrIISFailedReadWebError" Overridable="yes">ウェブ エラー処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 15 | <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">HTTP ヘッダ処理中に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 16 | |||
| 17 | <String Id="msierrIISFailedSchedTransaction" Overridable="yes">IIS 変更トランザクションのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 18 | <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">IIS ウェブ サイト インストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 19 | <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">IIS ウェブ ディレクトリ インストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 20 | <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">IIS 仮想ディレクトリ インストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 21 | <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">IIS フィルタ インストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 22 | <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">IIS アプリケーション プール インストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 23 | <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">IIS プロパティ インストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 24 | <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">IIS ウェブ サービス拡張インストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 25 | |||
| 26 | <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">IISウェブ サイト アンインストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 27 | <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">IIS ウェブ ディレクトリ アンインストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 28 | <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">IIS 仮想ディレクトリ アンインストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 29 | <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">IIS フィルタ アンインストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 30 | <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">IIS アプリケーション プール アンインストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 31 | <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">IIS プロパティ アンインストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 32 | <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">IIS ウェブ サービス拡張アンインストールのスケジューリングに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 33 | |||
| 34 | <String Id="msierrIISFailedStartTransaction" Overridable="yes">IIS トランザクション開始に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 35 | <String Id="msierrIISFailedOpenKey" Overridable="yes">メタベース キーのオープンに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 36 | <String Id="msierrIISFailedCreateKey" Overridable="yes">メタベース キーの作成に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 37 | <String Id="msierrIISFailedWriteData" Overridable="yes">メタベース キーの書き込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 38 | <String Id="msierrIISFailedCreateApp" Overridable="yes">ウェブ アプリケーションの作成に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 39 | <String Id="msierrIISFailedDeleteKey" Overridable="yes">メタベース キーの削除に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 40 | <String Id="msierrIISFailedDeleteValue" Overridable="yes">メタベース値の削除に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 41 | |||
| 42 | <String Id="ConfigureIIs" Overridable="yes">IIS を構成しています</String> | ||
| 43 | <String Id="StartMetabaseTransaction" Overridable="yes">IIS メタベース トランザクションを開始しています</String> | ||
| 44 | <String Id="RollbackMetabaseTransaction" Overridable="yes">IIS メタベース トランザクションをロールバックしています</String> | ||
| 45 | <String Id="CommitMetabaseTransaction" Overridable="yes">IIS メタベース トランザクションを確定しています</String> | ||
| 46 | <String Id="WriteMetabaseChanges" Overridable="yes">IIS メタベース キーと値をインストールしています</String> | ||
| 47 | </WixLocalization> | ||
diff --git a/src/ext/Iis/wixlib/pt-br.wxl b/src/ext/Iis/wixlib/pt-br.wxl new file mode 100644 index 00000000..1fc0d768 --- /dev/null +++ b/src/ext/Iis/wixlib/pt-br.wxl | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="pt-br" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrIISCannotConnect" Overridable="yes">Não foi possível conectar no Internet Information Server. ([2] [3] [4] [5])</String> | ||
| 6 | <String Id="msierrIISFailedReadWebSite" Overridable="yes">Erro ao processar WebSites. ([2] [3] [4] [5])</String> | ||
| 7 | <String Id="msierrIISFailedReadWebDirs" Overridable="yes">Erro ao processar WebDirs. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrIISFailedReadVDirs" Overridable="yes">Erro ao processar WebVirtualDirs. ([2] [3] [4] [5])</String> | ||
| 9 | <String Id="msierrIISFailedReadFilters" Overridable="yes">Erro ao processar WebFilters. ([2] [3] [4] [5])</String> | ||
| 10 | <String Id="msierrIISFailedReadMimeMap" Overridable="yes">Erro ao processar MimeMaps. ([2] [3] [4] [5])</String> | ||
| 11 | <String Id="msierrIISFailedReadAppPool" Overridable="yes">Erro ao processar WebAppPools. ([2] [3] [4] [5])</String> | ||
| 12 | <String Id="msierrIISFailedReadProp" Overridable="yes">Erro ao processar WebProperties. ([2] [3] [4] [5])</String> | ||
| 13 | <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">Erro ao processar WebServiceExtensions. ([2] [3] [4] [5])</String> | ||
| 14 | <String Id="msierrIISFailedReadWebError" Overridable="yes">Erro ao processar WebErrors. ([2] [3] [4] [5])</String> | ||
| 15 | <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">Erro ao processar HttpHeaders. ([2] [3] [4] [5])</String> | ||
| 16 | <String Id="msierrIISFailedSchedTransaction" Overridable="yes">Erro ao agendar transação para alterações no IIS. ([2] [3] [4] [5])</String> | ||
| 17 | <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">Erro ao agendar instalação de IIS Web Sites. ([2] [3] [4] [5])</String> | ||
| 18 | <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">Erro ao agendar instalação de IIS Web Directories. ([2] [3] [4] [5])</String> | ||
| 19 | <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">Erro ao agendar instalação de IIS Virtual Directories. ([2] [3] [4] [5])</String> | ||
| 20 | <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">Erro ao agendar instalação de IIS Filters. ([2] [3] [4] [5])</String> | ||
| 21 | <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">Erro ao agendar instalação de IIS AppPools. ([2] [3] [4] [5])</String> | ||
| 22 | <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">Erro ao agendar instalação de IIS Properties. ([2] [3] [4] [5])</String> | ||
| 23 | <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">Erro ao agendar instalação de IIS Web Service Extensions. ([2] [3] [4] [5])</String> | ||
| 24 | <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">Erro ao agendar desinstalação de IIS Web Sites. ([2] [3] [4] [5])</String> | ||
| 25 | <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">Erro ao agendar desinstalação de IIS Web Directories. ([2] [3] [4] [5])</String> | ||
| 26 | <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">Erro ao agendar desinstalação de IIS Virtual Directories. ([2] [3] [4] [5])</String> | ||
| 27 | <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">Erro ao agendar desinstalação de IIS Filters. ([2] [3] [4] [5])</String> | ||
| 28 | <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">Erro ao agendar desinstalação de IIS AppPools. ([2] [3] [4] [5])</String> | ||
| 29 | <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">Erro ao agendar desinstalação de IIS Properties. ([2] [3] [4] [5])</String> | ||
| 30 | <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">Erro ao agendar desinstalação de IIS Web Service Extensions. ([2] [3] [4] [5])</String> | ||
| 31 | <String Id="msierrIISFailedStartTransaction" Overridable="yes">Erro ao iniciar transação do IIS . ([2] [3] [4] [5])</String> | ||
| 32 | <String Id="msierrIISFailedOpenKey" Overridable="yes">Erro ao abrir metabase key. ([2] [3] [4] [5])</String> | ||
| 33 | <String Id="msierrIISFailedCreateKey" Overridable="yes">Erro ao criar metabase key. ([2] [3] [4] [5])</String> | ||
| 34 | <String Id="msierrIISFailedWriteData" Overridable="yes">Erro ao escrever dados na metabase key. ([2] [3] [4] [5])</String> | ||
| 35 | <String Id="msierrIISFailedCreateApp" Overridable="yes">Erro ao criar aplicação Web. ([2] [3] [4] [5])</String> | ||
| 36 | <String Id="msierrIISFailedDeleteKey" Overridable="yes">Erro ao excluir metabase key. ([2] [3] [4] [5])</String> | ||
| 37 | <String Id="msierrIISFailedDeleteValue" Overridable="yes">Erro ao excluir valor da metabase. ([2] [3] [4] [5])</String> | ||
| 38 | <String Id="msierrIISFailedCommitInUse" Overridable="yes">Erro ao fazer commit de transação IIS por violação de compartilhamento. Alguma outra aplicação pode estar tentando configurar o ISS ao mesmo tempo.</String> | ||
| 39 | <String Id="ConfigureIIs" Overridable="yes">Configurando IIS</String> | ||
| 40 | <String Id="ConfigureIIsExec" Overridable="yes">Executando Configurações do IIS</String> | ||
| 41 | <String Id="StartMetabaseTransaction" Overridable="yes">Iniciando Transação de Metabase do IIS</String> | ||
| 42 | <String Id="RollbackMetabaseTransaction" Overridable="yes">Cancelando Transação de Metabase do IIS</String> | ||
| 43 | <String Id="CommitMetabaseTransaction" Overridable="yes">Efetivando Transação de Metabase do IIS</String> | ||
| 44 | <String Id="WriteMetabaseChanges" Overridable="yes">Instalando Chaves e Valores de Metabase do IIS</String> | ||
| 45 | <String Id="ConfigureIIs7Exec" Overridable="yes">Configurando IIS</String> | ||
| 46 | <String Id="StartIIS7ConfigTransaction" Overridable="yes">Iniciando Transação de Configuração do IIS</String> | ||
| 47 | <String Id="RollbackIIS7ConfigTransaction" Overridable="yes">Cancelando Transação de Configuração do IIS</String> | ||
| 48 | <String Id="CommitIIS7ConfigTransaction" Overridable="yes">Efetivando Transação de Configuração do IIS</String> | ||
| 49 | <String Id="WriteIIS7ConfigChanges" Overridable="yes">Instalando Chaves e Valores de Configurações do IIS</String> | ||
| 50 | </WixLocalization> | ||
