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/ext | |
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/ext')
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> | ||